dsl/integer.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_INTEGER_HPP_INCLUDED
5 #define LEXY_DSL_INTEGER_HPP_INCLUDED
6 
7 #include <climits>
8 
10 #include <lexy/code_point.hpp>
11 #include <lexy/dsl/base.hpp>
12 #include <lexy/dsl/digit.hpp>
13 
14 namespace lexy
15 {
16 // Number of digits to express the given value.
17 template <typename Integer>
18 constexpr std::size_t _digit_count(int radix, Integer value)
19 {
20  LEXY_PRECONDITION(value >= Integer(0));
21 
22  if (value == 0)
23  return 1;
24 
25  std::size_t result = 0;
26  while (value > 0)
27  {
28  value = Integer(value / Integer(radix));
29  ++result;
30  }
31  return result;
32 }
33 
34 template <typename T>
36 {
37  using type = T;
38 
39  static constexpr auto is_bounded = true;
40 
41  static constexpr auto _max = [] {
42  if constexpr (std::is_same_v<T, char>)
43  return CHAR_MAX; // NOLINT
44  else if constexpr (std::is_same_v<T, signed char>)
45  return SCHAR_MAX;
46  else if constexpr (std::is_same_v<T, unsigned char>)
47  return UCHAR_MAX; // NOLINT
48  else if constexpr (std::is_same_v<T, wchar_t>)
49  return WCHAR_MAX; // NOLINT
50 #if LEXY_HAS_CHAR8_T
51  else if constexpr (std::is_same_v<T, char8_t>)
52  return UCHAR_MAX; // NOLINT
53 #endif
54  else if constexpr (std::is_same_v<T, char16_t>)
55  return UINT_LEAST16_MAX;
56  else if constexpr (std::is_same_v<T, char32_t>)
57  return UINT_LEAST32_MAX;
58  else if constexpr (std::is_same_v<T, signed short>)
59  return SHRT_MAX;
60  else if constexpr (std::is_same_v<T, unsigned short>)
61  return USHRT_MAX;
62  else if constexpr (std::is_same_v<T, signed int>)
63  return INT_MAX;
64  else if constexpr (std::is_same_v<T, unsigned int>)
65  return UINT_MAX;
66  else if constexpr (std::is_same_v<T, signed long>)
67  return LONG_MAX;
68  else if constexpr (std::is_same_v<T, unsigned long>)
69  return ULONG_MAX;
70  else if constexpr (std::is_same_v<T, signed long long>)
71  return LLONG_MAX;
72  else if constexpr (std::is_same_v<T, unsigned long long>)
73  return ULLONG_MAX;
74 #ifdef __SIZEOF_INT128__
75  else if constexpr (std::is_same_v<T, __int128_t>)
76  return __int128_t(~__uint128_t{} >> 1);
77  else if constexpr (std::is_same_v<T, __uint128_t>)
78  return ~__uint128_t{};
79 #endif
80  else
81  static_assert(_detail::error<T>,
82  "specialize integer_traits for your custom integer types");
83  }();
84  template <int Radix>
85  static constexpr std::size_t max_digit_count = _digit_count(Radix, _max);
86 
87  template <int Radix>
88  static constexpr void add_digit_unchecked(T& result, unsigned digit)
89  {
90  result = T(result * T(Radix) + T(digit));
91  }
92 
93  template <int Radix>
94  static constexpr bool add_digit_checked(T& result, unsigned digit)
95  {
96  constexpr auto can_use_unsigned = [] {
97  if constexpr (sizeof(T) >= sizeof(unsigned))
98  // If it's bigger or of the same size as unsigned, we can't use unsigned.
99  return false;
100  else
101  {
102  // We can do it if the worst-case does not overflow unsigned.
103  auto worst_case = static_cast<unsigned>(_max);
104  return integer_traits<unsigned>::add_digit_checked<Radix>(worst_case, Radix - 1);
105  }
106  }();
107 
108  // Check whether we can do an optimization for small integers,
109  // where we do the operation on unsigned and check later.
110  if constexpr (can_use_unsigned)
111  {
112  // This can't overflow, we've checked it above.
113  auto value = static_cast<unsigned>(result) * Radix + digit;
114 
115  // Check whether the final value can fit.
116  if (value > static_cast<unsigned>(_max))
117  return false;
118  else
119  {
120  result = static_cast<T>(value);
121  return true;
122  }
123  }
124  else
125  {
126  // result *= Radix
127  constexpr auto max_per_radix = T(_max / Radix);
128  if (result > max_per_radix)
129  return false;
130  result = T(result * Radix);
131 
132  // result += digit
133  if (result > T(_max - digit))
134  return false;
135  result = T(result + T(digit));
136 
137  return true;
138  }
139  }
140 };
141 
142 template <>
144 {
145  using type = code_point;
146 
147  static constexpr auto is_bounded = true;
148 
149  template <int Radix>
150  static constexpr std::size_t max_digit_count = _digit_count(Radix, 0x10'FFFF);
151 
152  template <int Radix>
153  static constexpr void add_digit_unchecked(type& result, unsigned digit)
154  {
155  std::uint_least32_t value = result.value();
156  integer_traits<std::uint_least32_t>::add_digit_unchecked<Radix>(value, digit);
157  result = code_point(value);
158  }
159  template <int Radix>
160  static constexpr bool add_digit_checked(type& result, unsigned digit)
161  {
162  std::uint_least32_t value = result.value();
163  if (!integer_traits<std::uint_least32_t>::add_digit_checked<Radix>(value, digit))
164  return false;
165  result = code_point(value);
166  return result.is_valid();
167  }
168 };
169 
170 template <typename T>
171 struct unbounded
172 {};
173 template <typename T>
174 struct integer_traits<unbounded<T>>
175 {
176  using type = typename integer_traits<T>::type;
177  static constexpr auto is_bounded = false;
178 
179  template <int Radix>
180  static constexpr void add_digit_unchecked(type& result, unsigned digit)
181  {
182  integer_traits<T>::template add_digit_unchecked<Radix>(result, digit);
183  }
184 };
185 
186 template <typename T, T Max>
187 struct bounded
188 {};
189 template <typename T, T Max>
190 struct integer_traits<bounded<T, Max>>
191 {
192  using type = typename integer_traits<T>::type;
193  static constexpr auto is_bounded = true;
194 
195  template <int Radix>
196  static constexpr std::size_t max_digit_count = _digit_count(Radix, Max);
197 
198  template <int Radix>
199  static constexpr void add_digit_unchecked(type& result, unsigned digit)
200  {
201  integer_traits<T>::template add_digit_unchecked<Radix>(result, digit);
202  }
203  template <int Radix>
204  static constexpr bool add_digit_checked(type& result, unsigned digit)
205  {
206  return integer_traits<T>::template add_digit_checked<Radix>(result, digit) && result <= Max;
207  }
208 };
209 } // namespace lexy
210 
211 namespace lexy
212 {
213 struct integer_overflow
214 {
215  static LEXY_CONSTEVAL auto name()
216  {
217  return "integer overflow";
218  }
219 };
220 } // namespace lexy
221 
222 namespace lexyd
223 {
224 template <typename T>
225 constexpr bool _is_bounded = lexy::integer_traits<T>::is_bounded;
226 
227 template <typename T, std::size_t N, int Radix>
228 constexpr bool _ndigits_can_overflow()
229 {
230  using traits = lexy::integer_traits<T>;
231  auto max_digit_count = traits::template max_digit_count<Radix>;
232  // We don't know whether the maximal value is a power of Radix,
233  // so we have to be conservative and don't rule out overflow on the same count.
234  return N >= max_digit_count;
235 }
236 
237 // Parses T in the Base without checking for overflow.
238 template <typename T, typename Base>
240 {
242  using base = Base;
243 
244  static constexpr auto radix = Base::digit_radix;
245 
246  struct result_type
247  {
248  typename traits::type value;
249  std::false_type overflow;
250  };
251 
252  template <typename Iterator>
253  static constexpr result_type parse(Iterator cur, Iterator end)
254  {
255  typename traits::type value(0);
256 
257  // Just parse digits until we've run out of digits.
258  while (cur != end)
259  {
260  auto digit = Base::digit_value(*cur++);
261  if (digit >= Base::digit_radix)
262  // Skip digit separator.
263  continue;
264 
265  traits::template add_digit_unchecked<radix>(value, digit);
266  }
267 
268  return {value, {}};
269  }
270 };
271 
272 // Parses T in the Base while checking for overflow.
273 template <typename T, typename Base, bool AssumeOnlyDigits>
275 {
277  using base = Base;
278 
279  static constexpr auto radix = Base::digit_radix;
280  static constexpr auto max_digit_count = traits::template max_digit_count<radix>;
281  static_assert(max_digit_count > 1, "integer must be able to store all possible digit values");
282 
283  struct result_type
284  {
285  typename traits::type value;
286  bool overflow;
287  };
288 
289  template <typename Iterator>
290  static constexpr result_type parse(Iterator cur, Iterator end)
291  {
292  // Find the first non-zero digit.
293  // Note that we always need a loop, even if leading zeros are not allowed:
294  // error recovery might get them anyway.
295  auto first_digit = 0u;
296  while (true)
297  {
298  if (cur == end)
299  return {typename traits::type(0), false};
300 
301  first_digit = Base::digit_value(*cur++);
302  if (first_digit != 0 && first_digit < radix)
303  break;
304  }
305 
306  // At this point, we've parsed exactly one non-zero digit, so we can assign.
307  auto value = typename traits::type(first_digit);
308 
309  // Handle at most the number of remaining digits.
310  // Due to the fixed loop count, it is most likely unrolled.
311  for (std::size_t digit_count = 1; digit_count < max_digit_count; ++digit_count)
312  {
313  // Find the next digit.
314  auto digit = 0u;
315  do
316  {
317  if (cur == end)
318  return {value, false};
319 
320  digit = Base::digit_value(*cur++);
321  // If we can assume it's a digit, we don't need the comparison.
322  } while (AssumeOnlyDigits ? false : digit >= Base::digit_radix);
323 
324  // We need to handle the last loop iteration special.
325  // (The compiler will not generate a branch here.)
326  if (digit_count == max_digit_count - 1)
327  {
328  // The last digit might overflow, so check for it.
329  if (!traits::template add_digit_checked<radix>(value, digit))
330  return {value, true};
331  }
332  else
333  {
334  // Add the digit without checking as it can't overflow.
335  traits::template add_digit_unchecked<radix>(value, digit);
336  }
337  }
338 
339  // If we've reached this point, we've parsed the maximal number of digits allowed.
340  // Now we can only overflow if there are still digits left.
341  return {value, cur != end};
342  }
343 };
344 template <typename T, typename Base, bool AssumeOnlyDigits>
345 using _integer_parser
346  = std::conditional_t<_is_bounded<T>, _bounded_integer_parser<T, Base, AssumeOnlyDigits>,
348 
349 template <typename T, typename Digits>
351 template <typename T, typename Base>
353 {
355 };
356 template <typename T, typename Base>
358 {
360 };
361 template <typename T, typename Base, typename Sep>
362 struct _integer_parser_digits<T, _digits_s<Base, Sep>>
363 {
365 };
366 template <typename T, typename Base, typename Sep>
367 struct _integer_parser_digits<T, _digits_st<Base, Sep>>
368 {
370 };
371 template <typename T, std::size_t N, typename Base>
372 struct _integer_parser_digits<T, _ndigits<N, Base>>
373 {
374  using value_type = std::conditional_t<_ndigits_can_overflow<T, N, Base::digit_radix>(), T,
377 };
378 template <typename T, std::size_t N, typename Base, typename Sep>
379 struct _integer_parser_digits<T, _ndigits_s<N, Base, Sep>>
380 {
381  using value_type = std::conditional_t<_ndigits_can_overflow<T, N, Base::digit_radix>(), T,
384 };
385 
386 template <typename T, typename Digits>
388 
389 template <typename Token, typename IntParser, typename Tag>
390 struct _int : _copy_base<Token>
391 {
392  template <typename NextParser>
393  struct _pc
394  {
395  template <typename Context, typename Reader, typename... Args>
396  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader,
397  typename Reader::iterator begin,
398  typename Reader::iterator end, Args&&... args)
399  {
400  auto [value, overflow] = IntParser::parse(begin, end);
401  if (overflow)
402  {
403  // Raise error but recover.
405  context.on(_ev::error{}, lexy::error<Reader, tag>(begin, end));
406  }
407 
408  // Need to skip whitespace now as well.
410  LEXY_FWD(args)..., value);
411  }
412  };
413 
414  template <typename Reader>
415  struct bp
416  {
417  typename Reader::marker end;
418 
419  constexpr auto try_parse(const void*, const Reader& reader)
420  {
422  auto result = parser.try_parse(reader);
423  end = parser.end;
424  return result;
425  }
426 
427  template <typename Context>
428  constexpr void cancel(Context&)
429  {}
430 
431  template <typename NextParser, typename Context, typename... Args>
432  LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args)
433  {
434  auto begin = reader.position();
435  context.on(_ev::token{}, Token{}, begin, end.position());
436  reader.reset(end);
437 
438  return _pc<NextParser>::parse(context, reader, begin, end.position(),
439  LEXY_FWD(args)...);
440  }
441  };
442 
443  template <typename NextParser>
444  struct p
445  {
446  template <typename Context, typename Reader, typename... Args>
447  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args)
448  {
449  auto begin = reader.position();
450  if (lexy::token_parser_for<Token, Reader> parser(reader); parser.try_parse(reader))
451  {
452  context.on(_ev::token{}, typename Token::token_type{}, begin,
453  parser.end.position());
454  reader.reset(parser.end);
455  }
456  else
457  {
458  parser.report_error(context, reader);
459  reader.reset(parser.end);
460 
461  // To recover we try and skip additional digits.
462  while (lexy::try_match_token(digit<typename IntParser::base>, reader))
463  {
464  }
465 
466  auto recovery_end = reader.position();
467  if (begin == recovery_end)
468  {
469  // We didn't get any digits; couldn't recover.
470  // We don't report error recovery events as nothing was done;
471  // we don't need to create an error token as nothing was consumed.
472  return false;
473  }
474  else
475  {
476  // We've succesfully recovered, mark everything as digits.
477  context.on(_ev::recovery_start{}, begin);
478  context.on(_ev::token{}, lexy::digits_token_kind, begin, recovery_end);
479  context.on(_ev::recovery_finish{}, recovery_end);
480  }
481  }
482  auto end = reader.position();
483 
484  return _pc<NextParser>::parse(context, reader, begin, end, LEXY_FWD(args)...);
485  }
486  };
487 };
488 
489 template <typename T, typename Base>
490 struct _int_dsl : _int<_digits<lexy::_detail::type_or<Base, decimal>>,
491  _integer_parser_for<T, _digits<lexy::_detail::type_or<Base, decimal>>>, void>
492 {
493  template <typename Digits>
494  constexpr auto operator()(Digits) const
495  {
496  static_assert(lexy::is_token_rule<Digits>);
497  if constexpr (std::is_void_v<Base>)
498  {
499  // Digits is a known rule as the user didn't specify Base.
501  }
502  else
503  {
504  // User has specified a base, so the digits are arbitrary.
505  using parser = _integer_parser<T, Base, false>;
507  }
508  }
509 };
510 
512 template <typename T, typename Base = void>
513 constexpr auto integer = _int_dsl<T, Base>{};
514 } // namespace lexyd
515 
516 //=== code_point_id ===//
517 namespace lexy
518 {
520 {
521  static LEXY_CONSTEVAL auto name()
522  {
523  return "invalid code point";
524  }
525 };
526 } // namespace lexy
527 
528 namespace lexyd
529 {
531 template <std::size_t N, typename Base = hex>
532 constexpr auto code_point_id = [] {
533  using type = std::conditional_t<_ndigits_can_overflow<lexy::code_point, N, Base::digit_radix>(),
535  using parser = _integer_parser<type, Base, true>;
537 }();
538 } // namespace lexyd
539 
540 //=== code_unit_id ===//
541 namespace lexy
542 {
544 {
545  static LEXY_CONSTEVAL auto name()
546  {
547  return "invalid code unit";
548  }
549 };
550 } // namespace lexy
551 
552 namespace lexyd
553 {
555 template <typename Encoding, std::size_t N, typename Base = hex>
556 constexpr auto code_unit_id = [] {
557  using char_type = typename Encoding::char_type;
558  using type = std::conditional_t<_ndigits_can_overflow<char_type, N, Base::digit_radix>(),
560  using parser = _integer_parser<type, Base, true>;
562 }();
563 } // namespace lexyd
564 
565 #endif // LEXY_DSL_INTEGER_HPP_INCLUDED
566 
lexy::integer_traits::add_digit_checked
static constexpr bool add_digit_checked(T &result, unsigned digit)
Definition: dsl/integer.hpp:94
lexyd::_unbounded_integer_parser::result_type
Definition: dsl/integer.hpp:246
LEXY_CONSTEVAL
#define LEXY_CONSTEVAL
Definition: config.hpp:98
lexyd::_digits_st
Definition: digit.hpp:354
lexy::parse_events::recovery_start
Definition: dsl/base.hpp:74
lexyd::_integer_parser_digits
Definition: dsl/integer.hpp:350
lexyd::code_point_id
constexpr auto code_point_id
Matches the integer value of a code point.
Definition: dsl/integer.hpp:532
lexyd::ascii::digit
constexpr auto digit
Definition: ascii.hpp:258
digit.hpp
magic_enum::char_type
string_view::value_type char_type
Definition: magic_enum.hpp:145
lexy::integer_traits
Definition: dsl/integer.hpp:35
lexyd::_integer_parser_digits< T, _ndigits_s< N, Base, Sep > >::type
_integer_parser< value_type, Base, false > type
Definition: dsl/integer.hpp:383
lexyd::_bounded_integer_parser::base
Base base
Definition: dsl/integer.hpp:277
lexy::invalid_code_unit::name
static LEXY_CONSTEVAL auto name()
Definition: dsl/integer.hpp:545
lexy::integer_traits::_max
static constexpr auto _max
Definition: dsl/integer.hpp:41
lexy::invalid_code_point::name
static LEXY_CONSTEVAL auto name()
Definition: dsl/integer.hpp:521
lexyd::_int::bp
Definition: dsl/integer.hpp:415
lexyd::_integer_parser_digits< T, _ndigits< N, Base > >::type
_integer_parser< value_type, Base, true > type
Definition: dsl/integer.hpp:376
LEXY_FWD
#define LEXY_FWD(...)
Definition: config.hpp:30
lexy::_detail::type_or
std::conditional_t< std::is_void_v< T >, Fallback, T > type_or
Definition: config.hpp:64
lexy::integer_traits::max_digit_count
static constexpr std::size_t max_digit_count
Definition: dsl/integer.hpp:85
lexyd::_bounded_integer_parser::result_type::value
traits::type value
Definition: dsl/integer.hpp:285
lexyd::_integer_parser_digits< T, _digits_s< Base, Sep > >::type
_integer_parser< T, Base, false > type
Definition: dsl/integer.hpp:364
lexyd::code_point
constexpr auto code_point
Matches a single unicode code point in the current unicode encoding.
Definition: dsl/code_point.hpp:200
lexyd::_integer_parser_digits< T, _ndigits< N, Base > >::value_type
std::conditional_t< _ndigits_can_overflow< T, N, Base::digit_radix >(), T, lexy::unbounded< T > > value_type
Definition: dsl/integer.hpp:375
lexyd::_digits_s
Definition: digit.hpp:407
lexy
Definition: any_ref.hpp:12
LEXY_PRECONDITION
#define LEXY_PRECONDITION(Expr)
Definition: assert.hpp:36
lexy::invalid_code_point
Definition: dsl/integer.hpp:519
lexyd::_unbounded_integer_parser
Definition: dsl/integer.hpp:239
cx::end
constexpr auto end(const C &c) -> decltype(c.end())
Definition: wildcards.hpp:686
lexyd::_bounded_integer_parser
Definition: dsl/integer.hpp:274
lexyd::_integer_parser_digits< T, _digits_t< Base > >::type
_integer_parser< T, Base, true > type
Definition: dsl/integer.hpp:359
lexy::integer_traits::is_bounded
static constexpr auto is_bounded
Definition: dsl/integer.hpp:39
lexy::error
Generic failure.
Definition: error.hpp:14
lexyd::_bounded_integer_parser::parse
static constexpr result_type parse(Iterator cur, Iterator end)
Definition: dsl/integer.hpp:290
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::invalid_code_unit
Definition: dsl/integer.hpp:543
lexyd::_integer_parser_for
typename _integer_parser_digits< T, Digits >::type _integer_parser_for
Definition: dsl/integer.hpp:387
lexyd::_ndigits
Definition: digit.hpp:600
lexy::parse_events::error
Definition: dsl/base.hpp:68
lexy::try_match_token
constexpr LEXY_FORCE_INLINE auto try_match_token(TokenRule, Reader &reader)
Definition: dsl/base.hpp:245
lexyd::_integer_parser_digits< T, _digits< Base > >::type
_integer_parser< T, Base, true > type
Definition: dsl/integer.hpp:354
lexy::_detail::automatic_ws_parser::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: whitespace.hpp:178
lexyd::_digits_t
Definition: digit.hpp:439
lexyd::_int::bp::cancel
constexpr void cancel(Context &)
Definition: dsl/integer.hpp:428
assert.hpp
lexyd::_int::bp::end
Reader::marker end
Definition: dsl/integer.hpp:417
lexy::digits_token_kind
@ digits_token_kind
Definition: grammar.hpp:95
lexyd::_ndigits_s
Definition: digit.hpp:561
lexy::parse_events::recovery_finish
Definition: dsl/base.hpp:79
LEXY_PARSER_FUNC
#define LEXY_PARSER_FUNC
Definition: dsl/base.hpp:108
lexyd::_int::_pc::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, typename Reader::iterator begin, typename Reader::iterator end, Args &&... args)
Definition: dsl/integer.hpp:396
cx::begin
constexpr auto begin(const C &c) -> decltype(c.begin())
Definition: wildcards.hpp:661
lexyd::_integer_parser_digits< T, _ndigits_s< N, Base, Sep > >::value_type
std::conditional_t< _ndigits_can_overflow< T, N, Base::digit_radix >(), T, lexy::unbounded< T > > value_type
Definition: dsl/integer.hpp:382
lexyd::_int::p::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: dsl/integer.hpp:447
lexyd::_int_dsl::operator()
constexpr auto operator()(Digits) const
Definition: dsl/integer.hpp:494
base.hpp
lexyd::_unbounded_integer_parser::base
Base base
Definition: dsl/integer.hpp:242
lexyd::_int_dsl
Definition: dsl/integer.hpp:490
lexyd::_integer_parser_digits< T, _digits_st< Base, Sep > >::type
_integer_parser< T, Base, false > type
Definition: dsl/integer.hpp:369
lexyd::_int::bp::try_parse
constexpr auto try_parse(const void *, const Reader &reader)
Definition: dsl/integer.hpp:419
lexy::parse_events::token
Definition: dsl/base.hpp:57
lexy::integer_traits::type
T type
Definition: dsl/integer.hpp:37
lexyd::_int::p
Definition: dsl/integer.hpp:444
lexyd::_integer_parser
std::conditional_t< _is_bounded< T >, _bounded_integer_parser< T, Base, AssumeOnlyDigits >, _unbounded_integer_parser< T, Base > > _integer_parser
Definition: dsl/integer.hpp:347
lexyd::_digits
Definition: digit.hpp:499
lexy::unbounded
Definition: dsl/integer.hpp:171
code_point.hpp
lexyd::_bounded_integer_parser::result_type::overflow
bool overflow
Definition: dsl/integer.hpp:286
lexy::_digit_count
constexpr std::size_t _digit_count(int radix, Integer value)
Definition: dsl/integer.hpp:18
lexyd::_unbounded_integer_parser::parse
static constexpr result_type parse(Iterator cur, Iterator end)
Definition: dsl/integer.hpp:253
lexyd::_unbounded_integer_parser::result_type::value
traits::type value
Definition: dsl/integer.hpp:248
lexyd::_int
Definition: dsl/integer.hpp:390
lexy::integer_traits::add_digit_unchecked
static constexpr void add_digit_unchecked(T &result, unsigned digit)
Definition: dsl/integer.hpp:88
lexy::token_parser_for
typename TokenRule::template tp< Reader > token_parser_for
Definition: dsl/base.hpp:242
lexyd
Definition: trace.hpp:22
lexyd::integer
constexpr auto integer
Parses the digits matched by the rule into an integer type.
Definition: dsl/integer.hpp:513
lexyd::_int::_pc
Definition: dsl/integer.hpp:393
lexyd::_unbounded_integer_parser::result_type::overflow
std::false_type overflow
Definition: dsl/integer.hpp:249
lexyd::_int::bp::finish
LEXY_PARSER_FUNC bool finish(Context &context, Reader &reader, Args &&... args)
Definition: dsl/integer.hpp:432
lexyd::_copy_base
decltype(_copy_base_impl< Rule >()) _copy_base
Definition: dsl/base.hpp:104
lexy::code_point
A unicode code point.
Definition: code_point.hpp:20
lexyd::_bounded_integer_parser::result_type
Definition: dsl/integer.hpp:283
lexyd::code_unit_id
constexpr auto code_unit_id
Matches the integer value of a code unit.
Definition: dsl/integer.hpp:556


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