production.hpp
Go to the documentation of this file.
1 // Copyright (C) 2020-2023 Jonathan Müller and lexy contributors
2 // SPDX-License-Identifier: BSL-1.0
3 
4 #ifndef LEXY_DSL_PRODUCTION_HPP_INCLUDED
5 #define LEXY_DSL_PRODUCTION_HPP_INCLUDED
6 
7 #include <lexy/action/base.hpp>
8 #include <lexy/dsl/base.hpp>
9 #include <lexy/dsl/branch.hpp>
10 #include <lexy/error.hpp>
11 
12 namespace lexyd
13 {
15 template <typename Production>
17 } // namespace lexyd
18 
19 namespace lexyd
20 {
21 template <typename Production, typename Context, typename Reader>
22 /* not force inline */ constexpr bool _parse_production(Context& context, Reader& reader)
23 {
25  return parser::parse(context, reader);
26 }
27 template <typename ProductionParser, typename Context, typename Reader>
28 /* not force inline */ constexpr bool _finish_production(ProductionParser& parser, Context& context,
29  Reader& reader)
30 {
31  return parser.template finish<lexy::_detail::final_parser>(context, reader);
32 }
33 
34 template <typename Production>
35 struct _prd
36 // If the production defines whitespace, it can't be a branch production.
37 : std::conditional_t<lexy::_production_defines_whitespace<Production>, rule_base,
38  _copy_base<lexy::production_rule<Production>>>
39 {
40  template <typename NextParser>
41  struct p
42  {
43  template <typename Context, typename Reader, typename... Args>
44  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args)
45  {
46  // Create a context for the production and parse the context there.
47  auto sub_context = context.sub_context(Production{});
48  sub_context.on(_ev::production_start{}, reader.position());
49 
50  // Skip initial whitespace if the rule changed.
51  if constexpr (lexy::_production_defines_whitespace<Production>)
52  {
53  if (!lexy::whitespace_parser<decltype(sub_context),
54  lexy::pattern_parser<>>::parse(sub_context, reader))
55  {
56  sub_context.on(_ev::production_cancel{}, reader.position());
57  return false;
58  }
59  }
60 
61  if (_parse_production<Production>(sub_context, reader))
62  {
63  sub_context.on(_ev::production_finish{}, reader.position());
64 
66  return continuation::parse(context, reader, sub_context, LEXY_FWD(args)...);
67  }
68  else
69  {
70  // Cancel.
71  sub_context.on(_ev::production_cancel{}, reader.position());
72  return false;
73  }
74  }
75  };
76 
77  template <typename Reader>
78  struct bp
79  {
81  typename Reader::iterator begin;
82 
83  template <typename ControlBlock>
84  constexpr auto try_parse(const ControlBlock* cb, const Reader& reader)
85  {
86  begin = reader.position();
87  return parser.try_parse(cb, reader);
88  }
89 
90  template <typename Context>
91  constexpr void cancel(Context& context)
92  {
93  // Cancel in a new context.
94  auto sub_context = context.sub_context(Production{});
95  sub_context.on(_ev::production_start{}, begin);
96  parser.cancel(sub_context);
97  sub_context.on(_ev::production_cancel{}, begin);
98  }
99 
100  template <typename NextParser, typename Context, typename... Args>
101  LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args)
102  {
103  static_assert(!lexy::_production_defines_whitespace<Production>);
104 
105  // Finish the production in a new context.
106  auto sub_context = context.sub_context(Production{});
107  sub_context.on(_ev::production_start{}, begin);
108  if (_finish_production(parser, sub_context, reader))
109  {
110  sub_context.on(_ev::production_finish{}, reader.position());
111 
113  return continuation::parse(context, reader, sub_context, LEXY_FWD(args)...);
114  }
115  else
116  {
117  // Cancel.
118  sub_context.on(_ev::production_cancel{}, reader.position());
119  return false;
120  }
121  }
122  };
123 };
124 
126 template <typename Production>
127 constexpr auto p = _prd<Production>{};
128 } // namespace lexyd
129 
130 namespace lexy
131 {
133 {
134  static LEXY_CONSTEVAL auto name()
135  {
136  return "maximum recursion depth exceeded";
137  }
138 };
139 } // namespace lexy
140 
141 namespace lexyd
142 {
143 template <typename Production, typename DepthError = void>
145 {
146  template <typename NextParser>
148  {
149  template <typename Context, typename Reader>
150  static constexpr bool increment_depth(Context& context, Reader& reader)
151  {
152  auto control_block = context.control_block;
153  LEXY_ASSERT(control_block->max_depth > 0,
154  "dsl::recurse_branch<P> is disabled in this context");
155 
156  // We're doing a recursive call, check for an exceeded depth.
157  if (control_block->cur_depth >= control_block->max_depth)
158  {
159  // We did report error from which we can't recover.
161  auto err = lexy::error<Reader, tag>(reader.position());
162  context.on(_ev::error{}, err);
163  return false;
164  }
165 
166  ++control_block->cur_depth;
167  return true;
168  }
169 
170  template <typename Context, typename Reader, typename... Args>
171  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args)
172  {
173  auto control_block = context.control_block;
174  --control_block->cur_depth;
175  return NextParser::parse(context, reader, LEXY_FWD(args)...);
176  }
177  };
178 
179  template <typename Reader>
180  struct bp
181  {
183 
186 
187  template <typename ControlBlock>
188  constexpr auto try_parse(const ControlBlock* cb, const Reader& reader)
189  {
190  return _impl.try_parse(cb, reader);
191  }
192 
193  template <typename Context>
194  constexpr void cancel(Context& context)
195  {
196  _impl.cancel(context);
197  }
198 
199  template <typename NextParser, typename Context, typename... Args>
200  LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args)
201  {
202  using depth = _depth_handler<NextParser>;
203  if (!depth::increment_depth(context, reader))
204  return false;
205  return _impl.template finish<depth>(context, reader, LEXY_FWD(args)...);
206  }
207  };
208 
209  template <typename NextParser>
210  struct p
211  {
212  template <typename Context, typename Reader, typename... Args>
213  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args)
214  {
215  using depth = _depth_handler<NextParser>;
216  if (!depth::increment_depth(context, reader))
217  return false;
218 
219  return lexy::parser_for<_prd<Production>, depth>::parse(context, reader,
220  LEXY_FWD(args)...);
221  }
222  };
223 
224  template <typename Tag>
226 };
227 
228 template <typename Production, typename DepthError = void>
229 struct _rec : rule_base
230 {
231  template <typename NextParser>
233 
234  template <typename Tag>
236 };
237 
241 template <typename Production>
242 constexpr auto recurse = _rec<Production>{};
243 
244 template <typename Production>
246 } // namespace lexyd
247 
248 #endif // LEXY_DSL_PRODUCTION_HPP_INCLUDED
249 
lexy::parse_events::production_finish
Definition: dsl/base.hpp:21
lexyd::_prd::bp::try_parse
constexpr auto try_parse(const ControlBlock *cb, const Reader &reader)
Definition: production.hpp:84
LEXY_CONSTEVAL
#define LEXY_CONSTEVAL
Definition: config.hpp:90
lexyd::_prd::bp::finish
LEXY_PARSER_FUNC bool finish(Context &context, Reader &reader, Args &&... args)
Definition: production.hpp:101
lexyd::branch_base
Definition: grammar.hpp:20
lexyd::_rec::p
lexy::parser_for< _recb< Production, DepthError >, NextParser > p
Definition: production.hpp:232
lexyd::_prd::p::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: production.hpp:44
lexyd::_finish_production
constexpr bool _finish_production(ProductionParser &parser, Context &context, Reader &reader)
Definition: production.hpp:28
lexyd::_recb::bp::_impl
impl _impl
Definition: production.hpp:185
lexyd::_prd::bp
Definition: production.hpp:78
lexy::_detail::context_finish_parser
Definition: action/base.hpp:175
lexyd::_recb::_depth_handler::increment_depth
static constexpr bool increment_depth(Context &context, Reader &reader)
Definition: production.hpp:150
lexyd::_recb::bp::finish
LEXY_PARSER_FUNC bool finish(Context &context, Reader &reader, Args &&... args)
Definition: production.hpp:200
lexy::branch_parser_for
typename BranchRule::template bp< Reader > branch_parser_for
Definition: dsl/base.hpp:103
LEXY_FWD
#define LEXY_FWD(...)
Definition: config.hpp:22
lexy::_detail::type_or
std::conditional_t< std::is_void_v< T >, Fallback, T > type_or
Definition: config.hpp:56
lexyd::_prd
Definition: capture.hpp:123
lexyd::inline_
constexpr auto inline_
Parses the rule of the production as if it were part of the current production.
Definition: production.hpp:16
lexyd::_prd::bp::cancel
constexpr void cancel(Context &context)
Definition: production.hpp:91
lexy
Definition: any_ref.hpp:12
lexyd::_recb::bp::impl
lexy::branch_parser_for< _prd< Production >, Reader > impl
Definition: production.hpp:184
lexyd::recurse
constexpr auto recurse
Definition: production.hpp:242
lexy::is_branch_rule
constexpr bool is_branch_rule
Definition: grammar.hpp:49
lexy::error
Generic failure.
Definition: error.hpp:14
lexyd::_prd::bp::begin
Reader::iterator begin
Definition: production.hpp:81
lexyd::_parse_production
constexpr bool _parse_production(Context &context, Reader &reader)
Definition: production.hpp:22
lexyd::_rec
Definition: production.hpp:229
lexyd::_prd::p
Definition: production.hpp:41
lexyd::recurse_branch
constexpr auto recurse_branch
Definition: production.hpp:245
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::parse_events::error
Definition: dsl/base.hpp:55
lexyd::_recb
Definition: production.hpp:144
lexyd::rule_base
Definition: grammar.hpp:17
lexyd::_recb::max_depth_error
static constexpr _recb< Production, Tag > max_depth_error
Definition: production.hpp:225
lexyd::_prd::bp::parser
lexy::production_branch_parser< Production, Reader > parser
Definition: production.hpp:80
lexy::production_rule
LEXY_DECAY_DECLTYPE(Production::rule) production_rule
Definition: grammar.hpp:133
lexy::parse_events::production_start
Definition: dsl/base.hpp:17
LEXY_PARSER_FUNC
#define LEXY_PARSER_FUNC
Definition: dsl/base.hpp:95
lexyd::_rec::max_depth_error
static constexpr _rec< Production, Tag > max_depth_error
Definition: production.hpp:235
lexy::whitespace_parser
Definition: dsl/base.hpp:216
lexy::max_recursion_depth_exceeded::name
static LEXY_CONSTEVAL auto name()
Definition: production.hpp:134
base.hpp
lexyd::_recb::bp
Definition: production.hpp:180
lexy::parse_events::production_cancel
Definition: dsl/base.hpp:25
lexy::pattern_parser
A parser that does not support any arguments.
Definition: dsl/base.hpp:159
lexy::_pb
Definition: dsl/base.hpp:106
lexyd::_recb::_depth_handler::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: production.hpp:171
lexy::_detail::final_parser
Definition: action/base.hpp:164
lexyd::_recb::p
Definition: production.hpp:210
lexy::parser_for
typename Rule::template p< NextParser > parser_for
Definition: dsl/base.hpp:100
lexyd::_recb::p::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: production.hpp:213
lexyd::_recb::bp::cancel
constexpr void cancel(Context &context)
Definition: production.hpp:194
base.hpp
lexy::max_recursion_depth_exceeded
Definition: production.hpp:132
lexyd::_recb::bp::try_parse
constexpr auto try_parse(const ControlBlock *cb, const Reader &reader)
Definition: production.hpp:188
lexyd
Definition: trace.hpp:22
LEXY_ASSERT
#define LEXY_ASSERT(Expr, Msg)
Definition: assert.hpp:37
branch.hpp
lexyd::p
constexpr auto p
Parses the production.
Definition: production.hpp:127
error.hpp
lexyd::_recb::_depth_handler
Definition: production.hpp:147


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:08