until.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_UNTIL_HPP_INCLUDED
5 #define LEXY_DSL_UNTIL_HPP_INCLUDED
6 
7 #include <lexy/_detail/swar.hpp>
8 #include <lexy/dsl/base.hpp>
9 #include <lexy/dsl/token.hpp>
10 
11 namespace lexyd
12 {
13 struct _nl;
14 
15 template <typename Condition, typename Reader>
16 constexpr void _until_swar([[maybe_unused]] Reader& reader)
17 {
18  if constexpr (std::is_same_v<Condition, _nl> //
19  && lexy::_detail::is_swar_reader<Reader>)
20  {
21  // We use SWAR to skip characters until we have one that is <= 0xF or EOF.
22  // Then we need to inspect it in more detail.
23  using char_type = typename Reader::encoding::char_type;
24 
25  while (true)
26  {
27  auto cur = reader.peek_swar();
29  || lexy::_detail::swar_has_char_less<char_type, 0xF>(cur))
30  break;
31  reader.bump_swar();
32  }
33  }
34 }
35 
36 template <typename Condition>
37 struct _until_eof : token_base<_until_eof<Condition>, unconditional_branch_base>
38 {
39  template <typename Reader>
40  struct tp
41  {
42  typename Reader::marker end;
43 
44  constexpr explicit tp(const Reader& reader) : end(reader.current()) {}
45 
46  constexpr std::true_type try_parse(Reader reader)
47  {
48  while (true)
49  {
50  _until_swar<Condition>(reader);
51 
52  // Check whether we've reached the end of the input or the condition.
53  // Note that we're checking for EOF before the condition.
54  // This is a potential optimization: as we're accepting EOF anyway, we don't need to
55  // enter Condition's parsing logic.
56  if (reader.peek() == Reader::encoding::eof()
57  || lexy::try_match_token(Condition{}, reader))
58  {
59  // It did, so we're done.
60  break;
61  }
62 
63  // It did not match, consume one code unit and try again.
64  reader.bump();
65  }
66 
67  end = reader.current();
68  return {};
69  }
70  };
71 };
72 
73 template <typename Condition>
74 struct _until : token_base<_until<Condition>>
75 {
76  template <typename Reader>
77  struct tp
78  {
79  typename Reader::marker end;
80 
81  constexpr explicit tp(const Reader& reader) : end(reader.current()) {}
82 
83  constexpr bool try_parse(Reader reader)
84  {
85  while (true)
86  {
87  _until_swar<Condition>(reader);
88 
89  // Try to parse the condition.
90  if (lexy::try_match_token(Condition{}, reader))
91  {
92  // It did match, we're done at that end.
93  end = reader.current();
94  return true;
95  }
96 
97  // Check whether we've reached the end of the input.
98  // We need to do it after checking for condition, as the condition might just
99  // accept EOF.
100  if (reader.peek() == Reader::encoding::eof())
101  {
102  // It did, so we did not succeed.
103  end = reader.current();
104  return false;
105  }
106 
107  // It did not match, consume one code unit and try again.
108  reader.bump();
109  }
110 
111  return false; // unreachable
112  }
113 
114  template <typename Context>
115  constexpr void report_error(Context& context, Reader reader)
116  {
117  // We need to trigger the error `Condition` would.
118  // As such, we try parsing it, which will report an error.
119 
120  reader.reset(end);
121  LEXY_ASSERT(reader.peek() == Reader::encoding::eof(),
122  "forgot to set end in try_parse()");
123 
125  auto result = parser.try_parse(reader);
126  LEXY_ASSERT(!result, "condition shouldn't have matched?!");
127  parser.report_error(context, reader);
128  }
129  };
130 
132  constexpr auto or_eof() const
133  {
134  return _until_eof<Condition>{};
135  }
136 };
137 
140 template <typename Condition>
141 constexpr auto until(Condition)
142 {
143  static_assert(lexy::is_token_rule<Condition>);
144  return _until<Condition>{};
145 }
146 } // namespace lexyd
147 
148 namespace lexy
149 {
150 template <typename Condition>
151 constexpr auto token_kind_of<lexy::dsl::_until_eof<Condition>> = lexy::any_token_kind;
152 template <typename Condition>
153 constexpr auto token_kind_of<lexy::dsl::_until<Condition>> = lexy::any_token_kind;
154 } // namespace lexy
155 
156 #endif // LEXY_DSL_UNTIL_HPP_INCLUDED
157 
lexyd::until
constexpr auto until(Condition)
Definition: until.hpp:141
lexy::any_token_kind
@ any_token_kind
Definition: grammar.hpp:88
token.hpp
magic_enum::char_type
string_view::value_type char_type
Definition: magic_enum.hpp:145
lexyd::_until::tp::end
Reader::marker end
Definition: until.hpp:79
lexyd::_until::tp::tp
constexpr tp(const Reader &reader)
Definition: until.hpp:81
lexyd::_until_eof::tp::try_parse
constexpr std::true_type try_parse(Reader reader)
Definition: until.hpp:46
lexyd::_until_eof::tp::tp
constexpr tp(const Reader &reader)
Definition: until.hpp:44
lexyd::_until_eof::tp::end
Reader::marker end
Definition: until.hpp:42
lexy
Definition: any_ref.hpp:12
lexyd::_until_eof::tp
Definition: until.hpp:40
lexy::_detail::swar_has_char
constexpr bool swar_has_char(swar_int v)
Definition: swar.hpp:177
lexyd::_until
Definition: until.hpp:74
swar.hpp
lexyd::_until::tp
Definition: until.hpp:77
lexy::try_match_token
constexpr LEXY_FORCE_INLINE auto try_match_token(TokenRule, Reader &reader)
Definition: dsl/base.hpp:245
lexyd::token_base
Definition: dsl/token.hpp:42
lexyd::_until::tp::try_parse
constexpr bool try_parse(Reader reader)
Definition: until.hpp:83
lexyd::_until_swar
constexpr void _until_swar([[maybe_unused]] Reader &reader)
Definition: until.hpp:16
base.hpp
lexyd::_until::or_eof
constexpr auto or_eof() const
Also accepts EOF as the closing condition.
Definition: until.hpp:132
lexyd::_until::tp::report_error
constexpr void report_error(Context &context, Reader reader)
Definition: until.hpp:115
lexyd::_until_eof
Definition: until.hpp:37
lexy::token_parser_for
typename TokenRule::template tp< Reader > token_parser_for
Definition: dsl/base.hpp:242
lexyd
Definition: trace.hpp:22
lexyd::eof
constexpr auto eof
Matches EOF.
Definition: eof.hpp:72
LEXY_ASSERT
#define LEXY_ASSERT(Expr, Msg)
Definition: assert.hpp:37


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