4 #ifndef LEXY_DSL_EXPRESSION_HPP_INCLUDED
5 #define LEXY_DSL_EXPRESSION_HPP_INCLUDED
33 template <
typename... Operands>
61 static constexpr
auto left(
unsigned group,
unsigned level)
65 static constexpr
auto right(
unsigned group,
unsigned level)
90 return lhs > 0 &&
rhs == 0;
94 return lhs == 0 &&
rhs > 0;
98 template <
typename Operation>
101 if constexpr (std::is_base_of_v<lexyd::infix_op_left, Operation>
105 || std::is_base_of_v<lexyd::infix_op_list, Operation>
107 || std::is_base_of_v<lexyd::infix_op_single, Operation>)
109 else if constexpr (std::is_base_of_v<lexyd::infix_op_right, Operation>)
111 else if constexpr (std::is_base_of_v<lexyd::prefix_op, Operation>)
113 else if constexpr (std::is_base_of_v<lexyd::postfix_op, Operation>)
117 template <
typename DestOperation>
126 template <
typename CurOperation>
127 static constexpr
auto transition(CurOperation
op,
unsigned cur_group,
unsigned cur_level)
130 return get(
op, cur_group, cur_level + 1);
132 template <
typename... Operations>
142 (
void)((result =
transition(Operations{}, cur_group + 1, cur_level),
143 cur_group = result.group, result.is_valid())
148 template <
typename CurOperation>
149 static constexpr
auto get(CurOperation,
unsigned cur_group,
unsigned cur_level)
151 if constexpr (std::is_same_v<DestOperation, CurOperation>)
152 return get_binding_power<CurOperation>(cur_group, cur_level);
154 return transition(
typename CurOperation::operand{}, cur_group, cur_level);
159 template <
typename Expr,
typename Operation>
168 template <
typename Operation>
171 template <
typename... Operations>
174 template <
typename T>
179 template <
typename... T>
185 static constexpr
auto size =
sizeof...(Operations);
189 template <
template <
typename>
typename Continuation,
typename Context,
typename Reader,
196 auto cur_idx = std::size_t(0);
211 template <
bool Pre,
unsigned MinBindingPower>
214 template <
unsigned CurLevel>
219 template <
unsigned CurLevel,
typename... Operations>
222 return (get<CurLevel>(Operations{}) + ...);
224 template <
unsigned CurLevel,
typename Operation>
225 static constexpr
auto get(Operation)
227 constexpr
auto bp = get_binding_power<Operation>(0, CurLevel);
229 auto tail = get<CurLevel + 1>(
typename Operation::operand{});
230 constexpr
auto is_prefix = std::is_base_of_v<lexyd::prefix_op, Operation>;
231 if constexpr (is_prefix == Pre
232 && ((is_prefix && bp.rhs >= MinBindingPower)
233 || (!is_prefix && bp.lhs >= MinBindingPower)))
234 return tail + Operation{};
241 template <
typename Expr,
unsigned MinBindingPower>
243 typename Expr::operation{}));
246 template <
typename Expr,
unsigned MinBindingPower>
248 typename Expr::operation{}));
254 template <
typename RootOperation>
263 template <
typename Operation>
268 template <
typename Context,
typename Reader,
typename... Args>
274 constexpr
auto value_type_void = std::is_void_v<typename Context::value_type>;
276 = binding_power_of<typename Context::production>(Operation{});
278 if constexpr (std::is_base_of_v<infix_op_list, Operation>)
283 auto sink = context.value_callback().sink();
286 if constexpr (!value_type_void)
297 if (!_parse<binding_power.rhs>(context, reader, state))
303 if constexpr (!value_type_void)
308 auto op = parse_operator<typename op_rule::op_literals>(reader);
312 reader.reset(
op.cur);
317 if (!op_rule::template op_finish<lexy::sink_parser>(context, reader,
op,
326 if constexpr (value_type_void)
329 context.value.emplace();
333 context.value.emplace(
LEXY_MOV(sink).finish());
342 if (!_parse<binding_power.rhs>(context, reader, state))
345 auto value =
LEXY_MOV(context.value);
348 if constexpr (value_type_void)
349 context.value.emplace_result(context.value_callback(),
352 context.value.emplace_result(context.value_callback(),
LEXY_FWD(op_args)...,
360 if (!_parse<binding_power.rhs>(context, reader, state))
370 if constexpr (value_type_void)
371 context.value.emplace_result(context.value_callback(),
374 context.value.emplace_result(context.value_callback(), *
LEXY_MOV(lhs),
377 if constexpr (std::is_base_of_v<infix_op_single, Operation>)
380 auto op = parse_operator<typename op_rule::op_literals>(reader);
383 using tag =
typename Context::production::operator_chain_error;
388 reader.reset(
op.cur);
393 auto value =
LEXY_MOV(context.value);
396 if constexpr (value_type_void)
397 context.value.emplace_result(context.value_callback(),
400 context.value.emplace_result(context.value_callback(), *
LEXY_MOV(value),
409 template <
typename Context,
typename Reader>
410 static constexpr
bool parse(Context& context, Reader& reader,
414 using production =
typename Context::production;
419 using tag =
typename production::operator_nesting_error;
424 reader.reset(
op.cur);
429 constexpr
auto binding_power = binding_power_of<production>(Operation{});
440 using tag =
typename production::operator_group_error;
453 template <
unsigned MinBindingPower,
typename Context,
typename Reader>
470 auto op = lexy::_detail::parse_operator<typename op_list::ops>(reader);
474 reader.reset(
op.cur);
479 auto result = op_list::template apply<_continuation>(context, reader,
op, state);
485 template <
unsigned MinBindingPower,
typename Context,
typename Reader>
486 static constexpr
bool _parse(Context& context, Reader& reader,
_state& state)
494 return _parse_lhs<MinBindingPower>(context, reader, state);
499 if (!_parse_lhs<MinBindingPower>(context, reader, state))
508 auto op = parse_operator<typename op_list::ops>(reader);
511 reader.reset(
op.cur);
515 result = op_list::template apply<_continuation>(context, reader,
op, state);
527 template <
typename NextParser>
530 template <
typename Context,
typename Reader>
533 static_assert(std::is_same_v<NextParser, lexy::_detail::final_parser>);
535 using production =
typename Context::production;
536 constexpr
auto binding_power = lexy::_detail::binding_power_of<production>(
542 constexpr
auto min_binding_power
546 _parse<min_binding_power>(context, reader, state);
549 return !!context.value;
562 return "maximum operator nesting level exceeded";
570 return "operator cannot be chained";
578 return "operator cannot be mixed with previous operators";
585 static constexpr
auto max_operator_nesting = 256;
593 template <
typename Expr,
typename RootOperation>
600 #endif // LEXY_DSL_EXPRESSION_HPP_INCLUDED