action/base.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_ACTION_BASE_HPP_INCLUDED
5 #define LEXY_ACTION_BASE_HPP_INCLUDED
6 
10 #include <lexy/callback/noop.hpp>
11 #include <lexy/dsl/base.hpp>
12 #include <lexy/grammar.hpp>
13 
14 //=== parse_context ===//
15 namespace lexy
16 {
17 namespace _detail
18 {
20  {
21  const void* id;
23 
24  constexpr parse_context_var_base(const void* id) : id(id), next(nullptr) {}
25 
26  template <typename Context>
27  constexpr void link(Context& context)
28  {
29  auto cb = context.control_block;
30  next = cb->vars;
31  cb->vars = this;
32  }
33 
34  template <typename Context>
35  constexpr void unlink(Context& context)
36  {
37  auto cb = context.control_block;
38  cb->vars = next;
39  }
40  };
41 
42  template <typename Id, typename T>
44  {
45  static constexpr auto type_id = lexy::_detail::type_id<Id>();
46 
47  T value;
48 
49  explicit constexpr parse_context_var(T&& value)
51  {}
52 
53  template <typename ControlBlock>
54  static constexpr T& get(const ControlBlock* cb)
55  {
56  for (auto cur = cb->vars; cur; cur = cur->next)
57  if (cur->id == &type_id)
58  return static_cast<parse_context_var*>(cur)->value;
59 
60  LEXY_ASSERT(false, "context variable hasn't been created");
61  return static_cast<parse_context_var*>(cb->vars)->value;
62  }
63  };
64 
65  template <typename Handler, typename State = void>
67  {
68  using handler_type = Handler;
69  using state_type = State;
70 
72  State* parse_state;
73 
75 
78 
79  constexpr parse_context_control_block(Handler&& handler, State* state,
80  std::size_t max_depth)
81  : parse_handler(LEXY_MOV(handler)), parse_state(state), //
82  vars(nullptr), //
83  cur_depth(0), max_depth(static_cast<int>(max_depth)), enable_whitespace_skipping(true)
84  {}
85 
86  template <typename OtherHandler>
87  constexpr parse_context_control_block(Handler&& handler,
89  : parse_handler(LEXY_MOV(handler)), parse_state(cb->parse_state), //
92  {}
93 
94  template <typename OtherHandler>
96  {
97  vars = cb->vars;
98  cur_depth = cb->cur_depth;
99  max_depth = cb->max_depth;
101  }
102  };
103 } // namespace _detail
104 
105 // If a production doesn't define whitespace, we don't need to pass it and can shorten the template
106 // name.
107 template <typename Production>
109  = std::conditional_t<_production_defines_whitespace<Production>, Production, void>;
110 
111 template <typename Handler, typename State, typename Production>
113  typename Handler::template value_callback<Production, State>::return_type;
114 
115 template <typename Handler, typename State, typename Production,
116  typename WhitespaceProduction = _whitespace_production_of<Production>>
117 struct _pc
118 {
119  using handler_type = Handler;
120  using state_type = State;
121 
122  using production = Production;
123  using whitespace_production = WhitespaceProduction;
125 
126  typename Handler::event_handler handler;
129 
131  : handler(Production{}), control_block(cb)
132  {}
133 
134  template <typename ChildProduction>
135  constexpr auto sub_context(ChildProduction)
136  {
137  // Update the whitespace production if necessary.
138  // If the current production is a token or defines whitespace,
139  // we change it to the current production (or void), otherwise keep it.
140  using new_whitespace_production
141  = std::conditional_t<is_token_production<ChildProduction> //
142  || _production_defines_whitespace<ChildProduction>,
143  _whitespace_production_of<ChildProduction>, WhitespaceProduction>;
145  }
146 
147  constexpr auto value_callback()
148  {
149  using callback = typename Handler::template value_callback<Production, State>;
150  return callback(control_block->parse_state);
151  }
152 
153  template <typename Event, typename... Args>
154  constexpr auto on(Event ev, Args&&... args)
155  {
156  return handler.on(control_block->parse_handler, ev, LEXY_FWD(args)...);
157  }
158 };
159 } // namespace lexy
160 
161 //=== do_action ===//
162 namespace lexy::_detail
163 {
165 {
166  template <typename Context, typename Reader, typename... Args>
167  LEXY_PARSER_FUNC static bool parse(Context& context, Reader&, Args&&... args)
168  {
169  context.value.emplace_result(context.value_callback(), LEXY_FWD(args)...);
170  return true;
171  }
172 };
173 
174 template <typename NextParser>
176 {
177  template <typename Context, typename Reader, typename SubContext, typename... Args>
178  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, SubContext& sub_context,
179  Args&&... args)
180  {
181  // Might need to skip whitespace, according to the original context.
182  using continuation
183  = std::conditional_t<lexy::is_token_production<typename SubContext::production>,
185 
186  // Pass the produced value to the next parser.
187  if constexpr (std::is_void_v<typename SubContext::value_type>)
188  return continuation::parse(context, reader, LEXY_FWD(args)...);
189  else
190  return continuation::parse(context, reader, LEXY_FWD(args)...,
191  LEXY_MOV(*sub_context.value));
192  }
193 };
194 } // namespace lexy::_detail
195 
196 namespace lexy
197 {
198 constexpr void* no_parse_state = nullptr;
199 
200 template <typename Handler, typename State, typename Production, typename Reader>
201 constexpr auto _do_action(_pc<Handler, State, Production>& context, Reader& reader)
202 {
203  context.on(parse_events::grammar_start{}, reader.position());
204  context.on(parse_events::production_start{}, reader.position());
205 
206  // We parse whitespace, theen the rule, then finish.
207  using parser = lexy::whitespace_parser<
208  LEXY_DECAY_DECLTYPE(context),
210  auto rule_result = parser::parse(context, reader);
211 
212  if (rule_result)
213  {
214  context.on(parse_events::production_finish{}, reader.position());
215  context.on(parse_events::grammar_finish{}, reader);
216  }
217  else
218  {
219  context.on(parse_events::production_cancel{}, reader.position());
220  context.on(parse_events::grammar_cancel{}, reader);
221  }
222 
223  return rule_result;
224 }
225 
226 template <typename Production, template <typename> typename Result, typename Handler,
227  typename State, typename Reader>
228 constexpr auto do_action(Handler&& handler, State* state, Reader& reader)
229 {
230  static_assert(!std::is_reference_v<Handler>, "need to move handler in");
231 
232  _detail::parse_context_control_block control_block(LEXY_MOV(handler), state,
233  max_recursion_depth<Production>());
234  _pc<Handler, State, Production> context(&control_block);
235 
236  auto rule_result = _do_action(context, reader);
237 
238  using value_type = typename decltype(context)::value_type;
239  if constexpr (std::is_void_v<value_type>)
240  return LEXY_MOV(control_block.parse_handler).template get_result<Result<void>>(rule_result);
241  else if (context.value)
242  return LEXY_MOV(control_block.parse_handler)
243  .template get_result<Result<value_type>>(rule_result, LEXY_MOV(*context.value));
244  else
245  return LEXY_MOV(control_block.parse_handler)
246  .template get_result<Result<value_type>>(rule_result);
247 }
248 } // namespace lexy
249 
250 //=== value callback ===//
251 namespace lexy::_detail
252 {
254 {
255  constexpr void_value_callback() = default;
256  template <typename State>
257  constexpr explicit void_value_callback(State*)
258  {}
259 
260  using return_type = void;
261 
262  constexpr auto sink() const
263  {
264  return lexy::noop.sink();
265  }
266 
267  template <typename... Args>
268  constexpr void operator()(Args&&...) const
269  {}
270 };
271 } // namespace lexy::_detail
272 
273 #endif // LEXY_ACTION_BASE_HPP_INCLUDED
274 
LEXY_MOV
#define LEXY_MOV(...)
Definition: config.hpp:29
lexy::parse_events::production_finish
Definition: dsl/base.hpp:34
lexy::_detail::parse_context_control_block::copy_vars_from
constexpr void copy_vars_from(parse_context_control_block< OtherHandler, State > *cb)
Definition: action/base.hpp:95
lexy::noop
constexpr auto noop
A callback with sink that does nothing.
Definition: noop.hpp:30
config.hpp
lexy::_detail::parse_context_control_block< lexy::_vh, State >::state_type
State state_type
Definition: action/base.hpp:69
lexy::_detail::parse_context_var::parse_context_var
constexpr parse_context_var(T &&value)
Definition: action/base.hpp:49
lexy::_detail::parse_context_control_block::cur_depth
int cur_depth
Definition: action/base.hpp:76
lexy::_detail::context_finish_parser
Definition: action/base.hpp:175
lexy::_detail::parse_context_var::get
static constexpr T & get(const ControlBlock *cb)
Definition: action/base.hpp:54
lexy::_scp
Definition: action/scan.hpp:14
noop.hpp
lexy::_vh
Definition: validate.hpp:167
lexy::parse_events::grammar_finish
Definition: dsl/base.hpp:21
lexy::no_parse_state
constexpr void * no_parse_state
Definition: action/base.hpp:198
LEXY_FWD
#define LEXY_FWD(...)
Definition: config.hpp:30
lexy::_detail::parse_context_control_block::parse_context_control_block
constexpr parse_context_control_block(Handler &&handler, State *state, std::size_t max_depth)
Definition: action/base.hpp:79
lexy::_detail::parse_context_var_base::next
parse_context_var_base * next
Definition: action/base.hpp:22
lexy::_detail::parse_context_var_base::id
const void * id
Definition: action/base.hpp:21
lexy::_whitespace_production_of
std::conditional_t< _production_defines_whitespace< Production >, Production, void > _whitespace_production_of
Definition: action/base.hpp:109
lexy::_pc::control_block
_detail::parse_context_control_block< Handler, State > * control_block
Definition: action/base.hpp:127
lexy::_pc::sub_context
constexpr auto sub_context(ChildProduction)
Definition: action/base.hpp:135
lexy
Definition: any_ref.hpp:12
lexy::_detail::void_value_callback::void_value_callback
constexpr void_value_callback(State *)
Definition: action/base.hpp:257
detail::void
j template void())
Definition: json.hpp:4893
grammar.hpp
lexy::_detail::void_value_callback::return_type
void return_type
Definition: action/base.hpp:260
lexy::_pc< lexy::_vh, State, lexy::_scp >::whitespace_production
_whitespace_production_of< lexy::_scp > whitespace_production
Definition: action/base.hpp:123
lexy::callback
constexpr auto callback(Fns &&... fns)
Creates a callback.
Definition: adapter.hpp:48
lexy::_detail::parse_context_control_block
Definition: action/base.hpp:66
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::_pc::value_callback
constexpr auto value_callback()
Definition: action/base.hpp:147
lexy::_detail::parse_context_control_block::enable_whitespace_skipping
bool enable_whitespace_skipping
Definition: action/base.hpp:77
lexy::_pc< lexy::_vh, State, lexy::_scp >::value_type
_production_value_type< lexy::_vh, State, lexy::_scp > value_type
Definition: action/base.hpp:124
lexy::_detail::lazy_init< value_type >
lexy::_detail::void_value_callback::operator()
constexpr void operator()(Args &&...) const
Definition: action/base.hpp:268
lexy::_detail::void_value_callback::sink
constexpr auto sink() const
Definition: action/base.hpp:262
lexy::_detail::parse_context_var_base::link
constexpr void link(Context &context)
Definition: action/base.hpp:27
LEXY_DECAY_DECLTYPE
#define LEXY_DECAY_DECLTYPE(...)
Definition: config.hpp:34
lexy::_production_value_type
typename Handler::template value_callback< Production, State >::return_type _production_value_type
Definition: action/base.hpp:113
lexy::parse_events::grammar_start
Definition: dsl/base.hpp:17
lexy::_detail::parse_context_var_base::parse_context_var_base
constexpr parse_context_var_base(const void *id)
Definition: action/base.hpp:24
lexy::parse_events::production_start
Definition: dsl/base.hpp:30
lexy::_detail::final_parser::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &, Args &&... args)
Definition: action/base.hpp:167
lexy::_detail::parse_context_control_block::vars
parse_context_var_base * vars
Definition: action/base.hpp:74
lexy::_detail::parse_context_var
Definition: action/base.hpp:43
lexy::_pc::_pc
constexpr _pc(_detail::parse_context_control_block< Handler, State > *cb)
Definition: action/base.hpp:130
LEXY_PARSER_FUNC
#define LEXY_PARSER_FUNC
Definition: dsl/base.hpp:108
lexy::_detail::parse_context_var_base
Definition: action/base.hpp:19
lexy::_detail::parse_context_control_block::parse_handler
LEXY_EMPTY_MEMBER Handler parse_handler
Definition: action/base.hpp:71
lexy::whitespace_parser
Definition: dsl/base.hpp:229
lexy::_pc::on
constexpr auto on(Event ev, Args &&... args)
Definition: action/base.hpp:154
lexy::_pc< lexy::_vh, State, lexy::_scp >::state_type
State state_type
Definition: action/base.hpp:120
base.hpp
lexy::_pc::handler
Handler::event_handler handler
Definition: action/base.hpp:126
lexy::_detail
Definition: any_ref.hpp:12
lexy::_detail::void_value_callback
Definition: action/base.hpp:253
lexy::parse_events::production_cancel
Definition: dsl/base.hpp:38
lexy::_detail::parse_context_var::type_id
static constexpr auto type_id
Definition: action/base.hpp:45
lexy::_detail::parse_context_control_block::max_depth
int max_depth
Definition: action/base.hpp:76
lexy::_detail::final_parser
Definition: action/base.hpp:164
lexy::parser_for
typename Rule::template p< NextParser > parser_for
Definition: dsl/base.hpp:113
lexy::_detail::parse_context_var::value
T value
Definition: action/base.hpp:47
lexy::_detail::context_finish_parser::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, SubContext &sub_context, Args &&... args)
Definition: action/base.hpp:178
BT::Result
Expected< std::monostate > Result
Definition: basic_types.h:333
lexy::_detail::void_value_callback::void_value_callback
constexpr void_value_callback()=default
lexy::_detail::parse_context_control_block::parse_context_control_block
constexpr parse_context_control_block(Handler &&handler, parse_context_control_block< OtherHandler, State > *cb)
Definition: action/base.hpp:87
LEXY_EMPTY_MEMBER
#define LEXY_EMPTY_MEMBER
Definition: config.hpp:193
lexy::_do_action
constexpr auto _do_action(_pc< Handler, State, Production > &context, Reader &reader)
Definition: action/base.hpp:201
type_name.hpp
lexy::_pc::value
_detail::lazy_init< value_type > value
Definition: action/base.hpp:128
lexy::_detail::parse_context_var_base::unlink
constexpr void unlink(Context &context)
Definition: action/base.hpp:35
lexy::parse_events::grammar_cancel
Definition: dsl/base.hpp:25
lexy::do_action
constexpr auto do_action(Handler &&handler, State *state, Reader &reader)
Definition: action/base.hpp:228
LEXY_ASSERT
#define LEXY_ASSERT(Expr, Msg)
Definition: assert.hpp:37
lazy_init.hpp
lexy::_detail::parse_context_control_block::parse_state
State * parse_state
Definition: action/base.hpp:72
lexy::_pc
Definition: action/base.hpp:117


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