parse_as.hpp
Go to the documentation of this file.
1 // Copyright (C) 2020-2024 Jonathan Müller and lexy contributors
2 // SPDX-License-Identifier: BSL-1.0
3 
4 #ifndef LEXY_DSL_PARSE_AS_HPP_INCLUDED
5 #define LEXY_DSL_PARSE_AS_HPP_INCLUDED
6 
7 #include <lexy/action/base.hpp>
9 #include <lexy/dsl/base.hpp>
10 
11 namespace lexyd
12 {
13 // Custom handler that forwards events but overrides the value callback.
14 template <typename Handler>
16 {
17  Handler& _handler;
18 
19  using event_handler = typename Handler::event_handler;
20 
21  // We are implicitly convertible to all handler types the original handler is convertible to.
22  // This is because the handler is passed to event_handler::on.
23  template <typename H, typename = decltype(static_cast<H&>(LEXY_DECLVAL(Handler&)))>
24  constexpr operator H&() const
25  {
26  return static_cast<H&>(_handler);
27  }
28 
29  // We use ::value to get a value.
30  // We can't use it unconditionally, as the initial production that contains the parse_as might
31  // not have one. So we silently fallback if that's the case - this might cause worse errors if
32  // the value is missing.
33  template <typename Production, typename State>
34  using value_callback
35  = std::conditional_t<lexy::production_has_value_callback<Production, State>,
38 };
39 
41 {
42  template <typename Context, typename Reader, typename T, typename... Args>
43  LEXY_PARSER_FUNC static bool parse(Context&, Reader&, lexy::_detail::lazy_init<T>& value,
44  Args&&... args)
45  {
46  value.emplace_result(lexy::construct<T>, LEXY_FWD(args)...);
47  return true;
48  }
49 };
50 
51 template <typename Handler>
52 constexpr auto _make_pas_handler(Handler& handler)
53 {
54  return _pas_handler<Handler>{handler};
55 }
56 // Prevent infinite nesting when parse_as itself is recursive.
57 template <typename Handler>
58 constexpr auto _make_pas_handler(_pas_handler<Handler>& handler)
59 {
60  return handler;
61 }
62 
63 template <typename T, typename Rule, bool Front = false>
64 struct _pas : _copy_base<Rule>
65 {
66  template <typename Reader>
67  struct bp
68  {
70 
71  template <typename ControlBlock>
72  constexpr bool try_parse(const ControlBlock* cb, const Reader& reader)
73  {
74  return rule_parser.try_parse(cb, reader);
75  }
76 
77  template <typename Context>
78  constexpr void cancel(Context& context)
79  {
80  // No need to use the special context here; it doesn't produce any values.
81  rule_parser.cancel(context);
82  }
83 
84  template <typename NextParser, typename Context, typename... Args>
85  LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args)
86  {
87  auto handler = _make_pas_handler(context.control_block->parse_handler);
88  lexy::_detail::parse_context_control_block cb(LEXY_MOV(handler), context.control_block);
89  using context_type
90  = lexy::_pc<decltype(handler), typename Context::state_type,
91  typename Context::production, typename Context::whitespace_production>;
92  context_type sub_context(&cb);
93  sub_context.handler = LEXY_MOV(context).handler;
94 
96  auto result
97  = rule_parser.template finish<_pas_final_parser>(sub_context, reader, value);
98 
99  context.control_block->copy_vars_from(&cb);
100  context.handler = LEXY_MOV(sub_context).handler;
101 
102  if (!result)
103  return false;
104  else if constexpr (std::is_void_v<T>)
105  // NOLINTNEXTLINE: clang-tidy wrongly thinks the branch is repeated.
106  return NextParser::parse(context, reader, LEXY_FWD(args)...);
107  else if constexpr (Front)
108  return NextParser::parse(context, reader, *LEXY_MOV(value), LEXY_FWD(args)...);
109  else
110  return NextParser::parse(context, reader, LEXY_FWD(args)..., *LEXY_MOV(value));
111  }
112  };
113 
114  template <typename NextParser>
115  struct p
116  {
117  template <typename Context, typename Reader, typename... Args>
118  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args)
119  {
120  auto handler = _make_pas_handler(context.control_block->parse_handler);
121  lexy::_detail::parse_context_control_block cb(LEXY_MOV(handler), context.control_block);
122  using context_type
123  = lexy::_pc<decltype(handler), typename Context::state_type,
124  typename Context::production, typename Context::whitespace_production>;
125  context_type sub_context(&cb);
126  sub_context.handler = LEXY_MOV(context).handler;
127 
129  auto result
130  = lexy::parser_for<Rule, _pas_final_parser>::parse(sub_context, reader, value);
131 
132  context.control_block->copy_vars_from(&cb);
133  context.handler = LEXY_MOV(sub_context).handler;
134 
135  if (!result)
136  return false;
137  else if constexpr (std::is_void_v<T>)
138  // NOLINTNEXTLINE: clang-tidy wrongly thinks the branch is repeated.
139  return NextParser::parse(context, reader, LEXY_FWD(args)...);
140  else if constexpr (Front)
141  return NextParser::parse(context, reader, *LEXY_MOV(value), LEXY_FWD(args)...);
142  else
143  return NextParser::parse(context, reader, LEXY_FWD(args)..., *LEXY_MOV(value));
144  }
145  };
146 };
147 
148 template <typename T, typename Rule>
149 constexpr auto parse_as(Rule)
150 {
151  return _pas<T, Rule>{};
152 }
153 } // namespace lexyd
154 
155 #endif // LEXY_DSL_PARSE_AS_HPP_INCLUDED
156 
LEXY_MOV
#define LEXY_MOV(...)
Definition: config.hpp:29
lexyd::_pas
Definition: parse_as.hpp:64
lexyd::_pas_handler::_handler
Handler & _handler
Definition: parse_as.hpp:17
lexy::branch_parser_for
typename BranchRule::template bp< Reader > branch_parser_for
Definition: dsl/base.hpp:116
LEXY_FWD
#define LEXY_FWD(...)
Definition: config.hpp:30
lexyd::parse_as
constexpr auto parse_as(Rule)
Definition: parse_as.hpp:149
lexy::_detail::parse_context_control_block
Definition: action/base.hpp:66
lexyd::_pas_handler::value_callback
std::conditional_t< lexy::production_has_value_callback< Production, State >, lexy::production_value_callback< Production, State >, lexy::_detail::void_value_callback > value_callback
Definition: parse_as.hpp:37
lexy::parse
constexpr auto parse(const Input &input, const ErrorCallback &callback)
Parses the production into a value, invoking the callback on error.
Definition: parse.hpp:171
lexy::production_value_callback
Definition: grammar.hpp:296
lexy::_detail::lazy_init
Definition: lazy_init.hpp:109
lexyd::_pas::bp
Definition: parse_as.hpp:67
lexyd::_pas_final_parser
Definition: parse_as.hpp:40
lexyd::_pas::bp::cancel
constexpr void cancel(Context &context)
Definition: parse_as.hpp:78
lexyd::_pas::p
Definition: parse_as.hpp:115
lexyd::_pas::p::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: parse_as.hpp:118
LEXY_PARSER_FUNC
#define LEXY_PARSER_FUNC
Definition: dsl/base.hpp:108
lexyd::_pas::bp::try_parse
constexpr bool try_parse(const ControlBlock *cb, const Reader &reader)
Definition: parse_as.hpp:72
base.hpp
lexy::_detail::void_value_callback
Definition: action/base.hpp:253
lexyd::_pas_handler
Definition: parse_as.hpp:15
lexyd::_pas_handler::event_handler
typename Handler::event_handler event_handler
Definition: parse_as.hpp:19
lexyd::_make_pas_handler
constexpr auto _make_pas_handler(Handler &handler)
Definition: parse_as.hpp:52
lexyd::_pas::bp::finish
LEXY_PARSER_FUNC bool finish(Context &context, Reader &reader, Args &&... args)
Definition: parse_as.hpp:85
lexyd::_pas_final_parser::parse
static LEXY_PARSER_FUNC bool parse(Context &, Reader &, lexy::_detail::lazy_init< T > &value, Args &&... args)
Definition: parse_as.hpp:43
base.hpp
lexyd::_pas::bp::rule_parser
lexy::branch_parser_for< Rule, Reader > rule_parser
Definition: parse_as.hpp:69
LEXY_DECLVAL
#define LEXY_DECLVAL(...)
Definition: config.hpp:32
object.hpp
lexyd
Definition: trace.hpp:22
lexy::_pc
Definition: action/base.hpp:117
lexyd::_copy_base
decltype(_copy_base_impl< Rule >()) _copy_base
Definition: dsl/base.hpp:104


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Dec 13 2024 03:19:17