combination.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_COMBINATION_HPP_INCLUDED
5 #define LEXY_DSL_COMBINATION_HPP_INCLUDED
6 
8 #include <lexy/dsl/base.hpp>
9 #include <lexy/dsl/choice.hpp>
10 #include <lexy/dsl/error.hpp>
11 #include <lexy/dsl/loop.hpp>
12 #include <lexy/dsl/sequence.hpp>
13 
14 namespace lexy
15 {
17 {
18  static LEXY_CONSTEVAL auto name()
19  {
20  return "combination duplicate";
21  }
22 };
23 } // namespace lexy
24 
25 namespace lexyd
26 {
27 template <typename Sink>
29 {
30  // The sink to store values of the item.
31  Sink& sink;
32  // Whether or not the state has already been handled.
33  const bool* handled;
34  // Write the index of the item in here.
35  std::size_t idx = 0;
36  // Whether or not we should break.
37  bool loop_break = false;
38 };
39 
40 // Final rule for one item in the combination.
41 template <std::size_t Idx>
43 {
44  template <typename NextParser>
45  struct p
46  {
47  template <typename Context, typename Reader, typename Sink, typename... Args>
48  LEXY_PARSER_FUNC static bool parse(Context&, Reader&, _comb_control<Sink>& ctrl,
49  Args&&... args)
50  {
51  ctrl.idx = Idx;
52  if constexpr (sizeof...(Args) > 0)
53  {
54  if (!ctrl.handled[Idx])
55  // Only call the sink if it is not a duplicate.
56  ctrl.sink(LEXY_FWD(args)...);
57  }
58  return true;
59  }
60  };
61 };
62 
63 template <typename DuplicateError, typename ElseRule, typename... R>
64 struct _comb : rule_base
65 {
66  template <std::size_t... Idx>
68  {
69  if constexpr (std::is_void_v<ElseRule>)
70  return ((R{} >> _comb_it<Idx>{}) | ...);
71  else
72  return ((R{} >> _comb_it<Idx>{}) | ... | ElseRule{});
73  }
75 
76  template <typename NextParser>
77  struct p
78  {
79  template <typename Context, typename Reader, typename... Args>
80  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args)
81  {
82  constexpr auto N = sizeof...(R);
83 
84  auto sink = context.value_callback().sink();
85  bool handled[N] = {};
86  _comb_control<decltype(sink)> control{sink, handled};
87 
88  // Parse all iterations of the choice.
89  for (auto count = 0; count < int(N); ++count)
90  {
91  auto begin = reader.position();
92 
93  using parser
95  if (!parser::parse(context, reader, control))
96  return false;
97  else if (control.loop_break)
98  break; // Partial combination and we're done.
99 
100  if (handled[control.idx])
101  {
103  auto err = lexy::error<Reader, tag>(begin, reader.position());
104  context.on(_ev::error{}, err);
105  // We can trivially recover, but need to do another iteration.
106  --count;
107  }
108  else
109  {
110  handled[control.idx] = true;
111  }
112  }
113 
114  // Obtain the final result and continue.
115  return lexy::sink_finish_parser<NextParser>::parse(context, reader, sink,
116  LEXY_FWD(args)...);
117  }
118  };
119 
120  //=== dsl ===//
121  template <typename Tag>
122  static constexpr _comb<Tag, ElseRule, R...> duplicate_error = {};
123 
124  template <typename Tag>
126 };
127 
130 template <typename... R>
131 constexpr auto combination(R...)
132 {
133  static_assert((lexy::is_branch_rule<R> && ...), "combination() requires a branch rule");
134  static_assert((!lexy::is_unconditional_branch_rule<R> && ...),
135  "combination() does not support unconditional branches");
136  return _comb<void, void, R...>{};
137 }
138 
141 template <typename... R>
142 constexpr auto partial_combination(R...)
143 {
144  static_assert((lexy::is_branch_rule<R> && ...), "partial_combination() requires a branch rule");
145  static_assert((!lexy::is_unconditional_branch_rule<R> && ...),
146  "partial_combination() does not support unconditional branches");
147  // If the choice no longer matches, we just break.
148  return _comb<void, decltype(break_), R...>{};
149 }
150 } // namespace lexyd
151 
152 #endif // LEXY_DSL_COMBINATION_HPP_INCLUDED
153 
lexyd::_comb
Definition: combination.hpp:64
choice.hpp
LEXY_CONSTEVAL
#define LEXY_CONSTEVAL
Definition: config.hpp:90
lexy::_detail::index_sequence_for
make_index_sequence< sizeof...(T)> index_sequence_for
Definition: integer_sequence.hpp:60
error.hpp
lexy::combination_duplicate
Definition: combination.hpp:16
lexyd::_comb::p
Definition: combination.hpp:77
lexyd::_comb::_comb_choice_
static auto _comb_choice_(lexy::_detail::index_sequence< Idx... >)
Definition: combination.hpp:67
loop.hpp
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
sequence.hpp
lexy::_detail::integer_sequence
Definition: integer_sequence.hpp:12
lexy
Definition: any_ref.hpp:12
lexyd::_comb_control::idx
std::size_t idx
Definition: combination.hpp:35
detail::void
j template void())
Definition: json.hpp:4893
lexy::error
Generic failure.
Definition: error.hpp:14
lexy::count
constexpr auto count
Sink that counts all arguments.
Definition: fold.hpp:88
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
lexyd::_comb_it::p
Definition: combination.hpp:45
lexyd::_comb::duplicate_error
static constexpr _comb< Tag, ElseRule, R... > duplicate_error
Definition: combination.hpp:122
lexyd::_comb_control::loop_break
bool loop_break
Definition: combination.hpp:37
lexy::parse_events::error
Definition: dsl/base.hpp:55
lexyd::_comb_it
Definition: combination.hpp:42
lexyd::rule_base
Definition: grammar.hpp:17
lexyd::_comb_control
Definition: combination.hpp:28
lexyd::_comb_control::sink
Sink & sink
Definition: combination.hpp:31
lexyd::_comb::_comb_choice
decltype(_comb_choice_(lexy::_detail::index_sequence_for< R... >{})) _comb_choice
Definition: combination.hpp:74
LEXY_PARSER_FUNC
#define LEXY_PARSER_FUNC
Definition: dsl/base.hpp:95
lexyd::_comb::missing_error
static constexpr _comb< DuplicateError, _err< Tag, void >, R... > missing_error
Definition: combination.hpp:125
integer_sequence.hpp
cx::begin
constexpr auto begin(const C &c) -> decltype(c.begin())
Definition: wildcards.hpp:661
base.hpp
lexy::pattern_parser
A parser that does not support any arguments.
Definition: dsl/base.hpp:159
lexyd::partial_combination
constexpr auto partial_combination(R...)
Definition: combination.hpp:142
lexyd::break_
constexpr auto break_
Exits a loop().
Definition: loop.hpp:30
lexyd::_comb_it::p::parse
static LEXY_PARSER_FUNC bool parse(Context &, Reader &, _comb_control< Sink > &ctrl, Args &&... args)
Definition: combination.hpp:48
lexyd::ascii::control
constexpr auto control
Definition: ascii.hpp:42
lexyd::combination
constexpr auto combination(R...)
Definition: combination.hpp:131
lexyd::_comb::p::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: combination.hpp:80
lexy::sink_finish_parser::parse
static LEXY_PARSER_FUNC auto parse(Context &context, Reader &reader, Sink &sink, Args &&... args)
Definition: dsl/base.hpp:189
lexy::parser_for
typename Rule::template p< NextParser > parser_for
Definition: dsl/base.hpp:100
lexy::combination_duplicate::name
static LEXY_CONSTEVAL auto name()
Definition: combination.hpp:18
lexyd
Definition: trace.hpp:22
lexyd::_comb_control::handled
const bool * handled
Definition: combination.hpp:33


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