File indexing completed on 2025-09-17 08:40:34
0001
0002
0003
0004
0005
0006 #ifndef BOOST_PARSER_PARSER_HPP
0007 #define BOOST_PARSER_PARSER_HPP
0008
0009 #include <boost/parser/parser_fwd.hpp>
0010 #include <boost/parser/concepts.hpp>
0011 #include <boost/parser/error_handling.hpp>
0012 #include <boost/parser/tuple.hpp>
0013 #include <boost/parser/detail/hl.hpp>
0014 #include <boost/parser/detail/numeric.hpp>
0015 #include <boost/parser/detail/case_fold.hpp>
0016 #include <boost/parser/detail/unicode_char_sets.hpp>
0017 #include <boost/parser/detail/pp_for_each.hpp>
0018 #include <boost/parser/detail/printing.hpp>
0019
0020 #include <boost/parser/detail/text/algorithm.hpp>
0021 #include <boost/parser/detail/text/trie_map.hpp>
0022 #include <boost/parser/detail/text/unpack.hpp>
0023
0024 #include <type_traits>
0025 #include <variant>
0026 #include <vector>
0027
0028
0029 namespace boost { namespace parser {
0030
0031
0032
0033
0034
0035 struct none;
0036
0037 #if defined(BOOST_PARSER_NO_RUNTIME_ASSERTIONS)
0038 struct none
0039 {};
0040 #else
0041 struct none
0042 {
0043 none() = default;
0044
0045
0046
0047 template<typename T>
0048 none(T const &)
0049 {
0050 fail();
0051 }
0052 template<typename T>
0053 none & operator=(T const &)
0054 {
0055 fail();
0056 return *this;
0057 }
0058 template<typename T>
0059 operator T() const
0060 {
0061 fail();
0062 return T{};
0063 }
0064
0065
0066 none operator+() const
0067 {
0068 fail();
0069 return none{};
0070 }
0071 none operator-() const
0072 {
0073 fail();
0074 return none{};
0075 }
0076 none operator*() const
0077 {
0078 fail();
0079 return none{};
0080 }
0081 none operator~() const
0082 {
0083 fail();
0084 return none{};
0085 }
0086 none operator&() const
0087 {
0088 fail();
0089 return none{};
0090 }
0091 none operator!() const
0092 {
0093 fail();
0094 return none{};
0095 }
0096 none operator++()
0097 {
0098 fail();
0099 return none{};
0100 }
0101 none & operator++(int)
0102 {
0103 fail();
0104 return *this;
0105 }
0106 none operator--()
0107 {
0108 fail();
0109 return none{};
0110 }
0111 none operator--(int)
0112 {
0113 fail();
0114 return *this;
0115 }
0116
0117
0118 template<typename T>
0119 none operator<<(T const &) const
0120 {
0121 fail();
0122 return none{};
0123 }
0124 template<typename T>
0125 none operator>>(T const &) const
0126 {
0127 fail();
0128 return none{};
0129 }
0130 template<typename T>
0131 none operator*(T const &) const
0132 {
0133 fail();
0134 return none{};
0135 }
0136 template<typename T>
0137 none operator/(T const &) const
0138 {
0139 fail();
0140 return none{};
0141 }
0142 template<typename T>
0143 none operator%(T const &) const
0144 {
0145 fail();
0146 return none{};
0147 }
0148 template<typename T>
0149 none operator+(T const &) const
0150 {
0151 fail();
0152 return none{};
0153 }
0154 template<typename T>
0155 none operator-(T const &) const
0156 {
0157 fail();
0158 return none{};
0159 }
0160 template<typename T>
0161 none operator<(T const &) const
0162 {
0163 fail();
0164 return none{};
0165 }
0166 template<typename T>
0167 none operator>(T const &) const
0168 {
0169 fail();
0170 return none{};
0171 }
0172 template<typename T>
0173 none operator<=(T const &) const
0174 {
0175 fail();
0176 return none{};
0177 }
0178 template<typename T>
0179 none operator>=(T const &) const
0180 {
0181 fail();
0182 return none{};
0183 }
0184 template<typename T>
0185 none operator==(T const &) const
0186 {
0187 fail();
0188 return none{};
0189 }
0190 template<typename T>
0191 none operator!=(T const &) const
0192 {
0193 fail();
0194 return none{};
0195 }
0196 template<typename T>
0197 none operator||(T const &) const
0198 {
0199 fail();
0200 return none{};
0201 }
0202 template<typename T>
0203 none operator&&(T const &) const
0204 {
0205 fail();
0206 return none{};
0207 }
0208 template<typename T>
0209 none operator&(T const &) const
0210 {
0211 fail();
0212 return none{};
0213 }
0214 template<typename T>
0215 none operator|(T const &) const
0216 {
0217 fail();
0218 return none{};
0219 }
0220 template<typename T>
0221 none operator^(T const &) const
0222 {
0223 fail();
0224 return none{};
0225 }
0226 template<typename T>
0227 none operator,(T const &) const
0228 {
0229 fail();
0230 return none{};
0231 }
0232 template<typename T>
0233 none operator->*(T const &) const
0234 {
0235 fail();
0236 return none{};
0237 }
0238 template<typename T>
0239 none operator<<=(T const &)
0240 {
0241 fail();
0242 return none{};
0243 }
0244 template<typename T>
0245 none operator>>=(T const &)
0246 {
0247 fail();
0248 return none{};
0249 }
0250 template<typename T>
0251 none operator*=(T const &)
0252 {
0253 fail();
0254 return none{};
0255 }
0256 template<typename T>
0257 none operator/=(T const &)
0258 {
0259 fail();
0260 return none{};
0261 }
0262 template<typename T>
0263 none operator%=(T const &)
0264 {
0265 fail();
0266 return none{};
0267 }
0268 template<typename T>
0269 none operator+=(T const &)
0270 {
0271 fail();
0272 return none{};
0273 }
0274 template<typename T>
0275 none operator-=(T const &)
0276 {
0277 fail();
0278 return none{};
0279 }
0280 template<typename T>
0281 none operator&=(T const &)
0282 {
0283 fail();
0284 return none{};
0285 }
0286 template<typename T>
0287 none operator|=(T const &)
0288 {
0289 fail();
0290 return none{};
0291 }
0292 template<typename T>
0293 none operator^=(T const &)
0294 {
0295 fail();
0296 return none{};
0297 }
0298 template<typename T>
0299 none operator[](T const &) const
0300 {
0301 fail();
0302 return none{};
0303 }
0304
0305
0306 template<typename... Args>
0307 none operator()(Args const &...) const
0308 {
0309 fail();
0310 return none{};
0311 }
0312
0313 void fail() const
0314 {
0315
0316
0317
0318
0319
0320
0321
0322 BOOST_PARSER_DEBUG_ASSERT(false);
0323 }
0324 };
0325 #endif
0326
0327 namespace detail {
0328
0329 #if defined(_MSC_VER)
0330 #pragma warning(push, 3)
0331 #pragma warning(disable : 4307)
0332 #endif
0333 #if defined(__EDG_VERSION__)
0334 namespace print_aux {
0335 template<typename T>
0336 struct dependent_unsigned
0337 {
0338 static const unsigned int value = 1;
0339 };
0340 }
0341 #endif
0342 template<typename T>
0343 struct identity_t
0344 {
0345 using type = T;
0346 };
0347 template<typename T>
0348 struct print_t : identity_t<T>
0349 {
0350 #if defined(__clang__)
0351 #pragma clang diagnostic push
0352 #pragma clang diagnostic ignored "-Wc++11-extensions"
0353 const int x_ = 1 / (sizeof(T) - sizeof(T));
0354 #pragma clang diagnostic pop
0355 #elif defined(_MSC_VER)
0356 enum { n = sizeof(T) + -1 };
0357 #elif defined(__MWERKS__)
0358 void f(int);
0359 #else
0360 enum {
0361 n =
0362 #if defined(__EDG_VERSION__)
0363 print_aux::dependent_unsigned<T>::value > -1
0364 #else
0365 sizeof(T) > -1
0366 #endif
0367 };
0368 #endif
0369 };
0370 #if defined(_MSC_VER)
0371 #pragma warning(pop)
0372 #endif
0373
0374 template<typename T>
0375 using print_type = typename print_t<T>::type;
0376
0377 template<typename R, typename Parser>
0378 struct attribute_impl;
0379
0380
0381
0382 struct nope
0383 {
0384 template<typename T>
0385 constexpr nope & operator=(T const &)
0386 {
0387 return *this;
0388 }
0389
0390 operator std::nullopt_t() const noexcept { return std::nullopt; }
0391
0392 template<typename Context>
0393 constexpr bool operator()(Context const &) const noexcept
0394 {
0395 return true;
0396 }
0397
0398 constexpr nope operator*() const noexcept { return nope{}; }
0399
0400 friend constexpr bool operator==(nope, nope) { return true; }
0401 friend constexpr bool operator!=(nope, nope) { return false; }
0402
0403 template<typename T>
0404 friend constexpr bool operator==(T, nope)
0405 {
0406 return false;
0407 }
0408 template<typename T>
0409 friend constexpr bool operator!=(T, nope)
0410 {
0411 return false;
0412 }
0413 };
0414
0415 inline nope global_nope;
0416
0417 template<typename T>
0418 using parser_interface_tag_expr =
0419 typename T::parser_interface_derivation_tag;
0420 template<typename T>
0421 constexpr bool derived_from_parser_interface_v =
0422 is_detected_v<parser_interface_tag_expr, T>;
0423
0424 template<typename T, bool AlwaysConst = false>
0425 using nope_or_pointer_t = std::conditional_t<
0426 std::is_same_v<std::remove_const_t<T>, nope>,
0427 nope,
0428 std::conditional_t<AlwaysConst, T const *, T *>>;
0429
0430 template<
0431 bool DoTrace,
0432 bool UseCallbacks,
0433 typename I,
0434 typename S,
0435 typename ErrorHandler,
0436 typename GlobalState = nope,
0437 typename Callbacks = nope,
0438 typename Attr = nope,
0439 typename Val = nope,
0440 typename RuleTag = void,
0441 typename RuleLocals = nope,
0442 typename RuleParams = nope,
0443 typename Where = nope>
0444 struct parse_context
0445 {
0446 parse_context() = default;
0447 parse_context(parse_context const &) = default;
0448 parse_context & operator=(parse_context const &) = default;
0449
0450 using rule_tag = RuleTag;
0451
0452 static constexpr bool do_trace = DoTrace;
0453 static constexpr bool use_callbacks = UseCallbacks;
0454
0455 I first_;
0456 S last_;
0457 bool * pass_ = nullptr;
0458 int * trace_indent_ = nullptr;
0459 symbol_table_tries_t * symbol_table_tries_ = nullptr;
0460 pending_symbol_table_operations_t *
0461 pending_symbol_table_operations_ = nullptr;
0462 ErrorHandler const * error_handler_ = nullptr;
0463 nope_or_pointer_t<GlobalState> globals_{};
0464 nope_or_pointer_t<Callbacks, true> callbacks_{};
0465 nope_or_pointer_t<Attr> attr_{};
0466 nope_or_pointer_t<Val> val_{};
0467 nope_or_pointer_t<RuleLocals> locals_{};
0468 nope_or_pointer_t<RuleParams, true> params_{};
0469 nope_or_pointer_t<Where, true> where_{};
0470 int no_case_depth_ = 0;
0471
0472 template<typename T>
0473 static auto nope_or_address(T & x)
0474 {
0475 if constexpr (std::is_same_v<std::remove_const_t<T>, nope>)
0476 return nope{};
0477 else
0478 return std::addressof(x);
0479 }
0480
0481 template<typename T, typename U>
0482 static auto other_or_address(T other, U & x)
0483 {
0484 if constexpr (std::is_same_v<std::remove_const_t<U>, nope>)
0485 return other;
0486 else
0487 return std::addressof(x);
0488 }
0489
0490 parse_context(
0491 std::bool_constant<DoTrace>,
0492 std::bool_constant<UseCallbacks>,
0493 I & first,
0494 S last,
0495 bool & success,
0496 int & indent,
0497 ErrorHandler const & error_handler,
0498 GlobalState & globals,
0499 symbol_table_tries_t & symbol_table_tries,
0500 pending_symbol_table_operations_t &
0501 pending_symbol_table_operations) :
0502 first_(first),
0503 last_(last),
0504 pass_(std::addressof(success)),
0505 trace_indent_(std::addressof(indent)),
0506 symbol_table_tries_(std::addressof(symbol_table_tries)),
0507 pending_symbol_table_operations_(
0508 std::addressof(pending_symbol_table_operations)),
0509 error_handler_(std::addressof(error_handler)),
0510 globals_(nope_or_address(globals))
0511 {}
0512
0513
0514 parse_context(
0515 std::bool_constant<DoTrace>,
0516 std::bool_constant<UseCallbacks>,
0517 I & first,
0518 S last,
0519 bool & success,
0520 int & indent,
0521 ErrorHandler const & error_handler,
0522 Callbacks const & callbacks,
0523 GlobalState & globals,
0524 symbol_table_tries_t & symbol_table_tries,
0525 pending_symbol_table_operations_t &
0526 pending_symbol_table_operations) :
0527 first_(first),
0528 last_(last),
0529 pass_(std::addressof(success)),
0530 trace_indent_(std::addressof(indent)),
0531 symbol_table_tries_(std::addressof(symbol_table_tries)),
0532 pending_symbol_table_operations_(
0533 std::addressof(pending_symbol_table_operations)),
0534 error_handler_(std::addressof(error_handler)),
0535 globals_(nope_or_address(globals)),
0536 callbacks_(std::addressof(callbacks))
0537 {}
0538
0539
0540 template<
0541 typename OldVal,
0542 typename OldRuleTag,
0543 typename OldRuleLocals,
0544 typename OldRuleParams,
0545 typename NewVal,
0546 typename NewRuleTag,
0547 typename NewRuleLocals,
0548 typename NewRuleParams>
0549 parse_context(
0550 parse_context<
0551 DoTrace,
0552 UseCallbacks,
0553 I,
0554 S,
0555 ErrorHandler,
0556 GlobalState,
0557 Callbacks,
0558 Attr,
0559 OldVal,
0560 OldRuleTag,
0561 OldRuleLocals,
0562 OldRuleParams> const & other,
0563 NewRuleTag * tag_ptr,
0564 NewVal & value,
0565 NewRuleLocals & locals,
0566 NewRuleParams const & params) :
0567 first_(other.first_),
0568 last_(other.last_),
0569 pass_(other.pass_),
0570 trace_indent_(other.trace_indent_),
0571 symbol_table_tries_(other.symbol_table_tries_),
0572 pending_symbol_table_operations_(
0573 other.pending_symbol_table_operations_),
0574 error_handler_(other.error_handler_),
0575 globals_(other.globals_),
0576 callbacks_(other.callbacks_),
0577 attr_(other.attr_),
0578 no_case_depth_(other.no_case_depth_)
0579 {
0580 if constexpr (
0581 std::is_same_v<OldRuleTag, NewRuleTag> &&
0582 !std::is_same_v<OldRuleTag, void>) {
0583 val_ = other.val_;
0584 locals_ = other.locals_;
0585 params_ = other.params_;
0586 } else {
0587 val_ = other_or_address(other.val_, value);
0588 locals_ = other_or_address(other.locals_, locals);
0589 params_ = other_or_address(other.params_, params);
0590 }
0591 }
0592
0593
0594 template<typename OldAttr, typename OldWhere>
0595 parse_context(
0596 parse_context<
0597 DoTrace,
0598 UseCallbacks,
0599 I,
0600 S,
0601 ErrorHandler,
0602 GlobalState,
0603 Callbacks,
0604 OldAttr,
0605 Val,
0606 RuleTag,
0607 RuleLocals,
0608 RuleParams,
0609 OldWhere> const & other,
0610 Attr & attr,
0611 Where const & where) :
0612 first_(other.first_),
0613 last_(other.last_),
0614 pass_(other.pass_),
0615 trace_indent_(other.trace_indent_),
0616 symbol_table_tries_(other.symbol_table_tries_),
0617 pending_symbol_table_operations_(
0618 other.pending_symbol_table_operations_),
0619 error_handler_(other.error_handler_),
0620 globals_(other.globals_),
0621 callbacks_(other.callbacks_),
0622 attr_(nope_or_address(attr)),
0623 val_(other.val_),
0624 locals_(other.locals_),
0625 params_(other.params_),
0626 where_(nope_or_address(where)),
0627 no_case_depth_(other.no_case_depth_)
0628 {}
0629 };
0630
0631 template<
0632 bool DoTrace,
0633 bool UseCallbacks,
0634 typename I,
0635 typename S,
0636 typename ErrorHandler,
0637 typename GlobalState,
0638 typename Callbacks,
0639 typename Val,
0640 typename RuleTag,
0641 typename RuleLocals,
0642 typename RuleParams,
0643 typename Attr,
0644 typename Where,
0645 typename OldAttr>
0646 auto make_action_context(
0647 parse_context<
0648 DoTrace,
0649 UseCallbacks,
0650 I,
0651 S,
0652 ErrorHandler,
0653 GlobalState,
0654 Callbacks,
0655 OldAttr,
0656 Val,
0657 RuleTag,
0658 RuleLocals,
0659 RuleParams> const & context,
0660 Attr & attr,
0661 Where const & where)
0662 {
0663 using result_type = parse_context<
0664 DoTrace,
0665 UseCallbacks,
0666 I,
0667 S,
0668 ErrorHandler,
0669 GlobalState,
0670 Callbacks,
0671 Attr,
0672 Val,
0673 RuleTag,
0674 RuleLocals,
0675 RuleParams,
0676 Where>;
0677 return result_type(context, attr, where);
0678 }
0679
0680 template<
0681 bool DoTrace,
0682 bool UseCallbacks,
0683 typename I,
0684 typename S,
0685 typename ErrorHandler,
0686 typename GlobalState,
0687 typename Callbacks,
0688 typename Attr,
0689 typename Val,
0690 typename RuleTag,
0691 typename RuleLocals,
0692 typename RuleParams,
0693 typename NewVal,
0694 typename NewRuleTag,
0695 typename NewRuleLocals,
0696 typename NewRuleParams>
0697 auto make_rule_context(
0698 parse_context<
0699 DoTrace,
0700 UseCallbacks,
0701 I,
0702 S,
0703 ErrorHandler,
0704 GlobalState,
0705 Callbacks,
0706 Attr,
0707 Val,
0708 RuleTag,
0709 RuleLocals,
0710 RuleParams> const & context,
0711 NewRuleTag * tag_ptr,
0712 NewVal & value,
0713 NewRuleLocals & locals,
0714 NewRuleParams const & params)
0715 {
0716 using result_type = parse_context<
0717 DoTrace,
0718 UseCallbacks,
0719 I,
0720 S,
0721 ErrorHandler,
0722 GlobalState,
0723 Callbacks,
0724 Attr,
0725 std::conditional_t<std::is_same_v<NewVal, nope>, Val, NewVal>,
0726 NewRuleTag,
0727 std::conditional_t<
0728 std::is_same_v<NewRuleLocals, nope>,
0729 RuleLocals,
0730 NewRuleLocals>,
0731 std::conditional_t<
0732 std::is_same_v<NewRuleParams, nope>,
0733 RuleParams,
0734 NewRuleParams>>;
0735 return result_type(context, tag_ptr, value, locals, params);
0736 }
0737
0738 template<
0739 bool DoTrace,
0740 bool UseCallbacks,
0741 typename Iter,
0742 typename Sentinel,
0743 typename ErrorHandler>
0744 auto make_context(
0745 Iter first,
0746 Sentinel last,
0747 bool & success,
0748 int & indent,
0749 ErrorHandler const & error_handler,
0750 nope & n,
0751 symbol_table_tries_t & symbol_table_tries,
0752 pending_symbol_table_operations_t &
0753 pending_symbol_table_operations) noexcept
0754 {
0755 return parse_context(
0756 std::bool_constant<DoTrace>{},
0757 std::bool_constant<UseCallbacks>{},
0758 first,
0759 last,
0760 success,
0761 indent,
0762 error_handler,
0763 n,
0764 symbol_table_tries,
0765 pending_symbol_table_operations);
0766 }
0767
0768 template<
0769 bool DoTrace,
0770 bool UseCallbacks,
0771 typename Iter,
0772 typename Sentinel,
0773 typename ErrorHandler,
0774 typename GlobalState>
0775 auto make_context(
0776 Iter first,
0777 Sentinel last,
0778 bool & success,
0779 int & indent,
0780 ErrorHandler const & error_handler,
0781 GlobalState & globals,
0782 symbol_table_tries_t & symbol_table_tries,
0783 pending_symbol_table_operations_t &
0784 pending_symbol_table_operations) noexcept
0785 {
0786 return parse_context(
0787 std::bool_constant<DoTrace>{},
0788 std::bool_constant<UseCallbacks>{},
0789 first,
0790 last,
0791 success,
0792 indent,
0793 error_handler,
0794 globals,
0795 symbol_table_tries,
0796 pending_symbol_table_operations);
0797 }
0798
0799 template<
0800 bool DoTrace,
0801 bool UseCallbacks,
0802 typename Iter,
0803 typename Sentinel,
0804 typename ErrorHandler,
0805 typename Callbacks>
0806 auto make_context(
0807 Iter first,
0808 Sentinel last,
0809 bool & success,
0810 int & indent,
0811 ErrorHandler const & error_handler,
0812 Callbacks const & callbacks,
0813 nope & n,
0814 symbol_table_tries_t & symbol_table_tries,
0815 pending_symbol_table_operations_t &
0816 pending_symbol_table_operations) noexcept
0817 {
0818 return parse_context(
0819 std::bool_constant<DoTrace>{},
0820 std::bool_constant<UseCallbacks>{},
0821 first,
0822 last,
0823 success,
0824 indent,
0825 error_handler,
0826 callbacks,
0827 n,
0828 symbol_table_tries,
0829 pending_symbol_table_operations);
0830 }
0831
0832 template<
0833 bool DoTrace,
0834 bool UseCallbacks,
0835 typename Iter,
0836 typename Sentinel,
0837 typename ErrorHandler,
0838 typename Callbacks,
0839 typename GlobalState>
0840 auto make_context(
0841 Iter first,
0842 Sentinel last,
0843 bool & success,
0844 int & indent,
0845 ErrorHandler const & error_handler,
0846 Callbacks const & callbacks,
0847 GlobalState & globals,
0848 symbol_table_tries_t & symbol_table_tries,
0849 pending_symbol_table_operations_t &
0850 pending_symbol_table_operations) noexcept
0851 {
0852 return parse_context(
0853 std::bool_constant<DoTrace>{},
0854 std::bool_constant<UseCallbacks>{},
0855 first,
0856 last,
0857 success,
0858 indent,
0859 error_handler,
0860 callbacks,
0861 globals,
0862 symbol_table_tries,
0863 pending_symbol_table_operations);
0864 }
0865
0866
0867 template<unsigned int I>
0868 struct param_t
0869 {
0870 template<typename Context>
0871 decltype(auto) operator()(Context const & context) const
0872 {
0873 return parser::get(parser::_params(context), llong<I>{});
0874 }
0875 };
0876
0877
0878 template<typename T, typename... Args>
0879 using callable = decltype(std::declval<T>()(std::declval<Args>()...));
0880
0881 template<
0882 typename Context,
0883 typename T,
0884 bool Callable = is_detected_v<callable, T const &, Context const &>>
0885 struct resolve_impl
0886 {
0887 static auto call(Context const &, T const & x) { return x; }
0888 };
0889
0890 template<typename Context, typename T>
0891 struct resolve_impl<Context, T, true>
0892 {
0893 static auto call(Context const & context, T const & x)
0894 {
0895 return x(context);
0896 }
0897 };
0898
0899 template<typename Context, typename T>
0900 auto resolve(Context const & context, T const & x)
0901 {
0902 return resolve_impl<Context, T>::call(context, x);
0903 }
0904
0905 template<typename Context>
0906 auto resolve(Context const &, nope n)
0907 {
0908 return n;
0909 }
0910
0911
0912 template<typename Context, typename ParamsTuple>
0913 auto
0914 resolve_rule_params(Context const & context, ParamsTuple const & params)
0915 {
0916 return detail::hl::transform(params, [&](auto const & x) {
0917 return detail::resolve(context, x);
0918 });
0919 }
0920
0921 template<typename Context>
0922 nope resolve_rule_params(Context const & context, nope)
0923 {
0924 return {};
0925 }
0926
0927 template<typename LocalsType, typename Context>
0928 LocalsType make_locals_impl(Context const & context, std::true_type)
0929 {
0930 return LocalsType(context);
0931 }
0932
0933 template<typename LocalsType, typename Context>
0934 LocalsType make_locals_impl(Context const & context, std::false_type)
0935 {
0936 return LocalsType();
0937 }
0938
0939 template<typename LocalsType, typename Context>
0940 LocalsType make_locals(Context const & context)
0941 {
0942 return detail::make_locals_impl<LocalsType>(
0943 context,
0944 typename std::is_convertible<Context const &, LocalsType>::
0945 type{});
0946 }
0947
0948
0949 template<typename Context>
0950 decltype(auto) _indent(Context const & context)
0951 {
0952 return *context.trace_indent_;
0953 }
0954
0955 template<typename Context>
0956 decltype(auto) _callbacks(Context const & context)
0957 {
0958 return *context.callbacks_;
0959 }
0960
0961
0962
0963
0964 template<typename T>
0965 using remove_cv_ref_t = typename std::remove_cv<
0966 typename std::remove_reference<T>::type>::type;
0967
0968 template<typename T, typename U>
0969 using comparison = decltype(std::declval<T>() == std::declval<U>());
0970
0971 template<typename T, typename U>
0972 constexpr bool is_equality_comparable_with_v =
0973 is_detected_v<comparison, T, U>;
0974
0975 template<typename T>
0976 struct is_nope : std::false_type
0977 {};
0978 template<>
0979 struct is_nope<nope> : std::true_type
0980 {};
0981 template<typename T>
0982 constexpr bool is_nope_v = is_nope<remove_cv_ref_t<T>>::value;
0983
0984 template<typename T>
0985 struct is_eps_p : std::false_type
0986 {};
0987 template<typename T>
0988 struct is_eps_p<eps_parser<T>> : std::true_type
0989 {};
0990
0991 template<typename T>
0992 struct is_unconditional_eps : std::false_type
0993 {};
0994 template<>
0995 struct is_unconditional_eps<eps_parser<nope>> : std::true_type
0996 {};
0997 template<typename T>
0998 constexpr bool is_unconditional_eps_v =
0999 is_unconditional_eps<remove_cv_ref_t<T>>::value;
1000
1001 template<typename T>
1002 struct is_zero_plus_p : std::false_type
1003 {};
1004 template<typename T>
1005 struct is_zero_plus_p<zero_plus_parser<T>> : std::true_type
1006 {};
1007
1008 template<typename T>
1009 struct is_or_p : std::false_type
1010 {};
1011 template<typename T>
1012 struct is_or_p<or_parser<T>> : std::true_type
1013 {};
1014
1015 template<typename T>
1016 struct is_perm_p : std::false_type
1017 {};
1018 template<typename T, typename DelimiterParser>
1019 struct is_perm_p<perm_parser<T, DelimiterParser>> : std::true_type
1020 {};
1021
1022 template<typename T>
1023 struct is_seq_p : std::false_type
1024 {};
1025 template<typename T, typename U, typename V>
1026 struct is_seq_p<seq_parser<T, U, V>> : std::true_type
1027 {};
1028
1029 template<typename T>
1030 struct is_one_plus_p : std::false_type
1031 {};
1032 template<typename T>
1033 struct is_one_plus_p<one_plus_parser<T>> : std::true_type
1034 {};
1035
1036 template<typename T>
1037 struct is_utf8_view : std::false_type
1038 {};
1039 template<typename V>
1040 struct is_utf8_view<text::utf8_view<V>> : std::true_type
1041 {};
1042
1043 template<typename T>
1044 using optional_type = remove_cv_ref_t<decltype(*std::declval<T &>())>;
1045
1046 template<typename F, typename... Args>
1047 constexpr bool is_invocable_v = is_detected_v<callable, F, Args...>;
1048
1049 template<typename T>
1050 using has_begin =
1051 decltype(*detail::text::detail::begin(std::declval<T &>()));
1052 template<typename T>
1053 using has_end =
1054 decltype(detail::text::detail::end(std::declval<T &>()));
1055
1056 template<typename T>
1057 constexpr bool is_range =
1058 is_detected_v<has_begin, T> && is_detected_v<has_end, T>;
1059
1060 template<typename T>
1061 using has_push_back =
1062 decltype(std::declval<T &>().push_back(*std::declval<T>().begin()));
1063
1064 #if BOOST_PARSER_USE_CONCEPTS
1065
1066 template<typename T>
1067 using iterator_t = std::ranges::iterator_t<T>;
1068 template<typename T>
1069 using sentinel_t = std::ranges::sentinel_t<T>;
1070 template<typename T>
1071 using iter_value_t = std::iter_value_t<T>;
1072 template<typename T>
1073 using iter_reference_t = std::iter_reference_t<T>;
1074 template<typename T>
1075 using range_value_t = std::ranges::range_value_t<T>;
1076 template<typename T>
1077 using range_reference_t = std::ranges::range_reference_t<T>;
1078 template<typename T>
1079 using range_rvalue_reference_t =
1080 std::ranges::range_rvalue_reference_t<T>;
1081
1082 template<typename T>
1083 constexpr bool is_parsable_code_unit_v = code_unit<T>;
1084
1085 #else
1086
1087 template<typename T>
1088 using iterator_t =
1089 decltype(detail::text::detail::begin(std::declval<T &>()));
1090 template<typename Range>
1091 using sentinel_t =
1092 decltype(detail::text::detail::end(std::declval<Range &>()));
1093 template<typename T>
1094 using iter_value_t = typename std::iterator_traits<T>::value_type;
1095 template<typename T>
1096 using iter_reference_t = decltype(*std::declval<T &>());
1097 template<typename T>
1098 using iter_rvalue_reference_t =
1099 decltype(std::move(*std::declval<T &>()));
1100 template<typename T>
1101 using range_value_t = iter_value_t<iterator_t<T>>;
1102 template<typename T>
1103 using range_reference_t = iter_reference_t<iterator_t<T>>;
1104 template<typename T>
1105 using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<T>>;
1106
1107 template<typename T>
1108 using has_insert = decltype(std::declval<T &>().insert(
1109 std::declval<T>().begin(), *std::declval<T>().begin()));
1110 template<typename T>
1111 using has_range_insert = decltype(std::declval<T &>().insert(
1112 std::declval<T>().begin(),
1113 std::declval<T>().begin(),
1114 std::declval<T>().end()));
1115
1116 template<typename T>
1117 constexpr bool is_container_v = is_detected_v<has_insert, T>;
1118
1119 template<typename T, typename U>
1120 constexpr bool container_and_value_type =
1121 is_container_v<T> &&
1122 (std::is_same_v<detected_t<range_value_t, T>, U> ||
1123 (std::is_same_v<T, std::string> && std::is_same_v<U, char32_t>));
1124
1125 template<typename T>
1126 constexpr bool is_parsable_code_unit_impl =
1127 std::is_same_v<T, char> || std::is_same_v<T, wchar_t> ||
1128 #if defined(__cpp_char8_t)
1129 std::is_same_v<T, char8_t> ||
1130 #endif
1131 std::is_same_v<T, char16_t> || std::is_same_v<T, char32_t>;
1132
1133 template<typename T>
1134 constexpr bool is_parsable_code_unit_v =
1135 is_parsable_code_unit_impl<std::remove_cv_t<T>>;
1136
1137 template<typename T>
1138 constexpr bool is_parsable_iter_v = is_parsable_code_unit_v<
1139 remove_cv_ref_t<detected_t<iter_value_t, T>>>;
1140
1141 template<typename T>
1142 constexpr bool is_parsable_range_v = is_parsable_code_unit_v<
1143 remove_cv_ref_t<detected_t<has_begin, T>>> &&
1144 is_detected_v<has_end, T>;
1145
1146 template<typename T>
1147 constexpr bool is_parsable_pointer_v =
1148 std::is_pointer_v<remove_cv_ref_t<T>> && is_parsable_code_unit_v<
1149 std::remove_pointer_t<remove_cv_ref_t<T>>>;
1150
1151 template<typename T>
1152 constexpr bool is_parsable_range_like_v =
1153 is_parsable_range_v<T> || is_parsable_pointer_v<T>;
1154 }
1155
1156 template<typename T>
1157 constexpr bool container = detail::is_container_v<T>;
1158
1159 namespace detail {
1160 #endif
1161
1162 template<typename T, bool = std::is_pointer_v<T>>
1163 constexpr bool is_code_unit_pointer_v = false;
1164 template<typename T>
1165 constexpr bool is_code_unit_pointer_v<T, true> =
1166 is_parsable_code_unit_v<std::remove_pointer_t<T>>;
1167
1168 template<typename T>
1169 constexpr bool is_range_like = is_range<T> || is_code_unit_pointer_v<T>;
1170
1171 template<typename I>
1172 constexpr bool is_char8_iter_v =
1173 #if defined(__cpp_char8_t)
1174 std::is_same_v<iter_value_t<I>, char8_t>
1175 #else
1176 false
1177 #endif
1178 ;
1179
1180
1181
1182 template<bool WrapInOptional, typename Tuple>
1183 struct to_hana_tuple_or_type_impl;
1184
1185 template<typename... T>
1186 struct to_hana_tuple_or_type_impl<true, tuple<T...>>
1187 {
1188 using type = std::optional<std::variant<T...>>;
1189 };
1190
1191 template<typename... T>
1192 struct to_hana_tuple_or_type_impl<false, tuple<T...>>
1193 {
1194 using type = std::variant<T...>;
1195 };
1196
1197 template<typename T>
1198 struct to_hana_tuple_or_type_impl<true, tuple<T>>
1199 {
1200
1201
1202
1203 using type =
1204 std::conditional_t<is_optional_v<T>, T, std::optional<T>>;
1205 };
1206
1207 template<typename T>
1208 struct to_hana_tuple_or_type_impl<false, tuple<T>>
1209 {
1210 using type = T;
1211 };
1212
1213 template<>
1214 struct to_hana_tuple_or_type_impl<true, tuple<>>
1215 {
1216 using type = nope;
1217 };
1218
1219 template<>
1220 struct to_hana_tuple_or_type_impl<false, tuple<>>
1221 {
1222 using type = nope;
1223 };
1224
1225 template<typename Pair>
1226 struct to_hana_tuple_or_type;
1227
1228 template<typename Tuple, typename TrueFalse>
1229 struct to_hana_tuple_or_type<tuple<Tuple, TrueFalse>>
1230 {
1231
1232 using type =
1233 typename to_hana_tuple_or_type_impl<TrueFalse::value, Tuple>::
1234 type;
1235 };
1236
1237 template<typename T>
1238 using to_hana_tuple_or_type_t = typename to_hana_tuple_or_type<T>::type;
1239
1240 template<typename T>
1241 auto make_sequence_of()
1242 {
1243 if constexpr (
1244 std::is_same_v<T, char> || std::is_same_v<T, char32_t>) {
1245 return std::string{};
1246 } else if constexpr (std::is_same_v<T, nope>) {
1247 return nope{};
1248 } else {
1249 return std::vector<T>{};
1250 }
1251 }
1252
1253 template<typename T>
1254 constexpr bool is_char_type_v =
1255 std::is_same_v<T, char> || std::is_same_v<T, char32_t>;
1256
1257 template<typename T>
1258 struct optional_of_impl
1259 {
1260 using type = std::optional<T>;
1261 };
1262
1263 template<typename T>
1264 struct optional_of_impl<std::optional<T>>
1265 {
1266 using type = std::optional<T>;
1267 };
1268
1269 template<>
1270 struct optional_of_impl<nope>
1271 {
1272 using type = nope;
1273 };
1274
1275 template<typename T>
1276 using optional_of = typename optional_of_impl<T>::type;
1277
1278 template<typename T>
1279 struct unwrapped_optional
1280 {
1281 using type = T;
1282 };
1283 template<typename T>
1284 struct unwrapped_optional<std::optional<T>>
1285 {
1286 using type = T;
1287 };
1288 template<typename T>
1289 using unwrapped_optional_t = typename unwrapped_optional<T>::type;
1290
1291
1292
1293
1294
1295 template<typename T>
1296 struct wrapper
1297 {
1298 using type = T;
1299
1300 constexpr bool operator==(wrapper) const { return true; }
1301 };
1302
1303 struct wrap
1304 {
1305 template<typename T>
1306 constexpr auto operator()(T type) const
1307 {
1308 return wrapper<T>{};
1309 }
1310 };
1311
1312 struct unwrap
1313 {
1314 template<typename T>
1315 constexpr auto operator()(T wrapped_type) const
1316 {
1317 return typename T::type{};
1318 }
1319 };
1320
1321 template<typename Container, typename T>
1322 void insert(Container & c, T && x)
1323 {
1324 if constexpr (is_detected_v<has_push_back, Container>) {
1325 c.push_back((T &&) x);
1326 } else {
1327 c.insert((T &&) x);
1328 }
1329 }
1330
1331 template<typename Container, typename I>
1332 void insert(Container & c, I first, I last)
1333 {
1334 std::for_each(first, last, [&](auto && x) {
1335 using type = decltype(x);
1336 insert(c, (type &&) x);
1337 });
1338 }
1339
1340 template<typename Container, typename T>
1341 constexpr bool needs_transcoding_to_utf8 =
1342 (std::is_same_v<range_value_t<remove_cv_ref_t<Container>>, char>
1343 #if defined(__cpp_char8_t)
1344 || std::is_same_v<range_value_t<remove_cv_ref_t<Container>>, char8_t>
1345 #endif
1346 ) && (std::is_same_v<remove_cv_ref_t<T>, char32_t>
1347 #if !defined(_MSC_VER)
1348 || std::is_same_v<remove_cv_ref_t<T>, wchar_t>
1349 #endif
1350 );
1351
1352 template<typename Container, typename T>
1353 void append(Container & c, T && x, bool gen_attrs)
1354 {
1355 if (!gen_attrs)
1356 return;
1357 if constexpr (needs_transcoding_to_utf8<Container, T>) {
1358 char32_t cps[1] = {(char32_t)x};
1359 auto const r = cps | text::as_utf8;
1360 c.insert(c.end(), r.begin(), r.end());
1361 } else {
1362 detail::insert(c, std::move(x));
1363 }
1364 }
1365
1366 template<typename Container, typename T>
1367 void append(std::optional<Container> & c, T && x, bool gen_attrs)
1368 {
1369 if (!gen_attrs)
1370 return;
1371 if (!c)
1372 c = Container();
1373 return detail::append(*c, (T &&) x, gen_attrs);
1374 }
1375
1376 template<typename Container>
1377 void append(Container & c, nope &&, bool)
1378 {}
1379
1380 template<typename T>
1381 void append(nope &, T &&, bool)
1382 {}
1383
1384 inline void append(nope &, nope &&, bool) {}
1385
1386 template<typename Container, typename Iter, typename Sentinel>
1387 void append(Container & c, Iter first, Sentinel last, bool gen_attrs)
1388 {
1389 if (!gen_attrs)
1390 return;
1391 if constexpr (needs_transcoding_to_utf8<
1392 Container,
1393 iter_value_t<Iter>>) {
1394 auto const r =
1395 BOOST_PARSER_SUBRANGE(first, last) | text::as_utf8;
1396 c.insert(c.end(), r.begin(), r.end());
1397 } else {
1398 detail::insert(c, first, last);
1399 }
1400 }
1401
1402 template<typename Container, typename Iter, typename Sentinel>
1403 void append(
1404 std::optional<Container> & c,
1405 Iter first,
1406 Sentinel last,
1407 bool gen_attrs)
1408 {
1409 if (!gen_attrs)
1410 return;
1411 if (!c)
1412 c = Container();
1413 return detail::append(*c, first, last, gen_attrs);
1414 }
1415
1416 template<typename Iter, typename Sentinel>
1417 void append(nope &, Iter first, Sentinel last, bool gen_attrs)
1418 {}
1419
1420 constexpr inline flags default_flags()
1421 {
1422 return flags(
1423 uint32_t(flags::gen_attrs) | uint32_t(flags::use_skip));
1424 }
1425 constexpr inline flags enable_skip(flags f)
1426 {
1427 return flags(uint32_t(f) | uint32_t(flags::use_skip));
1428 }
1429 constexpr inline flags disable_skip(flags f)
1430 {
1431 return flags(uint32_t(f) & ~uint32_t(flags::use_skip));
1432 }
1433 constexpr inline flags enable_attrs(flags f)
1434 {
1435 return flags(uint32_t(f) | uint32_t(flags::gen_attrs));
1436 }
1437 constexpr inline flags disable_attrs(flags f)
1438 {
1439 return flags(uint32_t(f) & ~uint32_t(flags::gen_attrs));
1440 }
1441 constexpr inline flags enable_trace(flags f)
1442 {
1443 return flags(uint32_t(f) | uint32_t(flags::trace));
1444 }
1445 constexpr inline flags disable_trace(flags f)
1446 {
1447 return flags(uint32_t(f) & ~uint32_t(flags::trace));
1448 }
1449 constexpr inline flags set_in_apply_parser(flags f)
1450 {
1451 return flags(uint32_t(f) | uint32_t(flags::in_apply_parser));
1452 }
1453 constexpr inline bool gen_attrs(flags f)
1454 {
1455 return (uint32_t(f) & uint32_t(flags::gen_attrs)) ==
1456 uint32_t(flags::gen_attrs);
1457 }
1458 constexpr inline bool use_skip(flags f)
1459 {
1460 return (uint32_t(f) & uint32_t(flags::use_skip)) ==
1461 uint32_t(flags::use_skip);
1462 }
1463 constexpr inline bool in_apply_parser(flags f)
1464 {
1465 return (uint32_t(f) & uint32_t(flags::in_apply_parser)) ==
1466 uint32_t(flags::in_apply_parser);
1467 }
1468
1469 struct null_parser
1470 {};
1471
1472 struct skip_skipper
1473 {
1474 template<
1475 typename Iter,
1476 typename Sentinel,
1477 typename Context,
1478 typename SkipParser>
1479 nope operator()(
1480 Iter & first,
1481 Sentinel last,
1482 Context const & context,
1483 SkipParser const & skip,
1484 flags flags,
1485 bool & success) const noexcept
1486 {
1487 return {};
1488 }
1489
1490 template<
1491 typename Iter,
1492 typename Sentinel,
1493 typename Context,
1494 typename SkipParser,
1495 typename Attribute>
1496 void operator()(
1497 Iter & first,
1498 Sentinel last,
1499 Context const & context,
1500 SkipParser const & skip,
1501 flags flags,
1502 bool & success,
1503 Attribute & retval) const
1504 {}
1505 };
1506
1507 template<typename Iter, typename Sentinel>
1508 void
1509 skip(Iter & first, Sentinel last, null_parser const & skip_, flags f)
1510 {}
1511
1512 template<typename Iter, typename Sentinel, typename SkipParser>
1513 void
1514 skip(Iter & first, Sentinel last, SkipParser const & skip_, flags f)
1515 {
1516 if (!detail::use_skip(f))
1517 return;
1518 bool success = true;
1519 int indent = 0;
1520 rethrow_error_handler eh;
1521 nope n;
1522 symbol_table_tries_t symbol_table_tries;
1523 pending_symbol_table_operations_t pending_symbol_table_operations;
1524 auto const context = detail::make_context<false, false>(
1525 first,
1526 last,
1527 success,
1528 indent,
1529 eh,
1530 n,
1531 symbol_table_tries,
1532 pending_symbol_table_operations);
1533 while (success) {
1534 skip_(
1535 first,
1536 last,
1537 context,
1538 skip_skipper{},
1539 detail::disable_trace(detail::disable_skip(f)),
1540 success);
1541 }
1542 }
1543
1544 enum : int64_t { unbounded = -1 };
1545
1546 template<typename T>
1547 std::optional<T> make_parse_result(T & x, bool success)
1548 {
1549 std::optional<T> retval;
1550 if (success)
1551 retval = x;
1552 return retval;
1553 }
1554
1555 inline bool make_parse_result(nope &, bool success) { return success; }
1556 inline bool make_parse_result(none &, bool success) { return success; }
1557
1558 template<typename LoType, typename HiType>
1559 struct char_pair
1560 {
1561 LoType lo_;
1562 HiType hi_;
1563 };
1564
1565 using case_fold_array_t = std::array<char32_t, detail::longest_mapping>;
1566
1567 template<typename I, typename S>
1568 struct no_case_iter : stl_interfaces::proxy_iterator_interface<
1569 no_case_iter<I, S>,
1570 std::forward_iterator_tag,
1571 char32_t>
1572 {
1573 no_case_iter() : it_(), last_(), idx_(0), last_idx_() {}
1574 no_case_iter(I it, S last) :
1575 it_(it), last_(last), idx_(0), last_idx_(0)
1576 {
1577 fold();
1578 }
1579
1580 char32_t operator*() const { return folded_[idx_]; }
1581 no_case_iter & operator++()
1582 {
1583 ++idx_;
1584 if (last_idx_ <= idx_) {
1585 ++it_;
1586 fold();
1587 }
1588 return *this;
1589 }
1590 I base() const { return it_; }
1591 friend bool operator==(no_case_iter lhs, S rhs) noexcept
1592 {
1593 return lhs.it_ == rhs;
1594 }
1595 friend bool operator==(no_case_iter lhs, no_case_iter rhs) noexcept
1596 {
1597 return lhs.it_ == rhs.it_ && lhs.idx_ == rhs.idx_;
1598 }
1599
1600 using base_type = stl_interfaces::proxy_iterator_interface<
1601 no_case_iter<I, S>,
1602 std::forward_iterator_tag,
1603 char32_t>;
1604 using base_type::operator++;
1605
1606 private:
1607 void fold()
1608 {
1609 idx_ = 0;
1610 if (it_ == last_) {
1611 folded_[0] = 0;
1612 last_idx_ = 1;
1613 return;
1614 }
1615 auto const folded_last =
1616 detail::case_fold(*it_, folded_.begin());
1617 last_idx_ = int(folded_last - folded_.begin());
1618 }
1619
1620 case_fold_array_t folded_;
1621 I it_;
1622 [[no_unique_address]] S last_;
1623 int idx_;
1624 int last_idx_;
1625 };
1626
1627 template<typename V>
1628 struct case_fold_view
1629 {
1630 using iterator =
1631 no_case_iter<detail::iterator_t<V>, detail::sentinel_t<V>>;
1632
1633 case_fold_view(V base) : base_(std::move(base)) {}
1634
1635 iterator begin() const
1636 {
1637 return iterator(
1638 text::detail::begin(base_), text::detail::end(base_));
1639 }
1640 auto end() const { return text::detail::end(base_); }
1641
1642 private:
1643 V base_;
1644 };
1645
1646 enum class symbol_table_op { insert, erase, clear };
1647
1648 template<typename T>
1649 struct symbol_table_operation
1650 {
1651 std::string key_;
1652 std::optional<T> value_;
1653 symbol_table_op kind_;
1654 };
1655
1656 template<typename T>
1657 void apply_symbol_table_operations(
1658 std::vector<std::pair<std::string, T>> & initial_elements,
1659 std::vector<symbol_table_operation<T>> & pending_operations)
1660 {
1661 auto lower_bound = [&initial_elements](std::string const & str) {
1662 return std::lower_bound(
1663 initial_elements.begin(),
1664 initial_elements.end(),
1665 str,
1666 [](auto const & a, auto b) {
1667 return a.first < b;
1668 });
1669 };
1670
1671 for (auto & op : pending_operations) {
1672 if (op.kind_ == symbol_table_op::insert) {
1673 auto it = lower_bound(op.key_);
1674 if (it == initial_elements.end() ||
1675 it->first != op.key_) {
1676 initial_elements.insert(
1677 it,
1678 std::pair<std::string, T>(
1679 std::move(op.key_), std::move(*op.value_)));
1680 } else {
1681 it->second = std::move(*op.value_);
1682 }
1683 } else if (op.kind_ == symbol_table_op::erase) {
1684 auto it = lower_bound(op.key_);
1685 if (it != initial_elements.end() && it->first == op.key_)
1686 initial_elements.erase(it);
1687 } else {
1688 initial_elements.clear();
1689 }
1690 }
1691
1692 pending_operations.clear();
1693 }
1694
1695 template<typename Context, typename T>
1696 auto get_trie(
1697 Context const & context, symbol_parser<T> const & sym_parser)
1698 {
1699 using trie_t = text::trie_map<std::vector<char32_t>, T>;
1700 using result_type = std::pair<trie_t &, bool>;
1701 symbol_table_tries_t & symbol_table_tries =
1702 *context.symbol_table_tries_;
1703
1704 auto & [any, has_case_folded] =
1705 symbol_table_tries[(void *)&sym_parser.ref()];
1706
1707 bool const needs_case_folded = context.no_case_depth_;
1708
1709 if (!any.has_value()) {
1710 any = trie_t{};
1711 has_case_folded = false;
1712 trie_t & trie = *std::any_cast<trie_t>(&any);
1713 for (auto const & e : sym_parser.initial_elements()) {
1714 trie.insert(e.first | text::as_utf32, e.second);
1715 if (needs_case_folded) {
1716 trie.insert(
1717 case_fold_view(e.first | text::as_utf32), e.second);
1718 has_case_folded = true;
1719 }
1720 }
1721 return result_type(trie, has_case_folded);
1722 } else {
1723 trie_t & trie = *std::any_cast<trie_t>(&any);
1724 if (needs_case_folded && !has_case_folded) {
1725 trie_t new_trie = trie;
1726 for (auto && [key, value] : trie) {
1727 new_trie.insert(
1728 case_fold_view(key | text::as_utf32), value);
1729 }
1730 std::swap(new_trie, trie);
1731 }
1732 return result_type(trie, has_case_folded);
1733 }
1734 }
1735
1736 template<typename Context, typename T>
1737 decltype(auto) get_pending_symtab_ops(
1738 Context const & context, symbol_parser<T> const & sym_parser)
1739 {
1740 void const * ptr = static_cast<void const *>(&sym_parser);
1741 auto & entry = (*context.pending_symbol_table_operations_)[ptr];
1742 std::vector<detail::symbol_table_operation<T>> * retval = nullptr;
1743 if (entry.visit_) {
1744 retval = std::any_cast<
1745 std::vector<detail::symbol_table_operation<T>>>(
1746 &entry.ops_);
1747 } else {
1748 entry.ops_ = std::vector<detail::symbol_table_operation<T>>{};
1749 retval = std::any_cast<
1750 std::vector<detail::symbol_table_operation<T>>>(
1751 &entry.ops_);
1752 entry.visit_ = [&sym_parser, ops_ptr = retval] {
1753 detail::apply_symbol_table_operations(
1754 sym_parser.initial_elements_, *ops_ptr);
1755 };
1756 }
1757 return *retval;
1758 }
1759
1760 template<>
1761 struct char_subranges<hex_digit_subranges>
1762 {
1763 static constexpr char_subrange ranges[] = {
1764 {U'0', U'9'},
1765 {U'A', U'F'},
1766 {U'a', U'f'},
1767 {U'\uff10', U'\uff19'},
1768 {U'\uff21', U'\uff26'},
1769 {U'\uff41', U'\uff46'}};
1770 };
1771
1772 template<>
1773 struct char_subranges<control_subranges>
1774 {
1775 static constexpr char_subrange ranges[] = {
1776 {U'\u0000', U'\u001f'}, {U'\u007f', U'\u009f'}};
1777 };
1778
1779 template<typename Iter, typename Sentinel, bool SortedUTF32>
1780 struct char_range
1781 {
1782 template<typename T, typename Context>
1783 bool contains(T c_, Context const & context) const
1784 {
1785 if constexpr (SortedUTF32) {
1786 return std::binary_search(chars_.begin(), chars_.end(), c_);
1787 }
1788
1789 if (context.no_case_depth_) {
1790 case_fold_array_t folded;
1791 auto folded_last = detail::case_fold(c_, folded.begin());
1792 if constexpr (std::is_same_v<T, char32_t>) {
1793 auto const cps = chars_ | text::as_utf32;
1794 auto chars_first = no_case_iter(cps.begin(), cps.end());
1795 auto chars_last = cps.end();
1796 auto result = text::search(
1797 chars_first,
1798 chars_last,
1799 folded.begin(),
1800 folded_last);
1801 return !result.empty();
1802 } else {
1803 auto chars_first =
1804 no_case_iter(chars_.begin(), chars_.end());
1805 auto chars_last = chars_.end();
1806 auto result = text::search(
1807 chars_first,
1808 chars_last,
1809 folded.begin(),
1810 folded_last);
1811 return !result.empty();
1812 }
1813 } else {
1814 if constexpr (std::is_same_v<T, char32_t>) {
1815 auto const cps = chars_ | text::as_utf32;
1816 return text::find(cps.begin(), cps.end(), c_) !=
1817 cps.end();
1818 } else {
1819 using element_type =
1820 remove_cv_ref_t<decltype(*chars_.begin())>;
1821 element_type const c = c_;
1822 return text::find(chars_.begin(), chars_.end(), c) !=
1823 chars_.end();
1824 }
1825 }
1826 }
1827
1828 BOOST_PARSER_SUBRANGE<Iter, Sentinel> chars_;
1829 };
1830
1831 template<bool SortedUTF32, typename Iter, typename Sentinel>
1832 constexpr auto make_char_range(Iter first, Sentinel last)
1833 {
1834 return char_range<Iter, Sentinel, SortedUTF32>{
1835 BOOST_PARSER_SUBRANGE<Iter, Sentinel>{first, last}};
1836 }
1837
1838 template<bool SortedUTF32, typename R>
1839 constexpr auto make_char_range(R && r) noexcept
1840 {
1841 if constexpr (std::is_pointer_v<remove_cv_ref_t<R>>) {
1842 return detail::make_char_range<SortedUTF32>(
1843 r, text::null_sentinel);
1844 } else {
1845 return detail::make_char_range<SortedUTF32>(
1846 text::detail::begin(r), text::detail::end(r));
1847 }
1848 }
1849
1850 template<bool Equal, typename Context>
1851 auto no_case_aware_compare(Context const & context)
1852 {
1853 return [no_case = context.no_case_depth_](char32_t a, char32_t b) {
1854 if (no_case) {
1855 case_fold_array_t folded_a = {0, 0, 0};
1856 detail::case_fold(a, folded_a.begin());
1857 case_fold_array_t folded_b = {0, 0, 0};
1858 detail::case_fold(b, folded_b.begin());
1859 return Equal ? folded_a == folded_b : folded_a < folded_b;
1860 } else {
1861 return Equal ? a == b : a < b;
1862 }
1863 };
1864 }
1865
1866 template<typename T, typename U>
1867 constexpr bool both_character_types =
1868 is_parsable_code_unit_v<T> && is_parsable_code_unit_v<U>;
1869
1870 template<typename T, typename U>
1871 using eq_comparable =
1872 decltype(std::declval<T &>() == std::declval<U &>());
1873
1874 template<
1875 typename Context,
1876 typename CharType,
1877 typename Expected,
1878 bool BothCharacters = both_character_types<CharType, Expected>>
1879 struct unequal_impl
1880 {
1881 static bool
1882 call(Context const & context, CharType c, Expected const & expected)
1883 {
1884 auto resolved = detail::resolve(context, expected);
1885 if constexpr (is_detected_v<
1886 eq_comparable,
1887 CharType,
1888 decltype(resolved)>) {
1889 auto const compare =
1890 detail::no_case_aware_compare<true>(context);
1891 return !compare(c, resolved);
1892 } else {
1893 return !resolved.contains(c, context);
1894 }
1895 }
1896 };
1897
1898 template<typename Context, typename CharType, typename Expected>
1899 struct unequal_impl<Context, CharType, Expected, true>
1900 {
1901 static bool
1902 call(Context const & context, CharType c, Expected expected)
1903 {
1904
1905 return !detail::no_case_aware_compare<true>(context)(
1906 c, expected);
1907 }
1908 };
1909
1910 template<typename Context, typename CharType, typename Expected>
1911 bool unequal(Context const & context, CharType c, Expected expected)
1912 {
1913 return unequal_impl<Context, CharType, Expected>::call(
1914 context, c, expected);
1915 }
1916
1917 template<
1918 typename Context,
1919 typename CharType,
1920 typename LoType,
1921 typename HiType>
1922 bool unequal(
1923 Context const & context,
1924 CharType c,
1925 char_pair<LoType, HiType> const & expected)
1926 {
1927 auto const less = detail::no_case_aware_compare<false>(context);
1928 {
1929 auto lo = detail::resolve(context, expected.lo_);
1930 if (less(c, lo))
1931 return true;
1932 }
1933 {
1934 auto hi = detail::resolve(context, expected.hi_);
1935 if (less(hi, c))
1936 return true;
1937 }
1938 return false;
1939 }
1940
1941 template<typename Context, typename CharType>
1942 bool unequal(Context const &, CharType, nope)
1943 {
1944 return false;
1945 }
1946
1947 template<typename Container, typename T>
1948 using insertable = decltype(std::declval<Container &>().insert(
1949 std::declval<Container &>().end(), std::declval<T>()));
1950
1951 template<typename T, typename Tuple, int... Is>
1952 auto
1953 make_from_tuple_impl(Tuple && tup, std::integer_sequence<int, Is...>)
1954 -> decltype(T(parser::get(std::move(tup), llong<Is>{})...))
1955 {
1956 return T(parser::get(std::move(tup), llong<Is>{})...);
1957 }
1958
1959 template<typename T, typename... Args>
1960 auto make_from_tuple(tuple<Args...> && tup)
1961 -> decltype(detail::make_from_tuple_impl<T>(
1962 std::move(tup),
1963 std::make_integer_sequence<int, tuple_size_<tuple<Args...>>>()))
1964 {
1965 return detail::make_from_tuple_impl<T>(
1966 std::move(tup),
1967 std::make_integer_sequence<int, tuple_size_<tuple<Args...>>>());
1968 }
1969
1970 template<typename T, typename Tuple>
1971 using constructible_from_tuple_expr =
1972 decltype(detail::make_from_tuple<T>(std::declval<Tuple>()));
1973
1974 template<typename T, typename Tuple, bool = is_tuple<Tuple>{}>
1975 constexpr bool is_constructible_from_tuple_v = false;
1976 template<typename T, typename Tuple>
1977 constexpr bool is_constructible_from_tuple_v<T, Tuple, true> =
1978 is_detected_v<constructible_from_tuple_expr, T, Tuple>;
1979
1980 template<typename Container, typename U>
1981 constexpr void move_back_impl(Container & c, U && x)
1982 {
1983 using just_t = range_value_t<Container>;
1984 using just_u = remove_cv_ref_t<U>;
1985 if constexpr (needs_transcoding_to_utf8<Container, U>) {
1986 char32_t cps[1] = {(char32_t)x};
1987 auto const r = cps | text::as_utf8;
1988 c.insert(c.end(), r.begin(), r.end());
1989 } else if constexpr (std::is_convertible_v<just_u &&, just_t>) {
1990 detail::insert(c, std::move(x));
1991 } else if constexpr (
1992 !is_tuple<just_t>::value && is_tuple<just_u>::value &&
1993 std::is_aggregate_v<just_t> &&
1994 !is_detected_v<insertable, Container, just_u &&> &&
1995 is_struct_assignable_v<just_t, just_u>) {
1996 auto int_seq =
1997 std::make_integer_sequence<int, tuple_size_<just_u>>();
1998 detail::insert(
1999 c,
2000 detail::tuple_to_aggregate<just_t>(std::move(x), int_seq));
2001 } else if constexpr (
2002 is_tuple<just_t>::value && !is_tuple<just_u>::value &&
2003 std::is_aggregate_v<just_u> &&
2004 !is_detected_v<insertable, Container, just_u &&> &&
2005 is_tuple_assignable_v<just_t, just_u>) {
2006 just_t t;
2007 auto tie = detail::tie_aggregate(x);
2008 detail::aggregate_to_tuple(
2009 t,
2010 tie,
2011 std::make_integer_sequence<int, tuple_size_<just_t>>());
2012 detail::insert(c, std::move(t));
2013 } else if constexpr (is_constructible_from_tuple_v<
2014 just_t,
2015 just_u>) {
2016 detail::insert(
2017 c, detail::make_from_tuple<just_t>(std::move(x)));
2018 } else {
2019 static_assert(
2020 sizeof(U) && false,
2021 "Could not insert value into container, by: just inserting "
2022 "it; doing tuple -> aggregate or aggregate -> tuple "
2023 "conversions; or tuple -> class type construction.");
2024 }
2025 }
2026
2027 template<typename Container, typename T>
2028 constexpr void move_back(Container & c, T && x, bool gen_attrs)
2029 {
2030 if (!gen_attrs)
2031 return;
2032 detail::move_back_impl(c, std::move(x));
2033 }
2034
2035 template<typename Container>
2036 constexpr void move_back(Container & c, Container & x, bool gen_attrs)
2037 {
2038 if (!gen_attrs)
2039 return;
2040 c.insert(c.end(), x.begin(), x.end());
2041 }
2042
2043 template<typename Container>
2044 constexpr void
2045 move_back(Container & c, std::optional<Container> && x, bool gen_attrs)
2046 {
2047 if (!gen_attrs || !x)
2048 return;
2049 c.insert(c.end(), x->begin(), x->end());
2050 }
2051
2052 template<typename Container, typename T>
2053 constexpr void
2054 move_back(Container & c, std::optional<T> & x, bool gen_attrs)
2055 {
2056 if (!gen_attrs || !x)
2057 return;
2058 detail::move_back_impl(c, std::move(*x));
2059 }
2060
2061 template<
2062 typename Container,
2063 typename T,
2064 typename Enable = std::enable_if_t<!std::is_same_v<Container, T>>>
2065 constexpr void
2066 move_back(Container & c, std::optional<T> && x, bool gen_attrs)
2067 {
2068 if (!gen_attrs || !x)
2069 return;
2070 detail::move_back_impl(c, std::move(*x));
2071 }
2072
2073 constexpr void move_back(nope, nope, bool gen_attrs) {}
2074
2075 template<typename Container>
2076 constexpr void move_back(Container & c, nope, bool gen_attrs)
2077 {}
2078
2079 template<typename From, typename To>
2080 using move_assignable_expr =
2081 decltype(std::declval<To &>() = std::declval<From &&>());
2082 template<typename From, typename To>
2083 constexpr bool is_move_assignable_v =
2084 is_detected_v<move_assignable_expr, From, To>;
2085
2086 template<typename T, typename U>
2087 constexpr void assign(T & t, U && u)
2088 {
2089 using just_t = remove_cv_ref_t<T>;
2090 using just_u = remove_cv_ref_t<U>;
2091 if constexpr (is_move_assignable_v<just_u, just_t>) {
2092 static_assert(
2093 (!std::is_same_v<just_t, std::string> ||
2094 !std::is_arithmetic_v<just_u>),
2095 "std::string is assignable from a char. Due to implicit "
2096 "conversions among arithmetic types, any arithmetic type "
2097 "(like int or double) is assignable to std::string. This "
2098 "is almost certainly not what you meant to write, so "
2099 "Boost.Parser disallows it. If you want to do this, write "
2100 "a semantic action and do it explicitly.");
2101 t = std::move(u);
2102 } else if constexpr (
2103 !is_tuple<just_t>::value && is_tuple<just_u>::value &&
2104 std::is_aggregate_v<just_t> &&
2105 !std::is_convertible_v<just_u &&, just_t> &&
2106 is_struct_assignable_v<just_t, just_u>) {
2107 auto int_seq =
2108 std::make_integer_sequence<int, tuple_size_<just_u>>();
2109 t = detail::tuple_to_aggregate<just_t>(std::move(u), int_seq);
2110 } else if constexpr (
2111 is_tuple<just_t>::value && !is_tuple<just_u>::value &&
2112 std::is_aggregate_v<just_u> &&
2113 !std::is_convertible_v<just_u &&, just_t> &&
2114 is_tuple_assignable_v<just_t, just_u>) {
2115 auto tie = detail::tie_aggregate(u);
2116 detail::aggregate_to_tuple(
2117 t,
2118 tie,
2119 std::make_integer_sequence<int, tuple_size_<just_t>>());
2120 } else if constexpr (is_constructible_from_tuple_v<
2121 just_t,
2122 just_u>) {
2123 t = detail::make_from_tuple<just_t>(std::move(u));
2124 } else {
2125 static_assert(
2126 sizeof(T) && false,
2127 "Could not assign value, by: just assigning it; doing tuple "
2128 "-> aggregate or aggregate -> tuple conversions; or tuple "
2129 "-> class type construction.");
2130 }
2131 }
2132
2133 template<typename T>
2134 constexpr void assign(T &, nope)
2135 {}
2136
2137 template<typename T, typename U>
2138 constexpr void assign_copy(T & t, U const & u)
2139 {
2140 t = u;
2141 }
2142
2143 template<typename T>
2144 constexpr void assign_copy(T &, nope)
2145 {}
2146
2147 template<
2148 typename Parser,
2149 typename Iter,
2150 typename Sentinel,
2151 typename Context,
2152 typename SkipParser,
2153 typename... T>
2154 void apply_parser(
2155 Parser const & parser,
2156 Iter & first,
2157 Sentinel last,
2158 Context const & context,
2159 SkipParser const & skip,
2160 flags flags,
2161 bool & success,
2162 std::optional<std::variant<T...>> & retval)
2163 {
2164 using attr_t = decltype(parser.call(
2165 first, last, context, skip, flags, success));
2166 if constexpr (std::is_same<
2167 attr_t,
2168 std::optional<std::variant<T...>>>{}) {
2169 parser.call(first, last, context, skip, flags, success, retval);
2170 } else if constexpr (is_nope_v<attr_t>) {
2171 parser.call(first, last, context, skip, flags, success);
2172 } else {
2173 auto attr =
2174 parser.call(first, last, context, skip, flags, success);
2175 if (success)
2176 detail::assign(retval, std::variant<T...>(std::move(attr)));
2177 }
2178 }
2179
2180 template<
2181 typename Parser,
2182 typename Iter,
2183 typename Sentinel,
2184 typename Context,
2185 typename SkipParser,
2186 typename... T>
2187 void apply_parser(
2188 Parser const & parser,
2189 Iter & first,
2190 Sentinel last,
2191 Context const & context,
2192 SkipParser const & skip,
2193 flags flags,
2194 bool & success,
2195 std::variant<T...> & retval)
2196 {
2197 auto attr = parser.call(first, last, context, skip, flags, success);
2198 if (success)
2199 detail::assign(retval, std::move(attr));
2200 }
2201
2202 template<
2203 typename Parser,
2204 typename Iter,
2205 typename Sentinel,
2206 typename Context,
2207 typename SkipParser,
2208 typename T>
2209 void apply_parser(
2210 Parser const & parser,
2211 Iter & first,
2212 Sentinel last,
2213 Context const & context,
2214 SkipParser const & skip,
2215 flags flags,
2216 bool & success,
2217 std::optional<T> & retval)
2218 {
2219 auto attr = parser.call(first, last, context, skip, flags, success);
2220 if (success)
2221 detail::assign(retval, std::move(attr));
2222 }
2223
2224 template<
2225 typename Parser,
2226 typename Iter,
2227 typename Sentinel,
2228 typename Context,
2229 typename SkipParser,
2230 typename Attribute>
2231 void apply_parser(
2232 Parser const & parser,
2233 Iter & first,
2234 Sentinel last,
2235 Context const & context,
2236 SkipParser const & skip,
2237 flags flags,
2238 bool & success,
2239 Attribute & retval)
2240 {
2241 parser.call(first, last, context, skip, flags, success, retval);
2242 }
2243
2244
2245
2246
2247
2248 template<typename Iter, typename Sentinel, typename Parser>
2249 auto has_attribute(Iter first, Sentinel last, Parser parser);
2250
2251 template<typename BaseIter, typename Iter>
2252 struct scoped_base_assign
2253 {
2254 scoped_base_assign(BaseIter & base, Iter & it) :
2255 base_(base), it_(it)
2256 {}
2257 ~scoped_base_assign() { base_ = it_.base(); }
2258
2259 BaseIter & base_;
2260 Iter & it_;
2261 };
2262
2263 template<typename Parser>
2264 using has_parser_data_member_expr =
2265 decltype(std::declval<Parser>().parser_);
2266 template<typename Parser>
2267 constexpr bool has_parser_data_member_v =
2268 is_detected_v<has_parser_data_member_expr, Parser>;
2269
2270 template<typename Parser>
2271 using has_parsers_data_member_expr =
2272 decltype(std::declval<Parser>().parsers_);
2273 template<typename Parser>
2274 constexpr bool has_parsers_data_member_v =
2275 is_detected_v<has_parsers_data_member_expr, Parser>;
2276
2277 struct scoped_apply_pending_symbol_table_operations
2278 {
2279 scoped_apply_pending_symbol_table_operations(
2280 pending_symbol_table_operations_t & pending_ops) :
2281 pending_ops_(pending_ops)
2282 {}
2283
2284 ~scoped_apply_pending_symbol_table_operations()
2285 {
2286 for (auto & [_, entry] : pending_ops_) {
2287 entry.visit_();
2288 }
2289 }
2290
2291 pending_symbol_table_operations_t & pending_ops_;
2292 };
2293
2294 template<
2295 bool Debug,
2296 typename Iter,
2297 typename Sentinel,
2298 typename Parser,
2299 typename Attr,
2300 typename ErrorHandler>
2301 bool parse_impl(
2302 Iter & first,
2303 Sentinel last,
2304 Parser const & parser,
2305 ErrorHandler const & error_handler,
2306 Attr & attr)
2307 {
2308 auto const initial_first = first;
2309 bool success = true;
2310 int trace_indent = 0;
2311 detail::symbol_table_tries_t symbol_table_tries;
2312 pending_symbol_table_operations_t pending_symbol_table_operations;
2313 scoped_apply_pending_symbol_table_operations apply_pending(
2314 pending_symbol_table_operations);
2315 auto context = detail::make_context<Debug, false>(
2316 first,
2317 last,
2318 success,
2319 trace_indent,
2320 error_handler,
2321 parser.globals_,
2322 symbol_table_tries,
2323 pending_symbol_table_operations);
2324 auto const flags =
2325 Debug ? detail::enable_trace(detail::flags::gen_attrs)
2326 : detail::flags::gen_attrs;
2327 try {
2328 parser(
2329 first,
2330 last,
2331 context,
2332 detail::null_parser{},
2333 flags,
2334 success,
2335 attr);
2336 if (Debug)
2337 detail::final_trace(context, flags, attr);
2338 return success;
2339 } catch (parse_error<Iter> const & e) {
2340 if (error_handler(initial_first, last, e) ==
2341 error_handler_result::rethrow) {
2342 throw;
2343 }
2344 return false;
2345 }
2346 }
2347
2348 template<
2349 bool Debug,
2350 typename Iter,
2351 typename Sentinel,
2352 typename Parser,
2353 typename ErrorHandler>
2354 auto parse_impl(
2355 Iter & first,
2356 Sentinel last,
2357 Parser const & parser,
2358 ErrorHandler const & error_handler)
2359 {
2360 auto const initial_first = first;
2361 bool success = true;
2362 int trace_indent = 0;
2363 detail::symbol_table_tries_t symbol_table_tries;
2364 pending_symbol_table_operations_t pending_symbol_table_operations;
2365 scoped_apply_pending_symbol_table_operations apply_pending(
2366 pending_symbol_table_operations);
2367 auto context = detail::make_context<Debug, false>(
2368 first,
2369 last,
2370 success,
2371 trace_indent,
2372 error_handler,
2373 parser.globals_,
2374 symbol_table_tries,
2375 pending_symbol_table_operations);
2376 auto const flags =
2377 Debug ? detail::enable_trace(detail::flags::gen_attrs)
2378 : detail::flags::gen_attrs;
2379 using attr_t = typename detail::attribute_impl<
2380 BOOST_PARSER_SUBRANGE<std::remove_const_t<Iter>, Sentinel>,
2381 Parser>::type;
2382 try {
2383 attr_t attr_ = parser(
2384 first,
2385 last,
2386 context,
2387 detail::null_parser{},
2388 flags,
2389 success);
2390 if (Debug)
2391 detail::final_trace(context, flags, nope{});
2392 return detail::make_parse_result(attr_, success);
2393 } catch (parse_error<Iter> const & e) {
2394 if (error_handler(initial_first, last, e) ==
2395 error_handler_result::rethrow) {
2396 throw;
2397 }
2398 attr_t attr_{};
2399 return detail::make_parse_result(attr_, false);
2400 }
2401 }
2402
2403 template<
2404 bool Debug,
2405 typename Iter,
2406 typename Sentinel,
2407 typename Parser,
2408 typename ErrorHandler,
2409 typename Callbacks>
2410 bool callback_parse_impl(
2411 Iter & first,
2412 Sentinel last,
2413 Parser const & parser,
2414 ErrorHandler const & error_handler,
2415 Callbacks const & callbacks)
2416 {
2417 auto const initial_first = first;
2418 bool success = true;
2419 int trace_indent = 0;
2420 detail::symbol_table_tries_t symbol_table_tries;
2421 pending_symbol_table_operations_t pending_symbol_table_operations;
2422 scoped_apply_pending_symbol_table_operations apply_pending(
2423 pending_symbol_table_operations);
2424 auto context = detail::make_context<Debug, true>(
2425 first,
2426 last,
2427 success,
2428 trace_indent,
2429 error_handler,
2430 callbacks,
2431 parser.globals_,
2432 symbol_table_tries,
2433 pending_symbol_table_operations);
2434 auto const flags =
2435 Debug ? detail::enable_trace(detail::flags::gen_attrs)
2436 : detail::flags::gen_attrs;
2437 try {
2438 parser(
2439 first,
2440 last,
2441 context,
2442 detail::null_parser{},
2443 flags,
2444 success);
2445 if (Debug)
2446 detail::final_trace(context, flags, nope{});
2447 return success;
2448 } catch (parse_error<Iter> const & e) {
2449 if (error_handler(initial_first, last, e) ==
2450 error_handler_result::rethrow) {
2451 throw;
2452 }
2453 return false;
2454 }
2455 }
2456
2457 template<
2458 bool Debug,
2459 typename Iter,
2460 typename Sentinel,
2461 typename Parser,
2462 typename SkipParser,
2463 typename Attr,
2464 typename ErrorHandler>
2465 bool skip_parse_impl(
2466 Iter & first,
2467 Sentinel last,
2468 Parser const & parser,
2469 SkipParser const & skip,
2470 ErrorHandler const & error_handler,
2471 Attr & attr)
2472 {
2473 auto const initial_first = first;
2474 bool success = true;
2475 int trace_indent = 0;
2476 detail::symbol_table_tries_t symbol_table_tries;
2477 pending_symbol_table_operations_t pending_symbol_table_operations;
2478 scoped_apply_pending_symbol_table_operations apply_pending(
2479 pending_symbol_table_operations);
2480 auto context = detail::make_context<Debug, false>(
2481 first,
2482 last,
2483 success,
2484 trace_indent,
2485 error_handler,
2486 parser.globals_,
2487 symbol_table_tries,
2488 pending_symbol_table_operations);
2489 auto const flags =
2490 Debug ? detail::enable_trace(detail::default_flags())
2491 : detail::default_flags();
2492 detail::skip(first, last, skip, flags);
2493 try {
2494 parser(first, last, context, skip, flags, success, attr);
2495 detail::skip(first, last, skip, flags);
2496 if (Debug)
2497 detail::final_trace(context, flags, attr);
2498 return success;
2499 } catch (parse_error<Iter> const & e) {
2500 if (error_handler(initial_first, last, e) ==
2501 error_handler_result::rethrow) {
2502 throw;
2503 }
2504 return false;
2505 }
2506 }
2507
2508 template<
2509 bool Debug,
2510 typename Iter,
2511 typename Sentinel,
2512 typename Parser,
2513 typename SkipParser,
2514 typename ErrorHandler>
2515 auto skip_parse_impl(
2516 Iter & first,
2517 Sentinel last,
2518 Parser const & parser,
2519 SkipParser const & skip,
2520 ErrorHandler const & error_handler)
2521 {
2522 auto const initial_first = first;
2523 bool success = true;
2524 int trace_indent = 0;
2525 detail::symbol_table_tries_t symbol_table_tries;
2526 pending_symbol_table_operations_t pending_symbol_table_operations;
2527 scoped_apply_pending_symbol_table_operations apply_pending(
2528 pending_symbol_table_operations);
2529 auto context = detail::make_context<Debug, false>(
2530 first,
2531 last,
2532 success,
2533 trace_indent,
2534 error_handler,
2535 parser.globals_,
2536 symbol_table_tries,
2537 pending_symbol_table_operations);
2538 auto const flags =
2539 Debug ? detail::enable_trace(detail::default_flags())
2540 : detail::default_flags();
2541 detail::skip(first, last, skip, flags);
2542 using attr_t = typename detail::attribute_impl<
2543 BOOST_PARSER_SUBRANGE<std::remove_const_t<Iter>, Sentinel>,
2544 Parser>::type;
2545 try {
2546 attr_t attr_ =
2547 parser(first, last, context, skip, flags, success);
2548 detail::skip(first, last, skip, flags);
2549 if (Debug)
2550 detail::final_trace(context, flags, nope{});
2551 return detail::make_parse_result(attr_, success);
2552 } catch (parse_error<Iter> const & e) {
2553 if (error_handler(initial_first, last, e) ==
2554 error_handler_result::rethrow) {
2555 throw;
2556 }
2557 attr_t attr_{};
2558 return detail::make_parse_result(attr_, false);
2559 }
2560 }
2561
2562 template<
2563 bool Debug,
2564 typename Iter,
2565 typename Sentinel,
2566 typename Parser,
2567 typename SkipParser,
2568 typename ErrorHandler,
2569 typename Callbacks>
2570 bool callback_skip_parse_impl(
2571 Iter & first,
2572 Sentinel last,
2573 Parser const & parser,
2574 SkipParser const & skip,
2575 ErrorHandler const & error_handler,
2576 Callbacks const & callbacks)
2577 {
2578 auto const initial_first = first;
2579 bool success = true;
2580 int trace_indent = 0;
2581 detail::symbol_table_tries_t symbol_table_tries;
2582 pending_symbol_table_operations_t pending_symbol_table_operations;
2583 scoped_apply_pending_symbol_table_operations apply_pending(
2584 pending_symbol_table_operations);
2585 auto context = detail::make_context<Debug, true>(
2586 first,
2587 last,
2588 success,
2589 trace_indent,
2590 error_handler,
2591 callbacks,
2592 parser.globals_,
2593 symbol_table_tries,
2594 pending_symbol_table_operations);
2595 auto const flags =
2596 Debug ? detail::enable_trace(detail::default_flags())
2597 : detail::default_flags();
2598 detail::skip(first, last, skip, flags);
2599 try {
2600 parser(first, last, context, skip, flags, success);
2601 detail::skip(first, last, skip, flags);
2602 if (Debug)
2603 detail::final_trace(context, flags, nope{});
2604 return success;
2605 } catch (parse_error<Iter> const & e) {
2606 if (error_handler(initial_first, last, e) ==
2607 error_handler_result::rethrow) {
2608 throw;
2609 }
2610 return false;
2611 }
2612 }
2613
2614 template<typename R>
2615 constexpr auto make_input_subrange(R && r) noexcept
2616 {
2617 using r_t = remove_cv_ref_t<R>;
2618 if constexpr (std::is_pointer_v<r_t>) {
2619 using value_type = iter_value_t<r_t>;
2620 if constexpr (std::is_same_v<value_type, char>) {
2621 return BOOST_PARSER_SUBRANGE(r, text::null_sentinel);
2622 } else {
2623 return r | text::as_utf32;
2624 }
2625 } else {
2626 using value_type = range_value_t<r_t>;
2627 if constexpr (text::detail::is_bounded_array_v<r_t>) {
2628 if constexpr (std::is_same_v<value_type, char>) {
2629 auto first = detail::text::detail::begin(r);
2630 auto last = detail::text::detail::end(r);
2631 if (first != last && !*std::prev(last))
2632 --last;
2633 return BOOST_PARSER_SUBRANGE(first, last);
2634 } else {
2635 return r | text::as_utf32;
2636 }
2637 } else {
2638 if constexpr (
2639 std::is_same_v<value_type, char> &&
2640 !is_utf8_view<r_t>::value) {
2641 return BOOST_PARSER_SUBRANGE(
2642 detail::text::detail::begin(r),
2643 detail::text::detail::end(r));
2644 } else {
2645 return r | text::as_utf32;
2646 }
2647 }
2648 }
2649 }
2650
2651 template<typename R>
2652 constexpr auto make_view_begin(R & r) noexcept
2653 {
2654 if constexpr (std::is_pointer_v<std::decay_t<R>>) {
2655 return r;
2656 } else {
2657 return detail::text::detail::begin(r);
2658 }
2659 }
2660
2661 template<typename R>
2662 constexpr auto make_view_end(R & r) noexcept
2663 {
2664 if constexpr (std::is_pointer_v<std::decay_t<R>>) {
2665 return text::null_sentinel;
2666 } else {
2667 return detail::text::detail::end(r);
2668 }
2669 }
2670
2671 template<
2672 typename Iter1,
2673 typename Sentinel1,
2674 typename Iter2,
2675 typename Sentinel2,
2676 typename Pred>
2677 std::pair<Iter1, Iter2> mismatch(
2678 Iter1 first1,
2679 Sentinel1 last1,
2680 Iter2 first2,
2681 Sentinel2 last2,
2682 Pred pred)
2683 {
2684 std::pair<Iter1, Iter2> retval{first1, first2};
2685 while (retval.first != last1 && retval.second != last2 &&
2686 pred(*retval.first, *retval.second)) {
2687 ++retval.first;
2688 ++retval.second;
2689 }
2690 return retval;
2691 }
2692
2693 template<
2694 typename Iter1,
2695 typename Sentinel1,
2696 typename Iter2,
2697 typename Sentinel2>
2698 std::pair<Iter1, Iter2> no_case_aware_string_mismatch(
2699 Iter1 first1,
2700 Sentinel1 last1,
2701 Iter2 first2,
2702 Sentinel2 last2,
2703 bool no_case)
2704 {
2705 if (no_case) {
2706 auto it1 = no_case_iter(first1, last1);
2707 auto it2 = no_case_iter(first2, last2);
2708 auto const mismatch = detail::mismatch(
2709 it1, last1, it2, last2, std::equal_to<char32_t>{});
2710 return std::pair<Iter1, Iter2>{
2711 mismatch.first.base(), mismatch.second.base()};
2712 } else {
2713 return detail::mismatch(
2714 first1, last1, first2, last2, std::equal_to<char32_t>{});
2715 }
2716 }
2717
2718 template<typename I, typename S, typename T>
2719 std::optional<T>
2720 if_full_parse(I & first, S last, std::optional<T> retval)
2721 {
2722 if (first != last)
2723 retval = std::nullopt;
2724 return retval;
2725 }
2726 template<typename I, typename S>
2727 bool if_full_parse(I & first, S last, bool retval)
2728 {
2729 if (first != last)
2730 retval = false;
2731 return retval;
2732 }
2733
2734
2735
2736 template<typename Struct, typename Tuple>
2737 constexpr auto is_struct_compatible();
2738
2739 struct element_compatibility
2740 {
2741 template<typename T, typename U>
2742 constexpr auto operator()(T result, U x) const
2743 {
2744 using struct_elem =
2745 remove_cv_ref_t<decltype(parser::get(x, llong<0>{}))>;
2746 using tuple_elem =
2747 remove_cv_ref_t<decltype(parser::get(x, llong<1>{}))>;
2748 if constexpr (!T::value) {
2749 return std::false_type{};
2750 } else if constexpr (
2751 is_optional_v<struct_elem> && is_optional_v<tuple_elem>) {
2752 using struct_opt_type = optional_type<struct_elem>;
2753 using tuple_opt_type = optional_type<tuple_elem>;
2754 using retval_t = decltype((*this)(
2755 result,
2756 detail::hl::make_tuple(
2757 std::declval<struct_opt_type &>(),
2758 std::declval<tuple_opt_type &>())));
2759 return retval_t{};
2760 } else if constexpr (std::is_convertible_v<
2761 tuple_elem &&,
2762 struct_elem>) {
2763 return std::true_type{};
2764 } else if constexpr (
2765 container<struct_elem> && container<tuple_elem>) {
2766 return detail::is_struct_compatible<
2767 range_value_t<struct_elem>,
2768 range_value_t<tuple_elem>>();
2769 } else {
2770 return std::bool_constant<detail::is_struct_compatible<
2771 struct_elem,
2772 tuple_elem>()>{};
2773 }
2774 }
2775 };
2776
2777 template<typename T, typename U>
2778 constexpr auto is_struct_compatible()
2779 {
2780 if constexpr (
2781 !std::is_aggregate_v<T> ||
2782 struct_arity_v<T> != tuple_size_<U>) {
2783 return std::false_type{};
2784 } else {
2785 using result_t = decltype(detail::hl::fold_left(
2786 detail::hl::zip(
2787 detail::tie_aggregate(std::declval<T &>()),
2788 std::declval<U &>()),
2789 std::true_type{},
2790 element_compatibility{}));
2791 return result_t{};
2792 }
2793 }
2794
2795 template<typename Struct, typename Tuple>
2796 constexpr bool is_struct_compatible_v =
2797 detail::is_struct_compatible<Struct, Tuple>();
2798
2799 template<typename ParserAttr, typename GivenContainerAttr>
2800 constexpr auto parser_attr_or_container_value_type()
2801 {
2802 if constexpr (is_nope_v<ParserAttr>) {
2803 return nope{};
2804 } else {
2805 using value_type = range_value_t<GivenContainerAttr>;
2806 return std::conditional_t<
2807 std::is_convertible_v<ParserAttr, value_type>,
2808 ParserAttr,
2809 value_type>{};
2810 }
2811 }
2812 template<typename ParserAttr, typename GivenContainerAttr>
2813 using parser_attr_or_container_value_type_v =
2814 decltype(parser_attr_or_container_value_type<
2815 ParserAttr,
2816 GivenContainerAttr>());
2817
2818 template<typename T>
2819 constexpr auto tuple_or_struct_size(T && x)
2820 {
2821 if constexpr (is_tuple<remove_cv_ref_t<T>>{}) {
2822 return hl::size(x);
2823 } else {
2824 return llong<struct_arity_v<remove_cv_ref_t<T>>>{};
2825 }
2826 }
2827
2828 template<typename T>
2829 struct attr_reset
2830 {
2831 attr_reset(T & x) : x_(std::addressof(x)) {}
2832 attr_reset(attr_reset const &) = delete;
2833 attr_reset(attr_reset &&) = delete;
2834 attr_reset & operator=(attr_reset const &) = delete;
2835 attr_reset & operator=(attr_reset &&) = delete;
2836 ~attr_reset()
2837 {
2838 if (x_)
2839 *x_ = T();
2840 }
2841
2842 bool operator=(bool b)
2843 {
2844 if (b)
2845 x_ = nullptr;
2846 return b;
2847 }
2848
2849 private:
2850 T * x_;
2851 };
2852 }
2853
2854 #ifndef BOOST_PARSER_DOXYGEN
2855
2856
2857
2858 template<typename Context>
2859 auto _val(Context const & context) -> std::conditional_t<
2860 detail::is_nope_v<decltype(*context.val_)>,
2861 none,
2862 decltype(*context.val_)>
2863 {
2864 if constexpr (detail::is_nope_v<decltype(*context.val_)>)
2865 return none{};
2866 else
2867 return *context.val_;
2868 }
2869
2870 template<typename Context>
2871 decltype(auto) _attr(Context const & context)
2872 {
2873 if constexpr (detail::is_nope_v<decltype(*context.attr_)>)
2874 return none{};
2875 else
2876 return *context.attr_;
2877 }
2878
2879 template<typename Context>
2880 decltype(auto) _where(Context const & context)
2881 {
2882 return *context.where_;
2883 }
2884
2885 template<typename Context>
2886 decltype(auto) _begin(Context const & context)
2887 {
2888 return context.first_;
2889 }
2890
2891 template<typename Context>
2892 decltype(auto) _end(Context const & context)
2893 {
2894 return context.last_;
2895 }
2896
2897 template<typename Context>
2898 decltype(auto) _pass(Context const & context)
2899 {
2900 return *context.pass_;
2901 }
2902
2903 template<typename Context>
2904 decltype(auto) _locals(Context const & context)
2905 {
2906 if constexpr (detail::is_nope_v<decltype(*context.locals_)>)
2907 return none{};
2908 else
2909 return *context.locals_;
2910 }
2911
2912 template<typename Context>
2913 decltype(auto) _params(Context const & context)
2914 {
2915 if constexpr (detail::is_nope_v<decltype(*context.params_)>)
2916 return none{};
2917 else
2918 return *context.params_;
2919 }
2920
2921 template<typename Context>
2922 decltype(auto) _globals(Context const & context)
2923 {
2924 if constexpr (detail::is_nope_v<decltype(*context.globals_)>)
2925 return none{};
2926 else
2927 return *context.globals_;
2928 }
2929
2930 template<typename Context>
2931 decltype(auto) _no_case(Context const & context)
2932 {
2933 return context.no_case_depth_;
2934 }
2935
2936 template<typename Context>
2937 decltype(auto) _error_handler(Context const & context)
2938 {
2939 return *context.error_handler_;
2940 }
2941
2942 #if BOOST_PARSER_USE_CONCEPTS
2943 template<std::forward_iterator I, typename Context>
2944 #else
2945 template<typename I, typename Context>
2946 #endif
2947 void
2948 _report_error(Context const & context, std::string_view message, I location)
2949 {
2950 return context.error_handler_->diagnose(
2951 diagnostic_kind::error, message, context, location);
2952 }
2953
2954 template<typename Context>
2955 void _report_error(Context const & context, std::string_view message)
2956 {
2957 return context.error_handler_->diagnose(
2958 diagnostic_kind::error, message, context);
2959 }
2960
2961 #if BOOST_PARSER_USE_CONCEPTS
2962 template<std::forward_iterator I, typename Context>
2963 #else
2964 template<typename I, typename Context>
2965 #endif
2966 void _report_warning(
2967 Context const & context, std::string_view message, I location)
2968 {
2969 return context.error_handler_->diagnose(
2970 diagnostic_kind::warning, message, context, location);
2971 }
2972
2973 template<typename Context>
2974 void _report_warning(Context const & context, std::string_view message)
2975 {
2976 return context.error_handler_->diagnose(
2977 diagnostic_kind::warning, message, context);
2978 }
2979
2980 #endif
2981
2982
2983
2984 template<unsigned int I>
2985 inline constexpr detail::param_t<I> _p = {};
2986
2987
2988
2989
2990
2991
2992 int64_t const Inf = detail::unbounded;
2993
2994 #ifndef BOOST_PARSER_DOXYGEN
2995 template<
2996 typename Parser,
2997 typename DelimiterParser,
2998 typename MinType,
2999 typename MaxType>
3000 struct repeat_parser
3001 {
3002 constexpr repeat_parser(
3003 Parser parser,
3004 MinType _min,
3005 MaxType _max,
3006 DelimiterParser delimiter_parser = DelimiterParser{}) :
3007 parser_(parser),
3008 delimiter_parser_(delimiter_parser),
3009 min_(_min),
3010 max_(_max)
3011 {}
3012
3013 template<
3014 typename Iter,
3015 typename Sentinel,
3016 typename Context,
3017 typename SkipParser>
3018 auto call(
3019 Iter & first,
3020 Sentinel last,
3021 Context const & context,
3022 SkipParser const & skip,
3023 detail::flags flags,
3024 bool & success) const
3025 {
3026 using attr_t = decltype(parser_.call(
3027 first, last, context, skip, flags, success));
3028 auto retval = detail::make_sequence_of<attr_t>();
3029 call(first, last, context, skip, flags, success, retval);
3030 return retval;
3031 }
3032
3033 template<
3034 typename Iter,
3035 typename Sentinel,
3036 typename Context,
3037 typename SkipParser,
3038 typename Attribute>
3039 void call(
3040 Iter & first,
3041 Sentinel last,
3042 Context const & context,
3043 SkipParser const & skip,
3044 detail::flags flags,
3045 bool & success,
3046 Attribute & retval) const
3047 {
3048 [[maybe_unused]] auto _ = detail::scoped_trace(
3049 *this,
3050 first,
3051 last,
3052 context,
3053 detail::in_apply_parser(flags) ? detail::disable_trace(flags)
3054 : flags,
3055 retval);
3056
3057 if constexpr (detail::is_optional_v<Attribute>) {
3058 detail::optional_type<Attribute> attr;
3059 detail::apply_parser(
3060 *this,
3061 first,
3062 last,
3063 context,
3064 skip,
3065 detail::set_in_apply_parser(flags),
3066 success,
3067 attr);
3068 if (success)
3069 retval = std::move(attr);
3070 } else {
3071 using attr_t = detail::parser_attr_or_container_value_type_v<
3072 decltype(parser_.call(
3073 first, last, context, skip, flags, success)),
3074 Attribute>;
3075
3076 int64_t count = 0;
3077
3078 for (int64_t end = detail::resolve(context, min_); count != end;
3079 ++count) {
3080 detail::skip(first, last, skip, flags);
3081 attr_t attr{};
3082 parser_.call(
3083 first, last, context, skip, flags, success, attr);
3084 if (!success) {
3085 detail::assign(retval, Attribute());
3086 return;
3087 }
3088 detail::move_back(
3089 retval, std::move(attr), detail::gen_attrs(flags));
3090 }
3091
3092 int64_t const end = detail::resolve(context, max_);
3093
3094
3095
3096 BOOST_PARSER_DEBUG_ASSERT(
3097 !detail::is_unconditional_eps<Parser>{} || end < Inf);
3098
3099 for (; count != end; ++count) {
3100 auto const prev_first = first;
3101
3102
3103
3104 if constexpr (!detail::is_nope_v<DelimiterParser>) {
3105 detail::skip(first, last, skip, flags);
3106 delimiter_parser_.call(
3107 first,
3108 last,
3109 context,
3110 skip,
3111 detail::disable_attrs(flags),
3112 success);
3113 if (!success) {
3114 success = true;
3115 first = prev_first;
3116 break;
3117 }
3118 }
3119
3120 detail::skip(first, last, skip, flags);
3121 attr_t attr{};
3122 parser_.call(
3123 first, last, context, skip, flags, success, attr);
3124 if (!success) {
3125 success = true;
3126 first = prev_first;
3127 break;
3128 }
3129 detail::move_back(
3130 retval, std::move(attr), detail::gen_attrs(flags));
3131 }
3132 }
3133 }
3134
3135 Parser parser_;
3136 DelimiterParser delimiter_parser_;
3137 MinType min_;
3138 MaxType max_;
3139 };
3140 #endif
3141
3142 template<typename Parser>
3143 struct zero_plus_parser : repeat_parser<Parser>
3144 {
3145 constexpr zero_plus_parser(Parser parser) :
3146 repeat_parser<Parser>(parser, 0, Inf)
3147 {}
3148 };
3149
3150 template<typename Parser>
3151 struct one_plus_parser : repeat_parser<Parser>
3152 {
3153 constexpr one_plus_parser(Parser parser) :
3154 repeat_parser<Parser>(parser, 1, Inf)
3155 {}
3156 };
3157
3158 template<typename Parser, typename DelimiterParser>
3159 struct delimited_seq_parser : repeat_parser<Parser, DelimiterParser>
3160 {
3161 constexpr delimited_seq_parser(
3162 Parser parser, DelimiterParser delimiter_parser) :
3163 repeat_parser<Parser, DelimiterParser>(
3164 parser, 1, Inf, delimiter_parser)
3165 {}
3166 };
3167
3168
3169 template<typename Parser>
3170 struct opt_parser
3171 {
3172
3173
3174 template<
3175 typename Iter,
3176 typename Sentinel,
3177 typename Context,
3178 typename SkipParser>
3179 auto call(
3180 Iter & first,
3181 Sentinel last,
3182 Context const & context,
3183 SkipParser const & skip,
3184 detail::flags flags,
3185 bool & success) const
3186 {
3187 using attr_t = decltype(parser_.call(
3188 first, last, context, skip, flags, success));
3189 detail::optional_of<attr_t> retval;
3190 call(first, last, context, skip, flags, success, retval);
3191 return retval;
3192 }
3193
3194
3195
3196 template<
3197 typename Iter,
3198 typename Sentinel,
3199 typename Context,
3200 typename SkipParser,
3201 typename Attribute>
3202 void call(
3203 Iter & first,
3204 Sentinel last,
3205 Context const & context,
3206 SkipParser const & skip,
3207 detail::flags flags,
3208 bool & success,
3209 Attribute & retval) const
3210 {
3211
3212 [[maybe_unused]] auto _ = detail::scoped_trace(
3213 *this, first, last, context, flags, retval);
3214
3215
3216
3217 detail::skip(first, last, skip, flags);
3218
3219
3220
3221 if (!detail::gen_attrs(flags)) {
3222 parser_.call(first, last, context, skip, flags, success);
3223 success = true;
3224 return;
3225 }
3226
3227
3228
3229 parser_.call(first, last, context, skip, flags, success, retval);
3230 success = true;
3231
3232 }
3233
3234
3235
3236 Parser parser_;
3237 };
3238
3239
3240 template<typename ParserTuple>
3241 struct or_parser
3242 {
3243 constexpr or_parser(ParserTuple parsers) : parsers_(parsers) {}
3244
3245 #ifndef BOOST_PARSER_DOXYGEN
3246
3247 template<
3248 typename Iter,
3249 typename Sentinel,
3250 typename Context,
3251 typename SkipParser>
3252 struct use_parser_t
3253 {
3254 template<typename Parser>
3255 auto operator()(Parser const & parser) const
3256 {
3257 detail::skip(first_, last_, skip_, flags_);
3258 success_ = true;
3259 return parser.call(
3260 first_,
3261 last_,
3262 context_,
3263 skip_,
3264 flags_,
3265 success_);
3266 }
3267
3268 template<typename Parser, typename Attribute>
3269 void operator()(Parser const & parser, Attribute & retval) const
3270 {
3271 detail::skip(first_, last_, skip_, flags_);
3272 success_ = true;
3273
3274 detail::apply_parser(
3275 parser,
3276 first_,
3277 last_,
3278 context_,
3279 skip_,
3280 flags_,
3281 success_,
3282 retval);
3283 }
3284
3285 Iter & first_;
3286 Sentinel last_;
3287 Context const & context_;
3288 SkipParser const & skip_;
3289 detail::flags flags_;
3290 bool & success_;
3291 };
3292
3293 #endif
3294
3295 template<
3296 typename Iter,
3297 typename Sentinel,
3298 typename Context,
3299 typename SkipParser>
3300 auto call(
3301 Iter & first,
3302 Sentinel last,
3303 Context const & context,
3304 SkipParser const & skip,
3305 detail::flags flags,
3306 bool & success) const
3307 {
3308 use_parser_t<Iter, Sentinel, Context, SkipParser> const use_parser{
3309 first, last, context, skip, flags, success};
3310
3311
3312 using all_types =
3313 decltype(detail::hl::transform(parsers_, use_parser));
3314
3315
3316 using all_types_wrapped =
3317 decltype(detail::hl::transform(all_types{}, detail::wrap{}));
3318
3319
3320
3321
3322
3323 auto append_unique = [](auto result, auto x) {
3324 using x_type = typename decltype(x)::type;
3325 if constexpr (detail::is_nope_v<x_type>) {
3326 return detail::hl::make_pair(
3327 detail::hl::first(result), std::true_type{});
3328 } else if constexpr (detail::hl::contains(
3329 detail::hl::first(result), x)) {
3330 return result;
3331 } else {
3332 return detail::hl::make_pair(
3333 detail::hl::append(detail::hl::first(result), x),
3334 detail::hl::second(result));
3335 }
3336 };
3337 using wrapped_unique_types = decltype(detail::hl::fold_left(
3338 all_types_wrapped{},
3339 detail::hl::make_pair(tuple<>{}, std::false_type{}),
3340 append_unique));
3341
3342
3343 using unwrapped_types = decltype(detail::hl::make_pair(
3344 detail::hl::transform(
3345 detail::hl::first(wrapped_unique_types{}),
3346 detail::unwrap{}),
3347 detail::hl::second(wrapped_unique_types{})));
3348
3349
3350
3351
3352 using result_t = detail::to_hana_tuple_or_type_t<unwrapped_types>;
3353
3354 result_t retval{};
3355 call(first, last, context, skip, flags, success, retval);
3356 return retval;
3357 }
3358
3359 template<
3360 typename Iter,
3361 typename Sentinel,
3362 typename Context,
3363 typename SkipParser,
3364 typename Attribute>
3365 void call(
3366 Iter & first,
3367 Sentinel last,
3368 Context const & context,
3369 SkipParser const & skip,
3370 detail::flags flags,
3371 bool & success,
3372 Attribute & retval) const
3373 {
3374 [[maybe_unused]] auto _ = detail::scoped_trace(
3375 *this, first, last, context, flags, retval);
3376
3377 use_parser_t<Iter, Sentinel, Context, SkipParser> const use_parser{
3378 first, last, context, skip, flags, success};
3379
3380 bool done = false;
3381 auto try_parser = [prev_first = first,
3382 use_parser,
3383 &success,
3384 flags,
3385 &retval,
3386 &done](auto const & parser) {
3387 if (done)
3388 return;
3389 if (detail::gen_attrs(flags))
3390 use_parser(parser, retval);
3391 else
3392 use_parser(parser);
3393 if (success)
3394 done = true;
3395 else
3396 use_parser.first_ = prev_first;
3397 };
3398 detail::hl::for_each(parsers_, try_parser);
3399
3400 if (!done)
3401 success = false;
3402 }
3403
3404 #ifndef BOOST_PARSER_DOXYGEN
3405
3406 template<typename Parser>
3407 constexpr auto prepend(parser_interface<Parser> parser) const noexcept;
3408 template<typename Parser>
3409 constexpr auto append(parser_interface<Parser> parser) const noexcept;
3410
3411 #endif
3412
3413 ParserTuple parsers_;
3414 };
3415
3416 template<typename ParserTuple, typename DelimiterParser>
3417 struct perm_parser
3418 {
3419 constexpr perm_parser(ParserTuple parsers) : parsers_(parsers) {}
3420 constexpr perm_parser(
3421 ParserTuple parsers, DelimiterParser delimiter_parser) :
3422 parsers_(parsers), delimiter_parser_(delimiter_parser)
3423 {}
3424
3425 #ifndef BOOST_PARSER_DOXYGEN
3426
3427 template<
3428 typename Iter,
3429 typename Sentinel,
3430 typename Context,
3431 typename SkipParser>
3432 struct use_parser_t
3433 {
3434 template<typename Parser>
3435 auto operator()(Parser const & parser) const
3436 {
3437 detail::skip(first_, last_, skip_, flags_);
3438 success_ = true;
3439 return parser.call(
3440 first_,
3441 last_,
3442 context_,
3443 skip_,
3444 flags_,
3445 success_);
3446 }
3447
3448 template<typename Parser, typename Attribute>
3449 void operator()(Parser const & parser, Attribute & retval) const
3450 {
3451 detail::skip(first_, last_, skip_, flags_);
3452 success_ = true;
3453
3454 detail::apply_parser(
3455 parser,
3456 first_,
3457 last_,
3458 context_,
3459 skip_,
3460 flags_,
3461 success_,
3462 retval);
3463 }
3464
3465 Iter & first_;
3466 Sentinel last_;
3467 Context const & context_;
3468 SkipParser const & skip_;
3469 detail::flags flags_;
3470 bool & success_;
3471 };
3472
3473 #endif
3474
3475 template<
3476 typename Iter,
3477 typename Sentinel,
3478 typename Context,
3479 typename SkipParser>
3480 auto call(
3481 Iter & first_,
3482 Sentinel last,
3483 Context const & context,
3484 SkipParser const & skip,
3485 detail::flags flags,
3486 bool & success) const
3487 {
3488 Iter first = first_;
3489
3490 use_parser_t<Iter, Sentinel, Context, SkipParser> const use_parser{
3491 first, last, context, skip, flags, success};
3492 using result_t =
3493 decltype(detail::hl::transform(parsers_, use_parser));
3494 result_t retval{};
3495
3496 [[maybe_unused]] auto _ = detail::scoped_trace(
3497 *this, first_, last, context, flags, retval);
3498
3499 call_impl(
3500 first,
3501 last,
3502 context,
3503 skip,
3504 flags,
3505 success,
3506 retval,
3507 std::make_integer_sequence<
3508 int,
3509 detail::tuple_size_<ParserTuple>>{});
3510
3511 if (success)
3512 first_ = first;
3513
3514 return retval;
3515 }
3516
3517 template<
3518 typename Iter,
3519 typename Sentinel,
3520 typename Context,
3521 typename SkipParser,
3522 typename Attribute>
3523 void call(
3524 Iter & first_,
3525 Sentinel last,
3526 Context const & context,
3527 SkipParser const & skip,
3528 detail::flags flags,
3529 bool & success,
3530 Attribute & retval) const
3531 {
3532 [[maybe_unused]] auto _ = detail::scoped_trace(
3533 *this, first_, last, context, flags, retval);
3534
3535 Iter first = first_;
3536 use_parser_t<Iter, Sentinel, Context, SkipParser> const use_parser{
3537 first, last, context, skip, flags, success};
3538 using result_t =
3539 decltype(detail::hl::transform(parsers_, use_parser));
3540
3541 constexpr auto indices = std::
3542 make_integer_sequence<int, detail::tuple_size_<ParserTuple>>{};
3543
3544 if constexpr (detail::is_optional_v<Attribute>) {
3545 typename Attribute::value_type attr;
3546 call(first, last, context, skip, flags, success, attr);
3547 if (success)
3548 detail::assign(retval, std::move(attr));
3549 } else if constexpr (
3550 detail::is_tuple<Attribute>{} ||
3551 detail::is_struct_compatible_v<Attribute, result_t>) {
3552 call_impl(
3553 first,
3554 last,
3555 context,
3556 skip,
3557 flags,
3558 success,
3559 retval,
3560 indices);
3561
3562 if (!success)
3563 detail::assign(retval, Attribute());
3564 } else if constexpr (detail::is_constructible_from_tuple_v<
3565 Attribute,
3566 result_t>) {
3567 result_t temp_retval{};
3568 call_impl(
3569 first,
3570 last,
3571 context,
3572 skip,
3573 flags,
3574 success,
3575 temp_retval,
3576 indices);
3577
3578 if (success && detail::gen_attrs(flags)) {
3579 detail::assign(
3580 retval,
3581 detail::make_from_tuple<Attribute>(
3582 std::move(temp_retval)));
3583 }
3584 } else {
3585 #if 0
3586
3587 tuple<Attribute> temp_retval{};
3588 call_impl(
3589 first,
3590 last,
3591 context,
3592 skip,
3593 flags,
3594 success,
3595 temp_retval,
3596 indices);
3597
3598 if (success && detail::gen_attrs(flags)) {
3599 detail::assign(
3600 retval, std::move(detail::hl::front(temp_retval)));
3601 }
3602 #else
3603 static_assert(
3604 std::is_same_v<Attribute, void> && false,
3605 "It looks like you passed an attribute to this permutation "
3606 "parser that is not capable of taking the number, or the "
3607 "types of values compatible with the ones it produces.");
3608 #endif
3609 }
3610
3611 if (success)
3612 first_ = first;
3613 }
3614
3615 template<
3616 typename Iter,
3617 typename Sentinel,
3618 typename Context,
3619 typename SkipParser,
3620 typename... Ts,
3621 int... Is>
3622 void call_impl(
3623 Iter & first,
3624 Sentinel last,
3625 Context const & context,
3626 SkipParser const & skip,
3627 detail::flags flags,
3628 bool & success,
3629 tuple<Ts...> & retval,
3630 std::integer_sequence<int, Is...>) const
3631 {
3632 std::array<bool, sizeof...(Ts)> used_parsers = {{}};
3633
3634
3635
3636 auto parse_into = [&](int i, auto const & parser, auto & x) {
3637 if (used_parsers[i])
3638 return false;
3639 detail::skip(first, last, skip, flags);
3640 parser.call(first, last, context, skip, flags, success, x);
3641 if (success) {
3642 used_parsers[i] = true;
3643 return true;
3644 }
3645 success = true;
3646 return false;
3647 };
3648
3649
3650 bool first_iteration = true;
3651 auto parsed_one = [&](auto) {
3652 if constexpr (!detail::is_nope_v<DelimiterParser>) {
3653 if (!first_iteration) {
3654 detail::skip(first, last, skip, flags);
3655 bool local_success = true;
3656 delimiter_parser_.call(
3657 first, last, context, skip, flags, local_success);
3658 if (!local_success)
3659 return false;
3660 }
3661 first_iteration = false;
3662 }
3663 return (
3664 parse_into(
3665 Is,
3666 parser::get(parsers_, llong<Is>{}),
3667 parser::get(retval, llong<Is>{})) ||
3668 ...);
3669 };
3670 success = (parsed_one(Is) && ...);
3671
3672 if (!success)
3673 retval = tuple<Ts...>{};
3674 }
3675
3676 #ifndef BOOST_PARSER_DOXYGEN
3677
3678 template<typename Parser>
3679 constexpr auto prepend(parser_interface<Parser> parser) const noexcept;
3680 template<typename Parser>
3681 constexpr auto append(parser_interface<Parser> parser) const noexcept;
3682
3683 #endif
3684
3685 ParserTuple parsers_;
3686 DelimiterParser delimiter_parser_;
3687 };
3688
3689 namespace detail {
3690 template<int N, int... I>
3691 constexpr auto
3692 make_default_combining_impl(std::integer_sequence<int, I...>)
3693 {
3694 return hl::make_tuple(((void)I, llong<N>{})...);
3695 }
3696 template<template<class...> class Tuple, typename... Args>
3697 constexpr auto make_default_combining(Tuple<Args...>)
3698 {
3699 return detail::make_default_combining_impl<0>(
3700 std::make_integer_sequence<int, sizeof...(Args)>());
3701 }
3702 template<typename ParserTuple>
3703 using default_combining_t = decltype(detail::make_default_combining(
3704 std::declval<ParserTuple>()));
3705
3706 struct merge_t
3707 {};
3708 struct separate_t
3709 {};
3710
3711 template<
3712 typename Iter,
3713 typename Sentinel,
3714 typename Context,
3715 typename SkipParser>
3716 struct dummy_use_parser_t
3717 {
3718 dummy_use_parser_t(
3719 Iter & first,
3720 Sentinel last,
3721 Context const & context,
3722 SkipParser const & skip,
3723 detail::flags flags,
3724 bool & success) :
3725 first_(first),
3726 last_(last),
3727 context_(context),
3728 skip_(skip),
3729 flags_(flags),
3730 success_(success)
3731 {}
3732 template<typename Parser>
3733 auto operator()(Parser const & parser) const
3734 {
3735 return parser.call(
3736 first_,
3737 last_,
3738 context_,
3739 skip_,
3740 flags_,
3741 success_);
3742 }
3743 Iter & first_;
3744 Sentinel last_;
3745 Context const & context_;
3746 SkipParser const & skip_;
3747 detail::flags flags_;
3748 bool & success_;
3749 };
3750
3751 template<typename... Args>
3752 constexpr void static_assert_merge_attributes(tuple<Args...> parsers);
3753
3754
3755
3756
3757 template<typename CombiningGroups, typename... Args>
3758 constexpr auto make_combining(tuple<Args...> parsers)
3759 {
3760 if constexpr (std::is_same_v<CombiningGroups, merge_t>) {
3761 detail::static_assert_merge_attributes(parsers);
3762 return detail::make_default_combining_impl<1>(
3763 std::make_integer_sequence<int, sizeof...(Args)>());
3764 } else if constexpr (std::is_same_v<CombiningGroups, separate_t>) {
3765 return detail::make_default_combining_impl<-1>(
3766 std::make_integer_sequence<int, sizeof...(Args)>());
3767 } else {
3768 return CombiningGroups{};
3769 }
3770 }
3771 template<typename ParserTuple, typename CombiningGroups>
3772 using combining_t = decltype(detail::make_combining<CombiningGroups>(
3773 std::declval<ParserTuple>()));
3774
3775 struct max_
3776 {
3777 template<typename T, typename U>
3778 constexpr auto operator()(T x, U y) const
3779 {
3780 if constexpr (T::value < U::value)
3781 return y;
3782 else
3783 return x;
3784 }
3785 };
3786 template<int MaxGroupIdx>
3787 struct adjust_combining_groups
3788 {
3789 template<typename T, typename U>
3790 constexpr auto operator()(T result, U x) const
3791 {
3792 if constexpr (U::value <= 0)
3793 return hl::append(result, x);
3794 else
3795 return hl::append(result, llong<MaxGroupIdx + U::value>{});
3796 }
3797 };
3798 template<typename Tuple1, typename Tuple2>
3799 constexpr auto make_combined_combining(Tuple1 lhs, Tuple2 rhs)
3800 {
3801 auto max_group_idx = detail::hl::fold_left(lhs, llong<0>{}, max_{});
3802 auto rhs_adjusted = detail::hl::fold_left(
3803 rhs,
3804 tuple<>{},
3805 adjust_combining_groups<decltype(max_group_idx)::value>{});
3806 return hl::concat(lhs, rhs_adjusted);
3807 }
3808 template<typename CombiningGroups1, typename CombiningGroups2>
3809 using combined_combining_t = decltype(detail::make_combined_combining(
3810 std::declval<CombiningGroups1>(),
3811 std::declval<CombiningGroups2>()));
3812
3813 enum class merge_kind { second_pass_detect, singleton, merged, group };
3814
3815 template<merge_kind Kind>
3816 struct merge_kind_t
3817 {
3818 static constexpr merge_kind kind = Kind;
3819 };
3820
3821 template<merge_kind Kind>
3822 static constexpr auto merge_wrap = merge_kind_t<Kind>{};
3823 }
3824
3825 #ifndef BOOST_PARSER_DOXYGEN
3826
3827 template<
3828 typename ParserTuple,
3829 typename BacktrackingTuple,
3830 typename CombiningGroups>
3831 struct seq_parser
3832 {
3833 using backtracking = BacktrackingTuple;
3834 using combining_groups = CombiningGroups;
3835
3836 constexpr seq_parser(ParserTuple parsers) : parsers_(parsers) {}
3837
3838 static constexpr auto true_ = std::true_type{};
3839 static constexpr auto false_ = std::false_type{};
3840
3841 struct combine
3842 {
3843 template<typename T, typename U>
3844 auto operator()(
3845 T result_merging_indices_and_prev_group, U x_and_group) const
3846 {
3847 using namespace literals;
3848 using detail::merge_wrap;
3849 using detail::merge_kind;
3850
3851 auto x = parser::get(x_and_group, 0_c);
3852 auto group = parser::get(x_and_group, 1_c);
3853
3854 auto result =
3855 parser::get(result_merging_indices_and_prev_group, 0_c);
3856 using result_back_type =
3857 typename std::decay_t<decltype(detail::hl::back(
3858 result))>::type;
3859 using unwrapped_optional_result_back_type =
3860 detail::unwrapped_optional_t<result_back_type>;
3861
3862 auto merging =
3863 parser::get(result_merging_indices_and_prev_group, 1_c);
3864 auto indices =
3865 parser::get(result_merging_indices_and_prev_group, 2_c);
3866 auto prev_group =
3867 parser::get(result_merging_indices_and_prev_group, 3_c);
3868
3869 using x_type = typename decltype(x)::type;
3870 using unwrapped_optional_x_type =
3871 detail::unwrapped_optional_t<x_type>;
3872
3873 if constexpr (detail::is_nope_v<x_type>) {
3874 if constexpr (
3875 !detail::is_nope_v<result_back_type> &&
3876 0 < decltype(group)::value &&
3877 decltype(group)::value != decltype(prev_group)::value) {
3878
3879
3880
3881
3882
3883
3884 return detail::hl::make_tuple(
3885 detail::hl::append(result, x),
3886 detail::hl::append(
3887 merging,
3888 merge_wrap<merge_kind::second_pass_detect>),
3889 detail::hl::append(
3890 indices, detail::hl::size(result)),
3891 group);
3892 } else {
3893
3894 return detail::hl::make_tuple(
3895 result,
3896 detail::hl::append(
3897 merging,
3898 merge_wrap<merge_kind::second_pass_detect>),
3899 detail::hl::append(
3900 indices, detail::hl::size_minus_one(result)),
3901 prev_group);
3902 }
3903 } else if constexpr (detail::is_nope_v<result_back_type>) {
3904
3905 constexpr auto merge =
3906 0 < decltype(group)::value
3907 ? merge_kind::group
3908 : (decltype(group)::value == -1
3909 ? merge_kind::singleton
3910 : merge_kind::second_pass_detect);
3911 return detail::hl::make_tuple(
3912 detail::hl::append(detail::hl::drop_back(result), x),
3913 detail::hl::append(merging, merge_wrap<merge>),
3914 detail::hl::append(
3915 indices, detail::hl::size_minus_one(result)),
3916 group);
3917 } else if constexpr (0 < decltype(group)::value) {
3918 if constexpr (
3919 decltype(prev_group)::value == decltype(group)::value) {
3920 return detail::hl::make_tuple(
3921 result,
3922 detail::hl::append(
3923 merging, merge_wrap<merge_kind::group>),
3924 detail::hl::append(
3925 indices, detail::hl::size_minus_one(result)),
3926 group);
3927 } else {
3928 return detail::hl::make_tuple(
3929 detail::hl::append(result, x),
3930 detail::hl::append(
3931 merging, merge_wrap<merge_kind::group>),
3932 detail::hl::append(
3933 indices, detail::hl::size(result)),
3934 group);
3935 }
3936 } else if constexpr (
3937 decltype(group)::value == -1 ||
3938 decltype(group)::value != decltype(prev_group)::value) {
3939 constexpr auto merge = decltype(group)::value == -1
3940 ? merge_kind::singleton
3941 : merge_kind::second_pass_detect;
3942 return detail::hl::make_tuple(
3943 detail::hl::append(result, x),
3944 detail::hl::append(merging, merge_wrap<merge>),
3945 detail::hl::append(indices, detail::hl::size(result)),
3946 group);
3947 } else if constexpr (
3948 detail::is_char_type_v<result_back_type> &&
3949 (detail::is_char_type_v<x_type> ||
3950 detail::is_char_type_v<unwrapped_optional_x_type>)) {
3951
3952 return detail::hl::make_tuple(
3953 detail::hl::append(
3954 detail::hl::drop_back(result),
3955 detail::wrapper<std::string>{}),
3956 detail::hl::append(
3957 detail::hl::append(
3958 detail::hl::drop_front(merging),
3959 merge_wrap<merge_kind::second_pass_detect>),
3960 merge_wrap<merge_kind::second_pass_detect>),
3961 detail::hl::append(
3962 indices, detail::hl::size_minus_one(result)),
3963 group);
3964 } else if constexpr (
3965 detail::
3966 container_and_value_type<result_back_type, x_type> ||
3967 detail::container_and_value_type<
3968 result_back_type,
3969 unwrapped_optional_x_type>) {
3970
3971
3972 return detail::hl::make_tuple(
3973 result,
3974 detail::hl::append(
3975 merging,
3976 merge_wrap<merge_kind::second_pass_detect>),
3977 detail::hl::append(
3978 indices, detail::hl::size_minus_one(result)),
3979 group);
3980 } else if constexpr (
3981 detail::
3982 container_and_value_type<x_type, result_back_type> ||
3983 detail::container_and_value_type<
3984 x_type,
3985 unwrapped_optional_result_back_type>) {
3986
3987
3988 return detail::hl::make_tuple(
3989 detail::hl::append(detail::hl::drop_back(result), x),
3990 detail::hl::append(
3991 detail::hl::append(
3992 detail::hl::drop_front(merging),
3993 merge_wrap<merge_kind::second_pass_detect>),
3994 merge_wrap<merge_kind::second_pass_detect>),
3995 detail::hl::append(
3996 indices, detail::hl::size_minus_one(result)),
3997 group);
3998 } else {
3999
4000 return detail::hl::make_tuple(
4001 detail::hl::append(result, x),
4002 detail::hl::append(
4003 merging, merge_wrap<merge_kind::second_pass_detect>),
4004 detail::hl::append(indices, detail::hl::size(result)),
4005 group);
4006 }
4007 }
4008 };
4009
4010 struct find_merged
4011 {
4012 template<typename T, typename U>
4013 auto operator()(
4014 T final_types_and_result, U x_index_and_prev_merged) const
4015 {
4016 using namespace literals;
4017 using detail::merge_wrap;
4018 using detail::merge_kind;
4019
4020 auto final_types = parser::get(final_types_and_result, 0_c);
4021 auto result = parser::get(final_types_and_result, 1_c);
4022
4023 auto x_type_wrapper = parser::get(x_index_and_prev_merged, 0_c);
4024 auto index = parser::get(x_index_and_prev_merged, 1_c);
4025 auto prev_merged = parser::get(x_index_and_prev_merged, 2_c);
4026
4027 auto type_at_index_wrapper = parser::get(final_types, index);
4028 using x_type = typename decltype(x_type_wrapper)::type;
4029 using type_at_index =
4030 typename decltype(type_at_index_wrapper)::type;
4031 if constexpr (
4032 decltype(prev_merged)::kind ==
4033 merge_kind::second_pass_detect) {
4034 if constexpr (
4035 !std::is_same_v<x_type, type_at_index> &&
4036 container<type_at_index>) {
4037 return detail::hl::make_tuple(
4038 final_types,
4039 detail::hl::append(
4040 result, merge_wrap<merge_kind::merged>));
4041 } else {
4042 return detail::hl::make_tuple(
4043 final_types,
4044 detail::hl::append(
4045 result, merge_wrap<merge_kind::singleton>));
4046 }
4047 } else {
4048 return detail::hl::make_tuple(
4049 final_types, detail::hl::append(result, prev_merged));
4050 }
4051 }
4052 };
4053
4054 template<long long I>
4055 static constexpr auto
4056 merging_from_group(integral_constant<long long, I>)
4057 {
4058 using detail::merge_wrap;
4059 using detail::merge_kind;
4060 if constexpr (0 < I)
4061 return merge_wrap<merge_kind::group>;
4062 else if constexpr (I == -1)
4063 return merge_wrap<merge_kind::singleton>;
4064 else
4065 return merge_wrap<merge_kind::second_pass_detect>;
4066 }
4067
4068
4069
4070
4071 template<
4072 typename Iter,
4073 typename Sentinel,
4074 typename Context,
4075 typename SkipParser>
4076 auto make_temp_result(
4077 Iter & first,
4078 Sentinel last,
4079 Context const & context,
4080 SkipParser const & skip,
4081 detail::flags flags,
4082 bool & success) const
4083 {
4084 using namespace literals;
4085
4086 detail::
4087 dummy_use_parser_t<Iter, Sentinel, Context, SkipParser> const
4088 dummy_use_parser(
4089 first, last, context, skip, flags, success);
4090
4091
4092 using all_types =
4093 decltype(detail::hl::transform(parsers_, dummy_use_parser));
4094
4095
4096 using all_types_wrapped =
4097 decltype(detail::hl::transform(all_types{}, detail::wrap{}));
4098
4099 using combining_groups =
4100 detail::combining_t<ParserTuple, CombiningGroups>;
4101 constexpr auto first_group = detail::hl::front(combining_groups{});
4102
4103
4104
4105
4106 constexpr auto combine_start = detail::hl::make_tuple(
4107 detail::hl::make_tuple(detail::hl::front(all_types_wrapped{})),
4108 detail::hl::make_tuple(merging_from_group(first_group)),
4109 tuple<llong<0>>{},
4110 first_group);
4111 using combined_types = decltype(detail::hl::fold_left(
4112 detail::hl::zip(
4113 detail::hl::drop_front(all_types_wrapped{}),
4114 detail::hl::drop_front(combining_groups{})),
4115 combine_start,
4116 combine{}));
4117
4118
4119 constexpr auto result_type_wrapped =
4120 parser::get(combined_types{}, 0_c);
4121 using result_type = decltype(detail::hl::transform(
4122 result_type_wrapped, detail::unwrap{}));
4123
4124 using indices = decltype(parser::get(combined_types{}, 2_c));
4125 using first_pass_merged =
4126 decltype(parser::get(combined_types{}, 1_c));
4127
4128 constexpr auto find_merged_start =
4129 detail::hl::make_tuple(result_type_wrapped, tuple<>{});
4130 using merged = decltype(detail::hl::fold_left(
4131 detail::hl::zip(
4132 all_types_wrapped{}, indices{}, first_pass_merged{}),
4133 find_merged_start,
4134 find_merged{}));
4135
4136 return detail::hl::make_tuple(
4137 result_type{}, indices{}, parser::get(merged{}, 1_c));
4138 }
4139
4140 template<
4141 typename Iter,
4142 typename Sentinel,
4143 typename Context,
4144 typename SkipParser>
4145 auto call(
4146 Iter & first_,
4147 Sentinel last,
4148 Context const & context,
4149 SkipParser const & skip,
4150 detail::flags flags,
4151 bool & success) const
4152 {
4153 Iter first = first_;
4154
4155 auto temp_result =
4156 make_temp_result(first, last, context, skip, flags, success);
4157
4158 std::decay_t<decltype(parser::get(temp_result, llong<0>{}))>
4159 retval{};
4160
4161 [[maybe_unused]] auto _ = detail::scoped_trace(
4162 *this,
4163 first_,
4164 last,
4165 context,
4166 detail::in_apply_parser(flags) ? detail::disable_trace(flags)
4167 : flags,
4168 retval);
4169
4170 std::decay_t<decltype(parser::get(temp_result, llong<1>{}))>
4171 indices;
4172 std::decay_t<decltype(parser::get(temp_result, llong<2>{}))>
4173 merged;
4174 call_impl(
4175 first,
4176 last,
4177 context,
4178 skip,
4179 flags,
4180 success,
4181 retval,
4182 indices,
4183 merged);
4184
4185 if (success)
4186 first_ = first;
4187
4188
4189 if constexpr (detail::hl::size(retval) == llong<1>{}) {
4190 using namespace literals;
4191 return parser::get(retval, 0_c);
4192 } else {
4193 return retval;
4194 }
4195 }
4196
4197 template<
4198 typename Iter,
4199 typename Sentinel,
4200 typename Context,
4201 typename SkipParser,
4202 typename Attribute>
4203 void call(
4204 Iter & first_,
4205 Sentinel last,
4206 Context const & context,
4207 SkipParser const & skip,
4208 detail::flags flags,
4209 bool & success,
4210 Attribute & retval) const
4211 {
4212 [[maybe_unused]] auto _ = detail::scoped_trace(
4213 *this,
4214 first_,
4215 last,
4216 context,
4217 detail::in_apply_parser(flags) ? detail::disable_trace(flags)
4218 : flags,
4219 retval);
4220
4221 Iter first = first_;
4222
4223 auto temp_result =
4224 make_temp_result(first, last, context, skip, flags, success);
4225 using temp_result_attr_t =
4226 std::decay_t<decltype(parser::get(temp_result, llong<0>{}))>;
4227 std::decay_t<decltype(parser::get(temp_result, llong<1>{}))>
4228 indices;
4229 std::decay_t<decltype(parser::get(temp_result, llong<2>{}))> merged;
4230
4231 auto max_ = [](auto result, auto x) {
4232 if constexpr (decltype(result)::value < decltype(x)::value) {
4233 return x;
4234 } else {
4235 return result;
4236 }
4237 };
4238 using max_index_t =
4239 decltype(detail::hl::fold_left(indices, llong<0>{}, max_));
4240
4241 if constexpr (detail::is_optional_v<Attribute>) {
4242 typename Attribute::value_type attr;
4243 call(first, last, context, skip, flags, success, attr);
4244 if (success)
4245 detail::assign(retval, std::move(attr));
4246 } else if constexpr (
4247 detail::is_tuple<Attribute>{} ||
4248 detail::is_struct_compatible_v<Attribute, temp_result_attr_t>) {
4249 call_impl(
4250 first,
4251 last,
4252 context,
4253 skip,
4254 flags,
4255 success,
4256 retval,
4257 indices,
4258 merged);
4259
4260 if (!success)
4261 detail::assign(retval, Attribute());
4262 } else if constexpr (
4263 0 < max_index_t::value && detail::is_constructible_from_tuple_v<
4264 Attribute,
4265 temp_result_attr_t>) {
4266 temp_result_attr_t temp_retval{};
4267 call_impl(
4268 first,
4269 last,
4270 context,
4271 skip,
4272 flags,
4273 success,
4274 temp_retval,
4275 indices,
4276 merged);
4277
4278 if (success && detail::gen_attrs(flags)) {
4279 detail::assign(
4280 retval,
4281 detail::make_from_tuple<Attribute>(
4282 std::move(temp_retval)));
4283 }
4284 } else {
4285
4286 tuple<Attribute> temp_retval{};
4287 call_impl(
4288 first,
4289 last,
4290 context,
4291 skip,
4292 flags,
4293 success,
4294 temp_retval,
4295 indices,
4296 merged);
4297
4298 if (success && detail::gen_attrs(flags)) {
4299 detail::assign(
4300 retval, std::move(detail::hl::front(temp_retval)));
4301 }
4302 }
4303
4304 if (success)
4305 first_ = first;
4306 }
4307
4308
4309
4310
4311 template<
4312 typename Iter,
4313 typename Sentinel,
4314 typename Context,
4315 typename SkipParser,
4316 typename Attribute,
4317 typename Indices,
4318 typename Merged>
4319 void call_impl(
4320 Iter & first,
4321 Sentinel last,
4322 Context const & context,
4323 SkipParser const & skip,
4324 detail::flags flags,
4325 bool & success,
4326 Attribute & retval,
4327 Indices const & indices,
4328 Merged const & merged) const
4329 {
4330 using detail::merge_wrap;
4331 using detail::merge_kind;
4332
4333 static_assert(
4334 detail::is_tuple<Attribute>{} || std::is_aggregate_v<Attribute>,
4335 "");
4336
4337 auto use_parser = [&first,
4338 last,
4339 &context,
4340 &skip,
4341 flags_ = flags,
4342 &success,
4343 &retval](auto const &
4344 parser_index_merged_and_backtrack) {
4345 auto flags = flags_;
4346 using namespace literals;
4347 detail::skip(first, last, skip, flags);
4348 if (!success)
4349 return;
4350
4351 auto const & parser =
4352 parser::get(parser_index_merged_and_backtrack, 0_c);
4353 auto merge_kind_t_ =
4354 parser::get(parser_index_merged_and_backtrack, 2_c);
4355 constexpr bool was_merged_into_adjacent_container =
4356 decltype(merge_kind_t_)::kind == merge_kind::merged;
4357 constexpr bool is_in_a_group =
4358 decltype(merge_kind_t_)::kind == merge_kind::group;
4359 bool const can_backtrack =
4360 parser::get(parser_index_merged_and_backtrack, 3_c);
4361
4362 if (!detail::gen_attrs(flags)) {
4363 parser.call(first, last, context, skip, flags, success);
4364 if (!success && !can_backtrack) {
4365 std::stringstream oss;
4366 detail::print_parser(context, parser, oss);
4367 throw parse_error<Iter>(first, oss.str());
4368 }
4369 return;
4370 }
4371
4372 auto const tuple_idx =
4373 parser::get(parser_index_merged_and_backtrack, 1_c);
4374 auto const tuple_size = detail::tuple_or_struct_size(retval);
4375 static_assert(
4376 decltype(tuple_idx)::value < decltype(tuple_size)::value,
4377 "Looks like you're trying to write some attribute into an "
4378 "out-of-bounds position in a tuple/struct. In other "
4379 "words, the attribute you're parsing into does not match "
4380 "the default attribute used by this parser. This may be "
4381 "because you passed an out-param to parse() at the top "
4382 "level that is not compatible with the attribute type "
4383 "generated by the parser you passed to parse().");
4384 if constexpr (!(decltype(tuple_idx)::value <
4385 decltype(tuple_size)::value)) {
4386 [[maybe_unused]] detail::print_type<Attribute> _;
4387 }
4388 auto & out = parser::get(retval, tuple_idx);
4389
4390 using attr_t = decltype(parser.call(
4391 first, last, context, skip, flags, success));
4392 constexpr bool out_container =
4393 container<std::decay_t<decltype(out)>>;
4394 constexpr bool attr_container = container<attr_t>;
4395
4396 if constexpr (
4397 (out_container == attr_container &&
4398 !was_merged_into_adjacent_container) ||
4399 is_in_a_group) {
4400 parser.call(
4401 first, last, context, skip, flags, success, out);
4402 if (!success) {
4403 if (!can_backtrack) {
4404 std::stringstream oss;
4405 detail::print_parser(context, parser, oss);
4406 throw parse_error<Iter>(first, oss.str());
4407 }
4408 out = std::decay_t<decltype(out)>();
4409 return;
4410 }
4411 } else {
4412 attr_t x =
4413 parser.call(first, last, context, skip, flags, success);
4414 if (!success) {
4415 if (!can_backtrack) {
4416 std::stringstream oss;
4417 detail::print_parser(context, parser, oss);
4418 throw parse_error<Iter>(first, oss.str());
4419 }
4420 return;
4421 }
4422 using just_x = attr_t;
4423 using just_out = detail::remove_cv_ref_t<decltype(out)>;
4424 if constexpr (
4425 (!out_container ||
4426 !std::is_same_v<just_x, just_out>) &&
4427 std::is_assignable_v<just_out &, just_x &&> &&
4428 (!std::is_same_v<just_out, std::string> ||
4429 !std::is_integral_v<just_x>)) {
4430 detail::assign(out, std::move(x));
4431 } else {
4432 detail::move_back(
4433 out, std::move(x), detail::gen_attrs(flags));
4434 }
4435 }
4436 };
4437
4438 auto const parsers_and_indices =
4439 detail::hl::zip(parsers_, indices, merged, backtracking{});
4440 detail::hl::for_each(parsers_and_indices, use_parser);
4441 }
4442
4443 template<bool AllowBacktracking, typename Parser>
4444 constexpr auto prepend(parser_interface<Parser> parser) const noexcept;
4445 template<bool AllowBacktracking, typename Parser>
4446 constexpr auto append(parser_interface<Parser> parser) const noexcept;
4447
4448 ParserTuple parsers_;
4449 };
4450
4451 #endif
4452
4453 namespace detail {
4454 template<typename Action, typename Attribute>
4455 using action_direct_call_expr =
4456 decltype(std::declval<Action>()(std::declval<Attribute>()));
4457 template<typename Action, typename Attribute>
4458 using action_apply_call_expr = decltype(hl::apply(
4459 std::declval<Action>(), std::declval<Attribute>()));
4460 template<typename Action, typename Attribute, typename Context>
4461 using action_assignable_to_val_direct_expr =
4462 decltype(_val(std::declval<Context>()) = std::declval<Action>()(std::declval<Attribute>()));
4463 template<typename Action, typename Attribute, typename Context>
4464 using action_assignable_to_val_apply_expr =
4465 decltype(_val(std::declval<Context>()) = hl::apply(std::declval<Action>(), std::declval<Attribute>()));
4466
4467 template<typename Action, typename Attribute, typename Context>
4468 constexpr auto action_assignable_to_val_direct()
4469 {
4470 if constexpr (is_nope_v<decltype(*std::declval<Context>().val_)>) {
4471 return false;
4472 } else if constexpr (!is_detected_v<
4473 action_direct_call_expr,
4474 Action,
4475 Attribute>) {
4476 return false;
4477 } else if constexpr (std::is_same_v<
4478 action_direct_call_expr<Action, Attribute>,
4479 void>) {
4480 return false;
4481 } else {
4482 return is_detected_v<
4483 action_assignable_to_val_direct_expr,
4484 Action,
4485 Attribute,
4486 Context>;
4487 }
4488 }
4489
4490 template<typename Action, typename Attribute, typename Context>
4491 constexpr auto action_assignable_to_val_apply()
4492 {
4493 if constexpr (is_nope_v<decltype(*std::declval<Context>().val_)>) {
4494 return false;
4495 } else if constexpr (!is_tuple<remove_cv_ref_t<Attribute>>{}) {
4496 return false;
4497 } else if constexpr (tuple_size_<remove_cv_ref_t<Attribute>> < 2) {
4498 return false;
4499 } else if constexpr (!is_detected_v<
4500 action_apply_call_expr,
4501 Action,
4502 Attribute>) {
4503 return false;
4504 } else if constexpr (std::is_same_v<
4505 action_apply_call_expr<Action, Attribute>,
4506 void>) {
4507 return false;
4508 } else {
4509 return is_detected_v<
4510 action_assignable_to_val_apply_expr,
4511 Action,
4512 Attribute,
4513 Context>;
4514 }
4515 }
4516
4517 template<typename Context, typename TagType>
4518 constexpr bool in_recursion =
4519 std::is_same_v<typename Context::rule_tag, TagType> &&
4520 !std::is_same_v<typename Context::rule_tag, void>;
4521 }
4522
4523 #ifndef BOOST_PARSER_DOXYGEN
4524
4525 template<typename Parser, typename Action>
4526 struct action_parser
4527 {
4528 template<
4529 typename Iter,
4530 typename Sentinel,
4531 typename Context,
4532 typename SkipParser>
4533 detail::nope call(
4534 Iter & first,
4535 Sentinel last,
4536 Context const & context,
4537 SkipParser const & skip,
4538 detail::flags flags,
4539 bool & success) const
4540 {
4541 detail::nope retval;
4542 call(first, last, context, skip, flags, success, retval);
4543 return retval;
4544 }
4545
4546 template<
4547 typename Iter,
4548 typename Sentinel,
4549 typename Context,
4550 typename SkipParser,
4551 typename Attribute>
4552 void call(
4553 Iter & first,
4554 Sentinel last,
4555 Context const & context,
4556 SkipParser const & skip,
4557 detail::flags flags,
4558 bool & success,
4559 Attribute & retval) const
4560 {
4561 [[maybe_unused]] auto _ = detail::scoped_trace(
4562 *this, first, last, context, flags, retval);
4563
4564 auto const initial_first = first;
4565 auto attr = parser_.call(
4566 first,
4567 last,
4568 context,
4569 skip,
4570 detail::enable_attrs(flags),
4571 success);
4572
4573 if (!success)
4574 return;
4575
4576 if constexpr (detail::action_assignable_to_val_apply<
4577 decltype(action_) &,
4578 decltype(attr),
4579 decltype(context)>()) {
4580 _val(context) = detail::hl::apply(action_, std::move(attr));
4581 } else {
4582 BOOST_PARSER_SUBRANGE const where(initial_first, first);
4583 auto const action_context =
4584 detail::make_action_context(context, attr, where);
4585 if constexpr (detail::action_assignable_to_val_direct<
4586 decltype(action_) &,
4587 decltype(action_context) &,
4588 decltype(action_context) &>()) {
4589 _val(action_context) = action_(action_context);
4590 } else if constexpr (std::is_same_v<
4591 decltype(action_(action_context)),
4592 void>) {
4593 action_(action_context);
4594 } else {
4595
4596
4597
4598
4599
4600
4601
4602 [[maybe_unused]] none n = action_(action_context);
4603 }
4604 }
4605 }
4606
4607 Parser parser_;
4608 Action action_;
4609 };
4610
4611 template<typename Parser, typename F>
4612 struct transform_parser
4613 {
4614 template<
4615 typename Iter,
4616 typename Sentinel,
4617 typename Context,
4618 typename SkipParser>
4619 auto call(
4620 Iter & first,
4621 Sentinel last,
4622 Context const & context,
4623 SkipParser const & skip,
4624 detail::flags flags,
4625 bool & success) const
4626 {
4627 [[maybe_unused]] auto _ = detail::scoped_trace(
4628 *this, first, last, context, flags, detail::global_nope);
4629 auto attr =
4630 parser_.call(first, last, context, skip, flags, success);
4631 if (success && detail::gen_attrs(flags))
4632 return f_(std::move(attr));
4633 else
4634 return decltype(f_(std::move(attr))){};
4635 }
4636
4637 template<
4638 typename Iter,
4639 typename Sentinel,
4640 typename Context,
4641 typename SkipParser,
4642 typename Attribute>
4643 void call(
4644 Iter & first,
4645 Sentinel last,
4646 Context const & context,
4647 SkipParser const & skip,
4648 detail::flags flags,
4649 bool & success,
4650 Attribute & retval) const
4651 {
4652 [[maybe_unused]] auto _ = detail::scoped_trace(
4653 *this, first, last, context, flags, retval);
4654 auto attr =
4655 parser_.call(first, last, context, skip, flags, success);
4656 if (success && detail::gen_attrs(flags))
4657 detail::assign(retval, f_(std::move(attr)));
4658 }
4659
4660 Parser parser_;
4661 F f_;
4662 };
4663
4664 template<typename Parser>
4665 struct omit_parser
4666 {
4667 template<
4668 typename Iter,
4669 typename Sentinel,
4670 typename Context,
4671 typename SkipParser>
4672 detail::nope call(
4673 Iter & first,
4674 Sentinel last,
4675 Context const & context,
4676 SkipParser const & skip,
4677 detail::flags flags,
4678 bool & success) const
4679 {
4680 [[maybe_unused]] auto _ = detail::scoped_trace(
4681 *this, first, last, context, flags, detail::global_nope);
4682
4683 parser_.call(
4684 first,
4685 last,
4686 context,
4687 skip,
4688 detail::disable_attrs(flags),
4689 success);
4690 return {};
4691 }
4692
4693 template<
4694 typename Iter,
4695 typename Sentinel,
4696 typename Context,
4697 typename SkipParser,
4698 typename Attribute>
4699 void call(
4700 Iter & first,
4701 Sentinel last,
4702 Context const & context,
4703 SkipParser const & skip,
4704 detail::flags flags,
4705 bool & success,
4706 Attribute & retval) const
4707 {
4708 [[maybe_unused]] auto _ = detail::scoped_trace(
4709 *this, first, last, context, flags, retval);
4710
4711 parser_.call(
4712 first,
4713 last,
4714 context,
4715 skip,
4716 detail::disable_attrs(flags),
4717 success);
4718 }
4719
4720 Parser parser_;
4721 };
4722
4723 template<typename Parser>
4724 struct raw_parser
4725 {
4726 template<
4727 typename Iter,
4728 typename Sentinel,
4729 typename Context,
4730 typename SkipParser>
4731 BOOST_PARSER_SUBRANGE<Iter> call(
4732 Iter & first,
4733 Sentinel last,
4734 Context const & context,
4735 SkipParser const & skip,
4736 detail::flags flags,
4737 bool & success) const
4738 {
4739 BOOST_PARSER_SUBRANGE<Iter> retval;
4740 call(first, last, context, skip, flags, success, retval);
4741 return retval;
4742 }
4743
4744 template<
4745 typename Iter,
4746 typename Sentinel,
4747 typename Context,
4748 typename SkipParser,
4749 typename Attribute>
4750 void call(
4751 Iter & first,
4752 Sentinel last,
4753 Context const & context,
4754 SkipParser const & skip,
4755 detail::flags flags,
4756 bool & success,
4757 Attribute & retval) const
4758 {
4759 [[maybe_unused]] auto _ = detail::scoped_trace(
4760 *this, first, last, context, flags, retval);
4761
4762 auto const initial_first = first;
4763 parser_.call(
4764 first,
4765 last,
4766 context,
4767 skip,
4768 detail::disable_attrs(flags),
4769 success);
4770 if (success && detail::gen_attrs(flags))
4771 detail::assign(
4772 retval, BOOST_PARSER_SUBRANGE<Iter>(initial_first, first));
4773 }
4774
4775 Parser parser_;
4776 };
4777
4778 #if BOOST_PARSER_USE_CONCEPTS
4779 template<typename Parser>
4780 struct string_view_parser
4781 {
4782 template<
4783 typename Iter,
4784 typename Sentinel,
4785 typename Context,
4786 typename SkipParser>
4787 auto call(
4788 Iter & first,
4789 Sentinel last,
4790 Context const & context,
4791 SkipParser const & skip,
4792 detail::flags flags,
4793 bool & success) const
4794 {
4795 auto r =
4796 parser::detail::text::unpack_iterator_and_sentinel(first, last);
4797 static_assert(
4798 std::contiguous_iterator<decltype(r.first)>,
4799 "string_view_parser and the string_view[] directive that uses "
4800 "it requires that the underlying char sequence being parsed be "
4801 "a contiguous range. If you're seeing this static_assert, you "
4802 "have not met this contract.");
4803 using char_type = detail::remove_cv_ref_t<decltype(*r.first)>;
4804 std::basic_string_view<char_type> retval;
4805 call(first, last, context, skip, flags, success, retval);
4806 return retval;
4807 }
4808
4809 template<
4810 typename Iter,
4811 typename Sentinel,
4812 typename Context,
4813 typename SkipParser,
4814 typename Attribute>
4815 void call(
4816 Iter & first,
4817 Sentinel last,
4818 Context const & context,
4819 SkipParser const & skip,
4820 detail::flags flags,
4821 bool & success,
4822 Attribute & retval) const
4823 {
4824 [[maybe_unused]] auto _ = detail::scoped_trace(
4825 *this, first, last, context, flags, retval);
4826
4827 auto const initial_first = first;
4828 parser_.call(
4829 first,
4830 last,
4831 context,
4832 skip,
4833 detail::disable_attrs(flags),
4834 success);
4835
4836 if (!success || !detail::gen_attrs(flags))
4837 return;
4838
4839 auto r = parser::detail::text::unpack_iterator_and_sentinel(
4840 initial_first, first);
4841 static_assert(
4842 std::contiguous_iterator<decltype(r.first)>,
4843 "string_view_parser and the string_view[] directive that uses "
4844 "it requires that the underlying char sequence being parsed be "
4845 "a contiguous range. If you're seeing this static_assert, you "
4846 "have not met this contract.");
4847 using char_type = detail::remove_cv_ref_t<decltype(*r.first)>;
4848 if (initial_first == first) {
4849 detail::assign(retval, std::basic_string_view<char_type>{});
4850 } else {
4851 detail::assign(
4852 retval,
4853 std::basic_string_view<char_type>{
4854 &*r.first, std::size_t(r.last - r.first)});
4855 }
4856 }
4857
4858 Parser parser_;
4859 };
4860 #endif
4861
4862 template<typename Parser>
4863 struct lexeme_parser
4864 {
4865 template<
4866 typename Iter,
4867 typename Sentinel,
4868 typename Context,
4869 typename SkipParser>
4870 auto call(
4871 Iter & first,
4872 Sentinel last,
4873 Context const & context,
4874 SkipParser const & skip,
4875 detail::flags flags,
4876 bool & success) const
4877 {
4878 using attr_t = decltype(parser_.call(
4879 first, last, context, skip, flags, success));
4880 attr_t retval{};
4881 call(first, last, context, skip, flags, success, retval);
4882 return retval;
4883 }
4884
4885 template<
4886 typename Iter,
4887 typename Sentinel,
4888 typename Context,
4889 typename SkipParser,
4890 typename Attribute>
4891 void call(
4892 Iter & first,
4893 Sentinel last,
4894 Context const & context,
4895 SkipParser const & skip,
4896 detail::flags flags,
4897 bool & success,
4898 Attribute & retval) const
4899 {
4900 [[maybe_unused]] auto _ = detail::scoped_trace(
4901 *this, first, last, context, flags, retval);
4902
4903 parser_.call(
4904 first,
4905 last,
4906 context,
4907 skip,
4908 detail::disable_skip(flags),
4909 success,
4910 retval);
4911 }
4912
4913 Parser parser_;
4914 };
4915
4916 template<typename Parser>
4917 struct no_case_parser
4918 {
4919 template<
4920 typename Iter,
4921 typename Sentinel,
4922 typename Context,
4923 typename SkipParser>
4924 auto call(
4925 Iter & first,
4926 Sentinel last,
4927 Context const & context_,
4928 SkipParser const & skip,
4929 detail::flags flags,
4930 bool & success) const
4931 {
4932 auto context = context_;
4933 ++context.no_case_depth_;
4934
4935 using attr_t = decltype(parser_.call(
4936 first, last, context, skip, flags, success));
4937 attr_t retval{};
4938 call(first, last, context, skip, flags, success, retval);
4939 return retval;
4940 }
4941
4942 template<
4943 typename Iter,
4944 typename Sentinel,
4945 typename Context,
4946 typename SkipParser,
4947 typename Attribute>
4948 void call(
4949 Iter & first,
4950 Sentinel last,
4951 Context const & context_,
4952 SkipParser const & skip,
4953 detail::flags flags,
4954 bool & success,
4955 Attribute & retval) const
4956 {
4957 auto context = context_;
4958 ++context.no_case_depth_;
4959
4960 [[maybe_unused]] auto _ = detail::scoped_trace(
4961 *this, first, last, context, flags, retval);
4962
4963 parser_.call(first, last, context, skip, flags, success, retval);
4964 }
4965
4966 Parser parser_;
4967 };
4968
4969 template<typename Parser, typename SkipParser>
4970 struct skip_parser
4971 {
4972 template<
4973 typename Iter,
4974 typename Sentinel,
4975 typename Context,
4976 typename SkipParser_>
4977 auto call(
4978 Iter & first,
4979 Sentinel last,
4980 Context const & context,
4981 SkipParser_ const & skip,
4982 detail::flags flags,
4983 bool & success) const
4984 {
4985 using attr_t = decltype(parser_.call(
4986 first, last, context, skip, flags, success));
4987 attr_t retval{};
4988 call(first, last, context, skip, flags, success, retval);
4989 return retval;
4990 }
4991
4992 template<
4993 typename Iter,
4994 typename Sentinel,
4995 typename Context,
4996 typename SkipParser_,
4997 typename Attribute>
4998 void call(
4999 Iter & first,
5000 Sentinel last,
5001 Context const & context,
5002 SkipParser_ const & skip,
5003 detail::flags flags,
5004 bool & success,
5005 Attribute & retval) const
5006 {
5007 [[maybe_unused]] auto _ = detail::scoped_trace(
5008 *this, first, last, context, flags, retval);
5009
5010 if constexpr (detail::is_nope_v<SkipParser>) {
5011 parser_.call(
5012 first,
5013 last,
5014 context,
5015 skip,
5016 detail::enable_skip(flags),
5017 success,
5018 retval);
5019 } else {
5020 parser_.call(
5021 first,
5022 last,
5023 context,
5024 skip_parser_,
5025 detail::enable_skip(flags),
5026 success,
5027 retval);
5028 }
5029 }
5030
5031 Parser parser_;
5032 SkipParser skip_parser_;
5033 };
5034
5035 template<typename Parser, bool FailOnMatch>
5036 struct expect_parser
5037 {
5038 template<
5039 typename Iter,
5040 typename Sentinel,
5041 typename Context,
5042 typename SkipParser>
5043 detail::nope call(
5044 Iter & first,
5045 Sentinel last,
5046 Context const & context,
5047 SkipParser const & skip,
5048 detail::flags flags,
5049 bool & success) const
5050 {
5051 detail::nope retval;
5052 call(first, last, context, skip, flags, success, retval);
5053 return retval;
5054 }
5055
5056 template<
5057 typename Iter,
5058 typename Sentinel,
5059 typename Context,
5060 typename SkipParser,
5061 typename Attribute>
5062 void call(
5063 Iter & first,
5064 Sentinel last,
5065 Context const & context,
5066 SkipParser const & skip,
5067 detail::flags flags,
5068 bool & success,
5069 Attribute & retval) const
5070 {
5071 [[maybe_unused]] auto _ = detail::scoped_trace(
5072 *this, first, last, context, flags, retval);
5073
5074 auto first_copy = first;
5075 parser_.call(
5076 first_copy,
5077 last,
5078 context,
5079 skip,
5080 detail::disable_attrs(flags),
5081 success);
5082 if (FailOnMatch)
5083 success = !success;
5084 }
5085
5086 Parser parser_;
5087 };
5088
5089 template<typename T>
5090 struct symbol_parser
5091 {
5092 symbol_parser() : copied_from_(nullptr) {}
5093 explicit symbol_parser(std::string_view diagnostic_text) :
5094 copied_from_(nullptr), diagnostic_text_(diagnostic_text)
5095 {}
5096 symbol_parser(symbol_parser const & other) :
5097 initial_elements_(other.initial_elements_),
5098 copied_from_(other.copied_from_ ? other.copied_from_ : &other),
5099 diagnostic_text_(other.diagnostic_text_)
5100 {}
5101 symbol_parser(symbol_parser && other) :
5102 initial_elements_(std::move(other.initial_elements_)),
5103 copied_from_(other.copied_from_),
5104 diagnostic_text_(other.diagnostic_text_)
5105 {}
5106
5107
5108
5109
5110
5111 template<typename Context>
5112 void insert_for_next_parse(
5113 Context const & context, std::string_view str, T x)
5114 {
5115 auto & pending_ops =
5116 detail::get_pending_symtab_ops(context, ref());
5117 pending_ops.push_back(detail::symbol_table_operation<T>{
5118 std::string(str),
5119 std::move(x),
5120 detail::symbol_table_op::insert});
5121 }
5122
5123
5124
5125
5126
5127 template<typename Context>
5128 void erase_for_next_parse(Context const & context, std::string_view str)
5129 {
5130 auto & pending_ops =
5131 detail::get_pending_symtab_ops(context, ref());
5132 pending_ops.push_back(detail::symbol_table_operation<T>{
5133 std::string(str),
5134 std::nullopt,
5135 detail::symbol_table_op::erase});
5136 }
5137
5138
5139
5140 template<typename Context>
5141 void clear_for_next_parse(Context const & context)
5142 {
5143 auto & pending_ops =
5144 detail::get_pending_symtab_ops(context, ref());
5145 pending_ops.push_back(detail::symbol_table_operation<T>{
5146 {}, std::nullopt, detail::symbol_table_op::clear});
5147 }
5148
5149
5150
5151
5152
5153 template<typename Context>
5154 parser::detail::text::optional_ref<T>
5155 find(Context const & context, std::string_view str) const
5156 {
5157 auto [trie, has_case_folded] = detail::get_trie(context, ref());
5158 if (context.no_case_depth_) {
5159 return trie[detail::case_fold_view(
5160 str | detail::text::as_utf32)];
5161 } else {
5162 return trie[str | detail::text::as_utf32];
5163 }
5164 }
5165
5166
5167
5168
5169 template<typename Context>
5170 void insert(Context const & context, std::string_view str, T && x) const
5171 {
5172 auto [trie, has_case_folded] = detail::get_trie(context, ref());
5173 if (context.no_case_depth_) {
5174 trie.insert(
5175 detail::case_fold_view(str | detail::text::as_utf32),
5176 std::move(x));
5177 } else {
5178 trie.insert(str | detail::text::as_utf32, std::move(x));
5179 }
5180 }
5181
5182
5183
5184 template<typename Context>
5185 void erase(Context const & context, std::string_view str) const
5186 {
5187 auto [trie, has_case_folded] = detail::get_trie(context, ref());
5188 if (context.no_case_depth_) {
5189 trie.erase(
5190 detail::case_fold_view(str | detail::text::as_utf32));
5191 } else {
5192 trie.erase(str | detail::text::as_utf32);
5193 }
5194 }
5195
5196
5197
5198 template<typename Context>
5199 void clear(Context const & context) const
5200 {
5201 auto [trie, _] = detail::get_trie(context, ref());
5202 trie.clear();
5203 }
5204
5205 template<
5206 typename Iter,
5207 typename Sentinel,
5208 typename Context,
5209 typename SkipParser>
5210 T call(
5211 Iter & first,
5212 Sentinel last,
5213 Context const & context,
5214 SkipParser const & skip,
5215 detail::flags flags,
5216 bool & success) const
5217 {
5218 T retval{};
5219 call(first, last, context, skip, flags, success, retval);
5220 return retval;
5221 }
5222
5223 template<
5224 typename Iter,
5225 typename Sentinel,
5226 typename Context,
5227 typename SkipParser,
5228 typename Attribute>
5229 void call(
5230 Iter & first,
5231 Sentinel last,
5232 Context const & context,
5233 SkipParser const & skip,
5234 detail::flags flags,
5235 bool & success,
5236 Attribute & retval) const
5237 {
5238 [[maybe_unused]] auto _ = detail::scoped_trace(
5239 *this, first, last, context, flags, retval);
5240
5241 auto [trie, _0] = detail::get_trie(context, ref());
5242 auto const lookup = context.no_case_depth_
5243 ? trie.longest_match(detail::case_fold_view(
5244 BOOST_PARSER_SUBRANGE(first, last)))
5245 : trie.longest_match(first, last);
5246 if (lookup.match) {
5247 std::advance(first, lookup.size);
5248 detail::assign(retval, T{*trie[lookup]});
5249 } else {
5250 success = false;
5251 }
5252 }
5253
5254 mutable std::vector<std::pair<std::string, T>> initial_elements_;
5255 symbol_parser const * copied_from_;
5256
5257 symbol_parser const & ref() const noexcept
5258 {
5259 if (copied_from_)
5260 return *copied_from_;
5261 return *this;
5262 }
5263 std::vector<std::pair<std::string, T>> &
5264 initial_elements() const noexcept
5265 {
5266 return ref().initial_elements_;
5267 }
5268
5269 std::string_view diagnostic_text_;
5270 };
5271
5272 template<
5273 bool CanUseCallbacks,
5274 typename TagType,
5275 typename Attribute,
5276 typename LocalState,
5277 typename ParamsTuple>
5278 struct rule_parser
5279 {
5280 using tag_type = TagType;
5281 using attr_type = Attribute;
5282 using locals_type = LocalState;
5283
5284 template<
5285 typename Iter,
5286 typename Sentinel,
5287 typename Context,
5288 typename SkipParser>
5289 std::conditional_t<
5290 detail::in_recursion<Context, tag_type>,
5291 detail::nope,
5292 attr_type>
5293 call(
5294 Iter & first,
5295 Sentinel last,
5296 Context const & context,
5297 SkipParser const & skip,
5298 detail::flags flags,
5299 bool & success) const
5300 {
5301 constexpr bool in_recursion =
5302 detail::in_recursion<Context, tag_type>;
5303
5304 if constexpr (in_recursion)
5305 flags = detail::disable_attrs(flags);
5306
5307 attr_type retval{};
5308 locals_type locals = detail::make_locals<locals_type>(context);
5309 auto params = detail::resolve_rule_params(context, params_);
5310 tag_type * const tag_ptr = nullptr;
5311 auto const rule_context = detail::make_rule_context(
5312 context, tag_ptr, retval, locals, params);
5313 [[maybe_unused]] auto _ = detail::scoped_trace(
5314 *this, first, last, rule_context, flags, retval);
5315
5316 bool dont_assign = false;
5317 if constexpr (in_recursion) {
5318
5319
5320
5321 parse_rule(
5322 tag_ptr,
5323 first,
5324 last,
5325 rule_context,
5326 skip,
5327 flags,
5328 success,
5329 dont_assign,
5330 retval);
5331 } else {
5332 auto attr = parse_rule(
5333 tag_ptr,
5334 first,
5335 last,
5336 rule_context,
5337 skip,
5338 flags,
5339 success,
5340 dont_assign);
5341 if (success && !dont_assign) {
5342 if constexpr (!detail::is_nope_v<decltype(attr)>)
5343 detail::assign(retval, attr);
5344 }
5345 }
5346
5347 if constexpr (
5348 CanUseCallbacks && Context::use_callbacks && !in_recursion) {
5349 if (!success)
5350 return attr_type{};
5351
5352 auto const & callbacks = _callbacks(context);
5353
5354 if constexpr (detail::is_nope_v<attr_type>) {
5355 static_assert(
5356 detail::is_invocable_v<decltype(callbacks), tag_type>,
5357 "For rules without attributes, Callbacks must be a "
5358 "struct with overloads of the form void(tag_type). If "
5359 "you're seeing an error here, you probably have not "
5360 "met this contract.");
5361 callbacks(tag_type{});
5362 } else {
5363 static_assert(
5364 detail::is_invocable_v<
5365 decltype(callbacks),
5366 tag_type,
5367 decltype(std::move(retval))>,
5368 "For rules with attributes, Callbacks must be a struct "
5369 "with overloads of the form void(tag_type, attr_type). "
5370 "If you're seeing an error here, you probably have not "
5371 "met this contract.");
5372 callbacks(tag_type{}, std::move(retval));
5373 }
5374
5375 return attr_type{};
5376 } else {
5377 if (!success && !in_recursion)
5378 detail::assign(retval, attr_type());
5379 if constexpr (in_recursion)
5380 return detail::nope{};
5381 else
5382 return retval;
5383 }
5384 }
5385
5386 template<
5387 typename Iter,
5388 typename Sentinel,
5389 typename Context,
5390 typename SkipParser,
5391 typename Attribute_>
5392 void call(
5393 Iter & first,
5394 Sentinel last,
5395 Context const & context,
5396 SkipParser const & skip,
5397 detail::flags flags,
5398 bool & success,
5399 Attribute_ & retval) const
5400 {
5401 if constexpr (CanUseCallbacks && Context::use_callbacks) {
5402 call(first, last, context, skip, flags, success);
5403 } else {
5404 auto attr = call(first, last, context, skip, flags, success);
5405 if (success)
5406 detail::assign(retval, std::move(attr));
5407 }
5408 }
5409
5410 std::string_view diagnostic_text_;
5411 ParamsTuple params_;
5412 };
5413
5414 #endif
5415
5416
5417
5418 template<typename Parser, typename GlobalState, typename ErrorHandler>
5419 struct parser_interface
5420 {
5421 using parser_type = Parser;
5422 using global_state_type = GlobalState;
5423 using error_handler_type = ErrorHandler;
5424
5425 constexpr parser_interface() : parser_() {}
5426 constexpr parser_interface(parser_type p) : parser_(std::move(p)) {}
5427 constexpr parser_interface(
5428 parser_type p, global_state_type gs, error_handler_type eh) :
5429 parser_(p), globals_(gs), error_handler_(eh)
5430 {}
5431
5432
5433
5434
5435 constexpr auto operator!() const noexcept
5436 {
5437 return parser::parser_interface{
5438 expect_parser<parser_type, true>{parser_}};
5439 }
5440
5441
5442
5443
5444 constexpr auto operator&() const noexcept
5445 {
5446 return parser::parser_interface{
5447 expect_parser<parser_type, false>{parser_}};
5448 }
5449
5450
5451
5452 constexpr auto operator*() const noexcept
5453 {
5454 if constexpr (detail::is_zero_plus_p<parser_type>{}) {
5455 return *this;
5456 } else if constexpr (detail::is_one_plus_p<parser_type>{}) {
5457 using inner_parser = decltype(parser_type::parser_);
5458 return parser::parser_interface{
5459 zero_plus_parser<inner_parser>(parser_.parser_)};
5460 } else {
5461 return parser::parser_interface{
5462 zero_plus_parser<parser_type>(parser_)};
5463 }
5464 }
5465
5466
5467
5468 constexpr auto operator+() const noexcept
5469 {
5470 if constexpr (detail::is_zero_plus_p<parser_type>{}) {
5471 using inner_parser = decltype(parser_type::parser_);
5472 return parser::parser_interface{
5473 zero_plus_parser<inner_parser>(parser_.parser_)};
5474 } else if constexpr (detail::is_one_plus_p<parser_type>{}) {
5475 return *this;
5476 } else {
5477 return parser::parser_interface{
5478 one_plus_parser<parser_type>(parser_)};
5479 }
5480 }
5481
5482
5483
5484 constexpr auto operator-() const noexcept
5485 {
5486 return parser::parser_interface{opt_parser<parser_type>{parser_}};
5487 }
5488
5489
5490
5491 template<typename ParserType2>
5492 constexpr auto
5493 operator>>(parser_interface<ParserType2> rhs) const noexcept
5494 {
5495 if constexpr (detail::is_seq_p<parser_type>{}) {
5496 return parser_.template append<true>(rhs);
5497 } else if constexpr (detail::is_seq_p<ParserType2>{}) {
5498 return rhs.parser_.template prepend<true>(*this);
5499 } else {
5500 using parser_t = seq_parser<
5501 tuple<parser_type, ParserType2>,
5502 tuple<std::true_type, std::true_type>,
5503 tuple<llong<0>, llong<0>>>;
5504 return parser::parser_interface{parser_t{
5505 tuple<parser_type, ParserType2>{parser_, rhs.parser_}}};
5506 }
5507 }
5508
5509
5510
5511 constexpr auto operator>>(char rhs) const noexcept;
5512
5513
5514
5515 constexpr auto operator>>(char32_t rhs) const noexcept;
5516
5517
5518
5519 #if BOOST_PARSER_USE_CONCEPTS
5520 template<parsable_range_like R>
5521 #else
5522 template<
5523 typename R,
5524 typename Enable =
5525 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
5526 #endif
5527 constexpr auto operator>>(R && r) const noexcept;
5528
5529
5530
5531
5532
5533
5534 template<typename ParserType2>
5535 constexpr auto
5536 operator>(parser_interface<ParserType2> rhs) const noexcept
5537 {
5538 if constexpr (detail::is_seq_p<parser_type>{}) {
5539 return parser_.template append<false>(rhs);
5540 } else if constexpr (detail::is_seq_p<ParserType2>{}) {
5541 return rhs.parser_.template prepend<false>(*this);
5542 } else {
5543 using parser_t = seq_parser<
5544 tuple<parser_type, ParserType2>,
5545 tuple<std::true_type, std::false_type>,
5546 tuple<llong<0>, llong<0>>>;
5547 return parser::parser_interface{parser_t{
5548 tuple<parser_type, ParserType2>{parser_, rhs.parser_}}};
5549 }
5550 }
5551
5552
5553
5554
5555
5556 constexpr auto operator>(char rhs) const noexcept;
5557
5558
5559
5560
5561
5562 constexpr auto operator>(char32_t rhs) const noexcept;
5563
5564
5565
5566
5567
5568 #if BOOST_PARSER_USE_CONCEPTS
5569 template<parsable_range_like R>
5570 #else
5571 template<
5572 typename R,
5573 typename Enable =
5574 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
5575 #endif
5576 constexpr auto operator>(R && r) const noexcept;
5577
5578
5579
5580 template<typename ParserType2>
5581 constexpr auto
5582 operator|(parser_interface<ParserType2> rhs) const noexcept
5583 {
5584 if constexpr (detail::is_or_p<parser_type>{}) {
5585 return parser_.append(rhs);
5586 } else if constexpr (detail::is_or_p<ParserType2>{}) {
5587 return rhs.parser_.prepend(*this);
5588 } else {
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598 BOOST_PARSER_ASSERT(
5599 !detail::is_unconditional_eps<parser_type>{});
5600 return parser::parser_interface{
5601 or_parser<tuple<parser_type, ParserType2>>{
5602 tuple<parser_type, ParserType2>{parser_, rhs.parser_}}};
5603 }
5604 }
5605
5606
5607
5608
5609
5610 template<typename ParserType2>
5611 constexpr auto
5612 operator||(parser_interface<ParserType2> rhs) const noexcept
5613 {
5614
5615
5616
5617 BOOST_PARSER_ASSERT(!detail::is_eps_p<parser_type>{});
5618 BOOST_PARSER_ASSERT(!detail::is_eps_p<ParserType2>{});
5619 if constexpr (detail::is_perm_p<parser_type>{}) {
5620 return parser_.append(rhs);
5621 } else if constexpr (detail::is_perm_p<ParserType2>{}) {
5622 return rhs.parser_.prepend(*this);
5623 } else {
5624 return parser::parser_interface{
5625 perm_parser<tuple<parser_type, ParserType2>, detail::nope>{
5626 tuple<parser_type, ParserType2>{parser_, rhs.parser_}}};
5627 }
5628 }
5629
5630
5631
5632 constexpr auto operator|(char rhs) const noexcept;
5633
5634
5635
5636 constexpr auto operator|(char32_t rhs) const noexcept;
5637
5638
5639
5640 #if BOOST_PARSER_USE_CONCEPTS
5641 template<parsable_range_like R>
5642 #else
5643 template<
5644 typename R,
5645 typename Enable =
5646 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
5647 #endif
5648 constexpr auto operator|(R && r) const noexcept;
5649
5650
5651
5652 template<typename ParserType2>
5653 constexpr auto
5654 operator-(parser_interface<ParserType2> rhs) const noexcept
5655 {
5656 return !rhs >> *this;
5657 }
5658
5659
5660
5661 constexpr auto operator-(char rhs) const noexcept;
5662
5663
5664
5665 constexpr auto operator-(char32_t rhs) const noexcept;
5666
5667
5668
5669 #if BOOST_PARSER_USE_CONCEPTS
5670 template<parsable_range_like R>
5671 #else
5672 template<
5673 typename R,
5674 typename Enable =
5675 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
5676 #endif
5677 constexpr auto operator-(R && r) const noexcept;
5678
5679
5680
5681 template<typename ParserType2>
5682 constexpr auto
5683 operator%(parser_interface<ParserType2> rhs) const noexcept
5684 {
5685 return parser::parser_interface{
5686 delimited_seq_parser<parser_type, ParserType2>(
5687 parser_, rhs.parser_)};
5688 }
5689
5690
5691
5692 constexpr auto operator%(char rhs) const noexcept;
5693
5694
5695
5696 constexpr auto operator%(char32_t rhs) const noexcept;
5697
5698
5699
5700 #if BOOST_PARSER_USE_CONCEPTS
5701 template<parsable_range_like R>
5702 #else
5703 template<
5704 typename R,
5705 typename Enable =
5706 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
5707 #endif
5708 constexpr auto operator%(R && r) const noexcept;
5709
5710
5711
5712
5713 template<typename Action>
5714 constexpr auto operator[](Action action) const
5715 {
5716 using action_parser_t = action_parser<parser_type, Action>;
5717 return parser::parser_interface{action_parser_t{parser_, action}};
5718 }
5719
5720
5721
5722
5723
5724
5725
5726
5727 template<typename Arg, typename... Args>
5728 constexpr auto operator()(Arg && arg, Args &&... args) const noexcept
5729 -> decltype(std::declval<parser_type const &>()(
5730 (Arg &&) arg, (Args &&) args...))
5731 {
5732 return parser_((Arg &&) arg, (Args &&) args...);
5733 }
5734
5735 #ifndef BOOST_PARSER_DOXYGEN
5736
5737
5738
5739 template<
5740 typename Iter,
5741 typename Sentinel,
5742 typename Context,
5743 typename SkipParserType>
5744 auto operator()(
5745 Iter & first,
5746 Sentinel last,
5747 Context const & context,
5748 SkipParserType const & skip,
5749 detail::flags flags,
5750 bool & success) const
5751 {
5752 return parser_.call(first, last, context, skip, flags, success);
5753 }
5754
5755
5756
5757 template<
5758 typename Iter,
5759 typename Sentinel,
5760 typename Context,
5761 typename SkipParserType,
5762 typename Attribute>
5763 void operator()(
5764 Iter & first,
5765 Sentinel last,
5766 Context const & context,
5767 SkipParserType const & skip,
5768 detail::flags flags,
5769 bool & success,
5770 Attribute & attr) const
5771 {
5772 parser_.call(first, last, context, skip, flags, success, attr);
5773 }
5774
5775 parser_type parser_;
5776 global_state_type globals_;
5777 error_handler_type error_handler_;
5778
5779 #endif
5780
5781 using parser_interface_derivation_tag = int;
5782 };
5783
5784
5785
5786
5787 template<typename Parser, typename GlobalState, typename ErrorHandler>
5788 auto with_globals(
5789 parser_interface<Parser, detail::nope, ErrorHandler> const & parser,
5790 GlobalState & globals)
5791 {
5792 return parser_interface<Parser, GlobalState &, ErrorHandler>{
5793 parser.parser_, globals, parser.error_handler_};
5794 }
5795
5796
5797
5798
5799 template<typename Parser, typename GlobalState, typename ErrorHandler>
5800 auto with_error_handler(
5801 parser_interface<Parser, GlobalState, default_error_handler> const &
5802 parser,
5803 ErrorHandler & error_handler)
5804 {
5805 return parser_interface<Parser, GlobalState, ErrorHandler &>{
5806 parser.parser_, parser.globals_, error_handler};
5807 }
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817 template<typename T>
5818 struct symbols : parser_interface<symbol_parser<T>>
5819 {
5820 symbols() {}
5821 symbols(char const * diagnostic_text) :
5822 parser_interface<symbol_parser<T>>(
5823 symbol_parser<T>(diagnostic_text))
5824 {}
5825 symbols(std::initializer_list<std::pair<std::string_view, T>> il)
5826 {
5827 this->parser_.initial_elements_.resize(il.size());
5828 std::copy(il.begin(), il.end(),
5829 this->parser_.initial_elements_.begin());
5830 }
5831 symbols(
5832 char const * diagnostic_text,
5833 std::initializer_list<std::pair<std::string_view, T>> il) :
5834 parser_interface<symbol_parser<T>>(
5835 symbol_parser<T>(diagnostic_text))
5836 {
5837 this->parser_.initial_elements_.resize(il.size());
5838 std::copy(il.begin(), il.end(),
5839 this->parser_.initial_elements_.begin());
5840 }
5841
5842
5843
5844
5845
5846 void insert_for_next_parse(std::string_view str, T x)
5847 {
5848 this->parser_.initial_elements_.push_back(
5849 std::pair(std::string(str), std::move(x)));
5850 }
5851
5852
5853
5854
5855
5856 void erase_for_next_parse(std::string_view str)
5857 {
5858 auto it = std::find_if(
5859 this->parser_.initial_elements_.begin(),
5860 this->parser_.initial_elements_.end(),
5861 [str](auto const & x) { return x.first == str; });
5862 this->parser_.initial_elements_.erase(it);
5863 }
5864
5865
5866
5867 void clear_for_next_parse() { this->parser_.initial_elements_.clear(); }
5868
5869
5870
5871
5872
5873 template<typename Context>
5874 void insert_for_next_parse(
5875 Context const & context, std::string_view str, T x)
5876 {
5877 this->parser_.insert_for_next_parse(context, str, std::move(x));
5878 }
5879
5880
5881
5882
5883
5884 template<typename Context>
5885 void erase_for_next_parse(Context const & context, std::string_view str)
5886 {
5887 this->parser_.erase_for_next_parse(context, str);
5888 }
5889
5890
5891
5892 template<typename Context>
5893 void clear_for_next_parse(Context const & context)
5894 {
5895 this->parser_.clear_for_next_parse(context);
5896 }
5897
5898
5899
5900
5901
5902 template<typename Context>
5903 parser::detail::text::optional_ref<T>
5904 find(Context const & context, std::string_view str) const
5905 {
5906 return this->parser_.find(context, str);
5907 }
5908
5909
5910
5911
5912 template<typename Context>
5913 void insert(Context const & context, std::string_view str, T x) const
5914 {
5915 this->parser_.insert(context, str, std::move(x));
5916 }
5917
5918
5919
5920 template<typename Context>
5921 void erase(Context const & context, std::string_view str) const
5922 {
5923 this->parser_.erase(context, str);
5924 }
5925
5926
5927
5928 template<typename Context>
5929 void clear(Context const & context) const
5930 {
5931 this->parser_.clear(context);
5932 }
5933 };
5934
5935 #ifndef BOOST_PARSER_DOXYGEN
5936
5937 template<
5938 typename TagType,
5939 typename Attribute,
5940 typename LocalState,
5941 typename ParamsTuple>
5942 struct rule
5943 : parser_interface<
5944 rule_parser<false, TagType, Attribute, LocalState, ParamsTuple>>
5945 {
5946 static_assert(
5947 !std::is_same_v<TagType, void>,
5948 "void is not a valid tag type for a rule.");
5949
5950 constexpr rule(char const * diagnostic_text)
5951 {
5952 this->parser_.diagnostic_text_ = diagnostic_text;
5953 }
5954
5955 template<typename T, typename... Ts>
5956 constexpr auto with(T && x, Ts &&... xs) const
5957 {
5958 BOOST_PARSER_ASSERT(
5959 (detail::is_nope_v<ParamsTuple> &&
5960 "If you're seeing this, you tried to chain calls on a rule, "
5961 "like 'rule.with(foo).with(bar)'. Quit it!'"));
5962 using params_tuple_type = decltype(detail::hl::make_tuple(
5963 static_cast<T &&>(x), static_cast<Ts &&>(xs)...));
5964 using rule_parser_type = rule_parser<
5965 false,
5966 TagType,
5967 Attribute,
5968 LocalState,
5969 params_tuple_type>;
5970 using result_type = parser_interface<rule_parser_type>;
5971 return result_type{rule_parser_type{
5972 this->parser_.diagnostic_text_,
5973 detail::hl::make_tuple(
5974 static_cast<T &&>(x), static_cast<Ts &&>(xs)...)}};
5975 }
5976 };
5977
5978 template<
5979 typename TagType,
5980 typename Attribute,
5981 typename LocalState,
5982 typename ParamsTuple>
5983 struct callback_rule
5984 : parser_interface<
5985 rule_parser<true, TagType, Attribute, LocalState, ParamsTuple>>
5986 {
5987 constexpr callback_rule(char const * diagnostic_text)
5988 {
5989 this->parser_.diagnostic_text_ = diagnostic_text;
5990 }
5991
5992 template<typename T, typename... Ts>
5993 constexpr auto with(T && x, Ts &&... xs) const
5994 {
5995 BOOST_PARSER_ASSERT(
5996 (detail::is_nope_v<ParamsTuple> &&
5997 "If you're seeing this, you tried to chain calls on a "
5998 "callback_rule, like 'rule.with(foo).with(bar)'. Quit it!'"));
5999 using params_tuple_type = decltype(detail::hl::make_tuple(
6000 static_cast<T &&>(x), static_cast<Ts &&>(xs)...));
6001 using rule_parser_type = rule_parser<
6002 true,
6003 TagType,
6004 Attribute,
6005 LocalState,
6006 params_tuple_type>;
6007 using result_type = parser_interface<rule_parser_type>;
6008 return result_type{rule_parser_type{
6009 this->parser_.diagnostic_text_,
6010 detail::hl::make_tuple(
6011 static_cast<T &&>(x), static_cast<Ts &&>(xs)...)}};
6012 }
6013 };
6014
6015
6016 #define BOOST_PARSER_DEFINE_IMPL(_, rule_name_) \
6017 template< \
6018 typename Iter, \
6019 typename Sentinel, \
6020 typename Context, \
6021 typename SkipParser> \
6022 decltype(rule_name_)::parser_type::attr_type parse_rule( \
6023 decltype(rule_name_)::parser_type::tag_type *, \
6024 Iter & first, \
6025 Sentinel last, \
6026 Context const & context, \
6027 SkipParser const & skip, \
6028 boost::parser::detail::flags flags, \
6029 bool & success, \
6030 bool & dont_assign) \
6031 { \
6032 auto const & parser = BOOST_PARSER_PP_CAT(rule_name_, _def); \
6033 using attr_t = \
6034 decltype(parser(first, last, context, skip, flags, success)); \
6035 using attr_type = decltype(rule_name_)::parser_type::attr_type; \
6036 if constexpr (boost::parser::detail::is_nope_v<attr_t>) { \
6037 dont_assign = true; \
6038 parser(first, last, context, skip, flags, success); \
6039 return {}; \
6040 } else if constexpr (std::is_same_v<attr_type, attr_t>) { \
6041 return parser(first, last, context, skip, flags, success); \
6042 } else if constexpr (std::is_constructible_v<attr_type, attr_t>) { \
6043 return attr_type( \
6044 parser(first, last, context, skip, flags, success)); \
6045 } else { \
6046 attr_type attr{}; \
6047 parser(first, last, context, skip, flags, success, attr); \
6048 return attr; \
6049 } \
6050 } \
6051 \
6052 template< \
6053 typename Iter, \
6054 typename Sentinel, \
6055 typename Context, \
6056 typename SkipParser, \
6057 typename Attribute> \
6058 void parse_rule( \
6059 decltype(rule_name_)::parser_type::tag_type *, \
6060 Iter & first, \
6061 Sentinel last, \
6062 Context const & context, \
6063 SkipParser const & skip, \
6064 boost::parser::detail::flags flags, \
6065 bool & success, \
6066 bool & dont_assign, \
6067 Attribute & retval) \
6068 { \
6069 auto const & parser = BOOST_PARSER_PP_CAT(rule_name_, _def); \
6070 using attr_t = \
6071 decltype(parser(first, last, context, skip, flags, success)); \
6072 if constexpr (boost::parser::detail::is_nope_v<attr_t>) { \
6073 parser(first, last, context, skip, flags, success); \
6074 } else { \
6075 parser(first, last, context, skip, flags, success, retval); \
6076 } \
6077 }
6078
6079
6080 #endif
6081
6082
6083
6084
6085
6086
6087 #define BOOST_PARSER_DEFINE_RULES(...) \
6088 BOOST_PARSER_PP_FOR_EACH(BOOST_PARSER_DEFINE_IMPL, _, __VA_ARGS__)
6089
6090
6091 #ifndef BOOST_PARSER_DOXYGEN
6092
6093 template<typename ParserTuple>
6094 template<typename Parser>
6095 constexpr auto or_parser<ParserTuple>::prepend(
6096 parser_interface<Parser> parser) const noexcept
6097 {
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107 BOOST_PARSER_ASSERT(!detail::is_unconditional_eps<Parser>{});
6108 return parser_interface{
6109 or_parser<decltype(detail::hl::prepend(parsers_, parser.parser_))>{
6110 detail::hl::prepend(parsers_, parser.parser_)}};
6111 }
6112
6113 template<typename ParserTuple>
6114 template<typename Parser>
6115 constexpr auto or_parser<ParserTuple>::append(
6116 parser_interface<Parser> parser) const noexcept
6117 {
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127 BOOST_PARSER_ASSERT(!detail::is_unconditional_eps_v<decltype(
6128 detail::hl::back(parsers_))>);
6129 if constexpr (detail::is_or_p<Parser>{}) {
6130 return parser_interface{or_parser<decltype(
6131 detail::hl::concat(parsers_, parser.parser_.parsers_))>{
6132 detail::hl::concat(parsers_, parser.parser_.parsers_)}};
6133 } else {
6134 return parser_interface{or_parser<decltype(
6135 detail::hl::append(parsers_, parser.parser_))>{
6136 detail::hl::append(parsers_, parser.parser_)}};
6137 }
6138 }
6139
6140 template<typename ParserTuple, typename DelimiterParser>
6141 template<typename Parser>
6142 constexpr auto perm_parser<ParserTuple, DelimiterParser>::prepend(
6143 parser_interface<Parser> parser) const noexcept
6144 {
6145
6146
6147
6148 BOOST_PARSER_ASSERT(!detail::is_eps_p<Parser>{});
6149 return parser_interface{perm_parser<
6150 decltype(detail::hl::prepend(parsers_, parser.parser_)),
6151 detail::nope>{detail::hl::prepend(parsers_, parser.parser_)}};
6152 }
6153
6154 template<typename ParserTuple, typename DelimiterParser>
6155 template<typename Parser>
6156 constexpr auto perm_parser<ParserTuple, DelimiterParser>::append(
6157 parser_interface<Parser> parser) const noexcept
6158 {
6159
6160
6161
6162 BOOST_PARSER_ASSERT(!detail::is_eps_p<Parser>{});
6163 if constexpr (detail::is_perm_p<Parser>{}) {
6164 return parser_interface{perm_parser<
6165 decltype(detail::hl::concat(parsers_, parser.parser_.parsers_)),
6166 detail::nope>{
6167 detail::hl::concat(parsers_, parser.parser_.parsers_)}};
6168 } else {
6169 return parser_interface{perm_parser<
6170 decltype(detail::hl::append(parsers_, parser.parser_)),
6171 detail::nope>{detail::hl::append(parsers_, parser.parser_)}};
6172 }
6173 }
6174
6175 template<
6176 typename ParserTuple,
6177 typename BacktrackingTuple,
6178 typename CombiningGroups>
6179 template<bool AllowBacktracking, typename Parser>
6180 constexpr auto
6181 seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups>::prepend(
6182 parser_interface<Parser> parser) const noexcept
6183 {
6184 using combining_groups =
6185 detail::combining_t<ParserTuple, CombiningGroups>;
6186 using final_combining_groups =
6187 decltype(detail::hl::prepend(combining_groups{}, llong<0>{}));
6188 using backtracking = decltype(detail::hl::prepend(
6189 detail::hl::prepend(
6190 detail::hl::drop_front(BacktrackingTuple{}),
6191 std::bool_constant<AllowBacktracking>{}),
6192 std::true_type{}));
6193 using parser_t = seq_parser<
6194 decltype(detail::hl::prepend(parsers_, parser.parser_)),
6195 backtracking,
6196 final_combining_groups>;
6197 return parser_interface{
6198 parser_t{detail::hl::prepend(parsers_, parser.parser_)}};
6199 }
6200
6201 template<
6202 typename ParserTuple,
6203 typename BacktrackingTuple,
6204 typename CombiningGroups>
6205 template<bool AllowBacktracking, typename Parser>
6206 constexpr auto
6207 seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups>::append(
6208 parser_interface<Parser> parser) const noexcept
6209 {
6210 using combining_groups =
6211 detail::combining_t<ParserTuple, CombiningGroups>;
6212 if constexpr (detail::is_seq_p<Parser>{}) {
6213 using parser_combining_groups = detail::combining_t<
6214 decltype(parser.parser_.parsers_),
6215 typename Parser::combining_groups>;
6216 using final_combining_groups = detail::
6217 combined_combining_t<combining_groups, parser_combining_groups>;
6218 using rhs_backtracking = decltype(detail::hl::prepend(
6219 detail::hl::drop_front(typename Parser::backtracking{}),
6220 std::bool_constant<AllowBacktracking>{}));
6221 using backtracking = decltype(detail::hl::concat(
6222 BacktrackingTuple{}, rhs_backtracking{}));
6223 using parser_t = seq_parser<
6224 decltype(detail::hl::concat(parsers_, parser.parser_.parsers_)),
6225 backtracking,
6226 final_combining_groups>;
6227 return parser_interface{parser_t{
6228 detail::hl::concat(parsers_, parser.parser_.parsers_)}};
6229 } else {
6230 using final_combining_groups =
6231 decltype(detail::hl::append(combining_groups{}, llong<0>{}));
6232 using backtracking = decltype(detail::hl::append(
6233 BacktrackingTuple{}, std::bool_constant<AllowBacktracking>{}));
6234 using parser_t = seq_parser<
6235 decltype(detail::hl::append(parsers_, parser.parser_)),
6236 backtracking,
6237 final_combining_groups>;
6238 return parser_interface{
6239 parser_t{detail::hl::append(parsers_, parser.parser_)}};
6240 }
6241 }
6242
6243 #endif
6244
6245
6246
6247
6248
6249
6250
6251 template<template<class> class Parser>
6252 struct directive
6253 {
6254 template<typename Parser2>
6255 constexpr auto operator[](parser_interface<Parser2> rhs) const noexcept
6256 {
6257 return parser_interface{Parser<Parser2>{rhs.parser_}};
6258 }
6259 };
6260
6261
6262
6263
6264 inline constexpr directive<omit_parser> omit;
6265
6266
6267
6268
6269 inline constexpr directive<raw_parser> raw;
6270
6271 #if defined(BOOST_PARSER_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS
6272
6273
6274
6275 inline constexpr directive<string_view_parser> string_view;
6276 #endif
6277
6278
6279
6280
6281 inline constexpr directive<lexeme_parser> lexeme;
6282
6283
6284
6285
6286 inline constexpr directive<no_case_parser> no_case;
6287
6288
6289
6290 template<typename MinType, typename MaxType>
6291 struct repeat_directive
6292 {
6293 template<typename Parser2>
6294 constexpr auto operator[](parser_interface<Parser2> rhs) const noexcept
6295 {
6296 using repeat_parser_type =
6297 repeat_parser<Parser2, detail::nope, MinType, MaxType>;
6298 return parser_interface{
6299 repeat_parser_type{rhs.parser_, min_, max_}};
6300 }
6301
6302 MinType min_;
6303 MaxType max_;
6304 };
6305
6306
6307
6308
6309 template<typename T>
6310 constexpr repeat_directive<T, T> repeat(T n) noexcept
6311 {
6312 return repeat_directive<T, T>{n, n};
6313 }
6314
6315
6316
6317
6318
6319 template<typename MinType, typename MaxType>
6320 constexpr repeat_directive<MinType, MaxType>
6321 repeat(MinType min_, MaxType max_) noexcept
6322 {
6323 return repeat_directive<MinType, MaxType>{min_, max_};
6324 }
6325
6326
6327
6328
6329
6330 template<typename DelimiterParser>
6331 struct delimiter_directive
6332 {
6333 template<typename ParserTuple, typename DelimiterParser2>
6334 constexpr auto operator[](
6335 parser_interface<perm_parser<ParserTuple, DelimiterParser2>> rhs)
6336 const noexcept
6337 {
6338 using parser_type = perm_parser<ParserTuple, DelimiterParser>;
6339 return parser_interface{
6340 parser_type{rhs.parser_.parsers_, delimiter_parser_}};
6341 }
6342
6343 DelimiterParser delimiter_parser_;
6344 };
6345
6346
6347
6348
6349 template<typename DelimiterParser>
6350 constexpr delimiter_directive<DelimiterParser>
6351 delimiter(parser_interface<DelimiterParser> delimiter_parser) noexcept
6352 {
6353 return delimiter_directive<DelimiterParser>{delimiter_parser.parser_};
6354 }
6355
6356
6357
6358
6359
6360
6361 template<typename SkipParser = detail::nope>
6362 struct skip_directive
6363 {
6364 template<typename Parser>
6365 constexpr auto operator[](parser_interface<Parser> rhs) const noexcept
6366 {
6367 return parser_interface{
6368 skip_parser<Parser, SkipParser>{rhs.parser_, skip_parser_}};
6369 }
6370
6371
6372 template<typename SkipParser2>
6373 constexpr auto
6374 operator()(parser_interface<SkipParser2> skip_parser) const noexcept
6375 {
6376 BOOST_PARSER_ASSERT(
6377 (detail::is_nope_v<SkipParser> &&
6378 "If you're seeing this, you tried to chain calls on skip, "
6379 "like 'skip(foo)(bar)'. Quit it!'"));
6380 return skip_directive<parser_interface<SkipParser2>>{skip_parser};
6381 }
6382
6383 SkipParser skip_parser_;
6384 };
6385
6386
6387
6388
6389 inline constexpr skip_directive<> skip;
6390
6391
6392
6393
6394 struct merge_directive
6395 {
6396 template<
6397 typename ParserTuple,
6398 typename BacktrackingTuple,
6399 typename CombiningGroups>
6400 constexpr auto
6401 operator[](parser_interface<
6402 seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups>>
6403 rhs) const noexcept
6404 {
6405 return parser_interface{
6406 seq_parser<ParserTuple, BacktrackingTuple, detail::merge_t>{
6407 rhs.parser_.parsers_}};
6408 }
6409 };
6410
6411
6412
6413
6414
6415
6416
6417 inline constexpr merge_directive merge;
6418
6419
6420
6421
6422 struct separate_directive
6423 {
6424 template<
6425 typename ParserTuple,
6426 typename BacktrackingTuple,
6427 typename CombiningGroups>
6428 constexpr auto
6429 operator[](parser_interface<
6430 seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups>>
6431 rhs) const noexcept
6432 {
6433 return parser_interface{
6434 seq_parser<ParserTuple, BacktrackingTuple, detail::separate_t>{
6435 rhs.parser_.parsers_}};
6436 }
6437 };
6438
6439
6440
6441
6442
6443
6444
6445 inline constexpr separate_directive separate;
6446
6447
6448
6449
6450 template<typename F>
6451 struct transform_directive
6452 {
6453 template<typename Parser>
6454 constexpr auto operator[](parser_interface<Parser> rhs) const noexcept
6455 {
6456 return parser_interface{
6457 transform_parser<Parser, F>{rhs.parser_, f_}};
6458 }
6459
6460 F f_;
6461 };
6462
6463
6464
6465 template<typename F>
6466 auto transform(F f)
6467 {
6468 return transform_directive<F>{std::move(f)};
6469 }
6470
6471
6472
6473
6474 #ifndef BOOST_PARSER_DOXYGEN
6475
6476 template<typename Predicate>
6477 struct eps_parser
6478 {
6479 template<
6480 typename Iter,
6481 typename Sentinel,
6482 typename Context,
6483 typename SkipParser>
6484 detail::nope call(
6485 Iter & first,
6486 Sentinel last,
6487 Context const & context,
6488 SkipParser const & skip,
6489 detail::flags flags,
6490 bool & success) const noexcept
6491 {
6492 [[maybe_unused]] auto _ = detail::scoped_trace(
6493 *this, first, last, context, flags, detail::global_nope);
6494 BOOST_PARSER_SUBRANGE const where(first, first);
6495 auto const predicate_context = detail::make_action_context(
6496 context, detail::global_nope, where);
6497
6498
6499
6500
6501 success = pred_(predicate_context);
6502 return {};
6503 }
6504
6505 template<
6506 typename Iter,
6507 typename Sentinel,
6508 typename Context,
6509 typename SkipParser,
6510 typename Attribute>
6511 void call(
6512 Iter & first,
6513 Sentinel last,
6514 Context const & context,
6515 SkipParser const & skip,
6516 detail::flags flags,
6517 bool & success,
6518 Attribute & retval) const
6519 {
6520 [[maybe_unused]] auto _ = detail::scoped_trace(
6521 *this, first, last, context, flags, retval);
6522 BOOST_PARSER_SUBRANGE const where(first, first);
6523 auto const predicate_context = detail::make_action_context(
6524 context, detail::global_nope, where);
6525
6526
6527
6528
6529 success = pred_(predicate_context);
6530 }
6531
6532
6533
6534 template<typename Predicate2>
6535 constexpr auto operator()(Predicate2 pred) const noexcept
6536 {
6537 BOOST_PARSER_ASSERT(
6538 (detail::is_nope_v<Predicate> &&
6539 "If you're seeing this, you tried to chain calls on eps, "
6540 "like 'eps(foo)(bar)'. Quit it!'"));
6541 return parser_interface{eps_parser<Predicate2>{std::move(pred)}};
6542 }
6543
6544 Predicate pred_;
6545 };
6546
6547 #endif
6548
6549
6550
6551
6552 inline constexpr parser_interface<eps_parser<detail::nope>> eps;
6553
6554 #ifndef BOOST_PARSER_DOXYGEN
6555
6556 struct eoi_parser
6557 {
6558 template<
6559 typename Iter,
6560 typename Sentinel,
6561 typename Context,
6562 typename SkipParser>
6563 detail::nope call(
6564 Iter & first,
6565 Sentinel last,
6566 Context const & context,
6567 SkipParser const & skip,
6568 detail::flags flags,
6569 bool & success) const
6570 {
6571 [[maybe_unused]] auto _ = detail::scoped_trace(
6572 *this, first, last, context, flags, detail::global_nope);
6573 if (first != last)
6574 success = false;
6575 return {};
6576 }
6577
6578 template<
6579 typename Iter,
6580 typename Sentinel,
6581 typename Context,
6582 typename SkipParser,
6583 typename Attribute>
6584 void call(
6585 Iter & first,
6586 Sentinel last,
6587 Context const & context,
6588 SkipParser const & skip,
6589 detail::flags flags,
6590 bool & success,
6591 Attribute & retval) const
6592 {
6593 [[maybe_unused]] auto _ = detail::scoped_trace(
6594 *this, first, last, context, flags, retval);
6595 if (first != last)
6596 success = false;
6597 }
6598 };
6599
6600 #endif
6601
6602
6603 inline constexpr parser_interface<eoi_parser> eoi;
6604
6605 #ifndef BOOST_PARSER_DOXYGEN
6606
6607 template<typename Attribute>
6608 struct attr_parser
6609 {
6610 template<
6611 typename Iter,
6612 typename Sentinel,
6613 typename Context,
6614 typename SkipParser>
6615 auto call(
6616 Iter & first,
6617 Sentinel last,
6618 Context const & context,
6619 SkipParser const &,
6620 detail::flags flags,
6621 bool &) const
6622 {
6623 [[maybe_unused]] auto _ = detail::scoped_trace(
6624 *this, first, last, context, flags, detail::global_nope);
6625 return detail::resolve(context, attr_);
6626 }
6627
6628 template<
6629 typename Iter,
6630 typename Sentinel,
6631 typename Context,
6632 typename SkipParser,
6633 typename Attribute_>
6634 void call(
6635 Iter & first,
6636 Sentinel last,
6637 Context const & context,
6638 SkipParser const & skip,
6639 detail::flags flags,
6640 bool & success,
6641 Attribute_ & retval) const
6642 {
6643 [[maybe_unused]] auto _ = detail::scoped_trace(
6644 *this, first, last, context, flags, retval);
6645 if (detail::gen_attrs(flags))
6646 detail::assign_copy(retval, detail::resolve(context, attr_));
6647 }
6648
6649 Attribute attr_;
6650 };
6651
6652 #endif
6653
6654
6655
6656 template<typename Attribute>
6657 constexpr auto attr(Attribute a) noexcept
6658 {
6659 return parser_interface{attr_parser<Attribute>{std::move(a)}};
6660 }
6661
6662 #ifndef BOOST_PARSER_DOXYGEN
6663
6664 template<typename Expected, typename AttributeType>
6665 struct char_parser
6666 {
6667 constexpr char_parser() {}
6668 constexpr char_parser(Expected expected) : expected_(expected) {}
6669
6670 template<typename T>
6671 using attribute_type = std::conditional_t<
6672 std::is_same_v<AttributeType, void>,
6673 std::decay_t<T>,
6674 AttributeType>;
6675
6676 template<
6677 typename Iter,
6678 typename Sentinel,
6679 typename Context,
6680 typename SkipParser>
6681 auto call(
6682 Iter & first,
6683 Sentinel last,
6684 Context const & context,
6685 SkipParser const & skip,
6686 detail::flags flags,
6687 bool & success) const -> attribute_type<decltype(*first)>
6688 {
6689 attribute_type<decltype(*first)> retval{};
6690 call(first, last, context, skip, flags, success, retval);
6691 return retval;
6692 }
6693
6694 template<
6695 typename Iter,
6696 typename Sentinel,
6697 typename Context,
6698 typename SkipParser,
6699 typename Attribute>
6700 void call(
6701 Iter & first,
6702 Sentinel last,
6703 Context const & context,
6704 SkipParser const & skip,
6705 detail::flags flags,
6706 bool & success,
6707 Attribute & retval) const
6708 {
6709 [[maybe_unused]] auto _ = detail::scoped_trace(
6710 *this, first, last, context, flags, retval);
6711
6712 if (first == last) {
6713 success = false;
6714 return;
6715 }
6716 attribute_type<decltype(*first)> const x = *first;
6717 if (detail::unequal(context, x, expected_)) {
6718 success = false;
6719 return;
6720 }
6721 detail::assign(retval, x);
6722 ++first;
6723 }
6724
6725
6726
6727
6728
6729 #if BOOST_PARSER_USE_CONCEPTS
6730 template<typename T>
6731 requires(!parsable_range_like<T>)
6732 #else
6733 template<
6734 typename T,
6735 typename Enable =
6736 std::enable_if_t<!detail::is_parsable_range_like_v<T>>>
6737 #endif
6738 constexpr auto operator()(T x) const noexcept
6739 {
6740 BOOST_PARSER_ASSERT(
6741 (detail::is_nope_v<Expected> &&
6742 "If you're seeing this, you tried to chain calls on char_, "
6743 "like 'char_('a')('b')'. Quit it!'"));
6744 return parser_interface{
6745 char_parser<T, AttributeType>{std::move(x)}};
6746 }
6747
6748
6749
6750 template<typename LoType, typename HiType>
6751 constexpr auto operator()(LoType lo, HiType hi) const noexcept
6752 {
6753 BOOST_PARSER_ASSERT(
6754 (detail::is_nope_v<Expected> &&
6755 "If you're seeing this, you tried to chain calls on char_, "
6756 "like 'char_('a', 'b')('c', 'd')'. Quit it!'"));
6757 using char_pair_t = detail::char_pair<LoType, HiType>;
6758 using char_parser_t = char_parser<char_pair_t, AttributeType>;
6759 return parser_interface(
6760 char_parser_t(char_pair_t{std::move(lo), std::move(hi)}));
6761 }
6762
6763
6764
6765
6766
6767
6768
6769 #if BOOST_PARSER_USE_CONCEPTS
6770 template<parsable_range_like R>
6771 #else
6772 template<
6773 typename R,
6774 typename Enable =
6775 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
6776 #endif
6777 constexpr auto operator()(R && r) const noexcept
6778 {
6779 BOOST_PARSER_ASSERT(
6780 ((!std::is_rvalue_reference_v<R &&> ||
6781 !detail::is_range<detail::remove_cv_ref_t<R>>) &&
6782 "It looks like you tried to pass an rvalue range to "
6783 "char_(). Don't do that, or you'll end up with dangling "
6784 "references."));
6785 BOOST_PARSER_ASSERT(
6786 (detail::is_nope_v<Expected> &&
6787 "If you're seeing this, you tried to chain calls on char_, "
6788 "like 'char_(char-set)(char-set)'. Quit it!'"));
6789 auto chars = detail::make_char_range<false>(r);
6790 using char_range_t = decltype(chars);
6791 using char_parser_t = char_parser<char_range_t, AttributeType>;
6792 return parser_interface(char_parser_t(chars));
6793 }
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803 #if BOOST_PARSER_USE_CONCEPTS
6804 template<parsable_range_like R>
6805 requires std::same_as<std::ranges::range_value_t<R>, char32_t>
6806 #else
6807 template<
6808 typename R,
6809 typename Enable = std::enable_if_t<
6810 detail::is_parsable_range_like_v<R> &&
6811 std::is_same_v<detail::range_value_t<R>, char32_t>>>
6812 #endif
6813 constexpr auto operator()(sorted_t, R && r) const noexcept
6814 {
6815 BOOST_PARSER_ASSERT(
6816 ((!std::is_rvalue_reference_v<R &&> ||
6817 !detail::is_range<detail::remove_cv_ref_t<R>>) &&
6818 "It looks like you tried to pass an rvalue range to "
6819 "char_(). Don't do that, or you'll end up with dangling "
6820 "references."));
6821 BOOST_PARSER_ASSERT(
6822 (detail::is_nope_v<Expected> &&
6823 "If you're seeing this, you tried to chain calls on char_, "
6824 "like 'char_(char-set)(char-set)'. Quit it!'"));
6825 auto chars = detail::make_char_range<true>(r);
6826 using char_range_t = decltype(chars);
6827 using char_parser_t = char_parser<char_range_t, AttributeType>;
6828 return parser_interface(char_parser_t(chars));
6829 }
6830
6831 Expected expected_;
6832 };
6833
6834 struct digit_parser
6835 {
6836 constexpr digit_parser() {}
6837
6838 template<typename T>
6839 using attribute_type = std::decay_t<T>;
6840
6841 template<
6842 typename Iter,
6843 typename Sentinel,
6844 typename Context,
6845 typename SkipParser>
6846 auto call(
6847 Iter & first,
6848 Sentinel last,
6849 Context const & context,
6850 SkipParser const & skip,
6851 detail::flags flags,
6852 bool & success) const -> attribute_type<decltype(*first)>
6853 {
6854 attribute_type<decltype(*first)> retval{};
6855 call(first, last, context, skip, flags, success, retval);
6856 return retval;
6857 }
6858
6859 template<
6860 typename Iter,
6861 typename Sentinel,
6862 typename Context,
6863 typename SkipParser,
6864 typename Attribute>
6865 void call(
6866 Iter & first,
6867 Sentinel last,
6868 Context const & context,
6869 SkipParser const & skip,
6870 detail::flags flags,
6871 bool & success,
6872 Attribute & retval) const
6873 {
6874 [[maybe_unused]] auto _ = detail::scoped_trace(
6875 *this, first, last, context, flags, retval);
6876
6877 if (first == last) {
6878 success = false;
6879 return;
6880 }
6881 attribute_type<decltype(*first)> const x = *first;
6882 char32_t const x_cmp = x;
6883 if (x_cmp < U'\x0100' && (x_cmp < U'0' || U'9' < x_cmp)) {
6884 success = false;
6885 return;
6886 }
6887 char32_t const * it = std::upper_bound(
6888 std::begin(zero_cps) + 1, std::end(zero_cps), x_cmp);
6889 if (it == std::begin(zero_cps) || x_cmp < *(it - 1) ||
6890 *(it - 1) + 9 < x_cmp) {
6891 success = false;
6892 return;
6893 }
6894 detail::assign(retval, x);
6895 ++first;
6896 }
6897
6898
6899
6900
6901 static constexpr char32_t zero_cps[] = {
6902 U'\u0030',
6903 U'\u0660',
6904 U'\u06F0',
6905 U'\u07C0',
6906 U'\u0966',
6907 U'\u09E6',
6908 U'\u0A66',
6909 U'\u0AE6',
6910 U'\u0B66',
6911 U'\u0BE6',
6912 U'\u0C66',
6913 U'\u0CE6',
6914 U'\u0D66',
6915 U'\u0DE6',
6916 U'\u0E50',
6917 U'\u0ED0',
6918 U'\u0F20',
6919 U'\u1040',
6920 U'\u1090',
6921 U'\u17E0',
6922 U'\u1810',
6923 U'\u1946',
6924 U'\u19D0',
6925 U'\u1A80',
6926 U'\u1A90',
6927 U'\u1B50',
6928 U'\u1BB0',
6929 U'\u1C40',
6930 U'\u1C50',
6931 U'\uA620',
6932 U'\uA8D0',
6933 U'\uA900',
6934 U'\uA9D0',
6935 U'\uA9F0',
6936 U'\uAA50',
6937 U'\uABF0',
6938 U'\uFF10',
6939 U'\U000104A0',
6940 U'\U00010D30',
6941 U'\U00011066',
6942 U'\U000110F0',
6943 U'\U00011136',
6944 U'\U000111D0',
6945 U'\U000112F0',
6946 U'\U00011450',
6947 U'\U000114D0',
6948 U'\U00011650',
6949 U'\U000116C0',
6950 U'\U00011730',
6951 U'\U000118E0',
6952 U'\U00011950',
6953 U'\U00011C50',
6954 U'\U00011D50',
6955 U'\U00011DA0',
6956 U'\U00011F50',
6957 U'\U00016A60',
6958 U'\U00016AC0',
6959 U'\U00016B50',
6960 U'\U0001D7CE',
6961 U'\U0001D7D8',
6962 U'\U0001D7E2',
6963 U'\U0001D7EC',
6964 U'\U0001D7F6',
6965 U'\U0001E140',
6966 U'\U0001E2F0',
6967 U'\U0001E4F0',
6968 U'\U0001E950',
6969 U'\U0001FBF0'
6970 };
6971 };
6972
6973 template<typename Tag>
6974 struct char_set_parser
6975 {
6976 BOOST_PARSER_ALGO_CONSTEXPR char_set_parser()
6977 {
6978 auto const & chars = detail::char_set<Tag>::chars;
6979 auto const first = std::begin(chars);
6980 auto const last = std::end(chars);
6981 auto it = std::upper_bound(first, last, 0x100, [](auto x, auto y){
6982 using common_t = std::common_type_t<decltype(x), decltype(x)>;
6983 return (common_t)x < (common_t)y;
6984 });
6985 if (it != last)
6986 one_byte_offset_ = int(it - first);
6987 }
6988
6989 template<typename T>
6990 using attribute_type = std::decay_t<T>;
6991
6992 template<
6993 typename Iter,
6994 typename Sentinel,
6995 typename Context,
6996 typename SkipParser>
6997 auto call(
6998 Iter & first,
6999 Sentinel last,
7000 Context const & context,
7001 SkipParser const & skip,
7002 detail::flags flags,
7003 bool & success) const -> attribute_type<decltype(*first)>
7004 {
7005 attribute_type<decltype(*first)> retval{};
7006 call(first, last, context, skip, flags, success, retval);
7007 return retval;
7008 }
7009
7010 template<
7011 typename Iter,
7012 typename Sentinel,
7013 typename Context,
7014 typename SkipParser,
7015 typename Attribute>
7016 void call(
7017 Iter & first,
7018 Sentinel last,
7019 Context const & context,
7020 SkipParser const & skip,
7021 detail::flags flags,
7022 bool & success,
7023 Attribute & retval) const
7024 {
7025 [[maybe_unused]] auto _ = detail::scoped_trace(
7026 *this, first, last, context, flags, retval);
7027
7028 if (first == last) {
7029 success = false;
7030 return;
7031 }
7032
7033 auto const & chars = detail::char_set<Tag>::chars;
7034 attribute_type<decltype(*first)> const x = *first;
7035 uint32_t const x_cmp = x;
7036 if (x_cmp < U'\x0100') {
7037 uint32_t const * it = std::lower_bound(
7038 std::begin(chars),
7039 std::begin(chars) + one_byte_offset_,
7040 x_cmp);
7041 if (it != std::end(chars) && *it == x_cmp) {
7042 detail::assign(retval, x_cmp);
7043 ++first;
7044 } else {
7045 success = false;
7046 }
7047 return;
7048 }
7049
7050 uint32_t const * it = std::lower_bound(
7051 std::begin(chars) + one_byte_offset_, std::end(chars), x_cmp);
7052 if (it != std::end(chars) && *it == x_cmp) {
7053 detail::assign(retval, x_cmp);
7054 ++first;
7055 return;
7056 }
7057
7058 success = false;
7059 }
7060
7061 int one_byte_offset_ = 0;
7062 };
7063
7064 template<typename Tag>
7065 struct char_subrange_parser
7066 {
7067 constexpr char_subrange_parser() {}
7068
7069 template<typename T>
7070 using attribute_type = std::decay_t<T>;
7071
7072 template<
7073 typename Iter,
7074 typename Sentinel,
7075 typename Context,
7076 typename SkipParser>
7077 auto call(
7078 Iter & first,
7079 Sentinel last,
7080 Context const & context,
7081 SkipParser const & skip,
7082 detail::flags flags,
7083 bool & success) const -> attribute_type<decltype(*first)>
7084 {
7085 attribute_type<decltype(*first)> retval{};
7086 call(first, last, context, skip, flags, success, retval);
7087 return retval;
7088 }
7089
7090 template<
7091 typename Iter,
7092 typename Sentinel,
7093 typename Context,
7094 typename SkipParser,
7095 typename Attribute>
7096 void call(
7097 Iter & first,
7098 Sentinel last,
7099 Context const & context,
7100 SkipParser const & skip,
7101 detail::flags flags,
7102 bool & success,
7103 Attribute & retval) const
7104 {
7105 [[maybe_unused]] auto _ = detail::scoped_trace(
7106 *this, first, last, context, flags, retval);
7107
7108 if (first == last) {
7109 success = false;
7110 return;
7111 }
7112 attribute_type<decltype(*first)> const x = *first;
7113 char32_t const x_cmp = x;
7114 success = false;
7115 for (auto subrange : detail::char_subranges<Tag>::ranges) {
7116 if (subrange.lo_ <= x_cmp && x_cmp <= subrange.hi_) {
7117 success = true;
7118 detail::assign(retval, x);
7119 ++first;
7120 return;
7121 }
7122 }
7123 }
7124 };
7125
7126 #endif
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138 inline constexpr parser_interface<char_parser<detail::nope>> char_;
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150 inline constexpr parser_interface<char_parser<detail::nope, char32_t>> cp;
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161 inline constexpr parser_interface<char_parser<detail::nope, char>> cu;
7162
7163
7164 inline constexpr auto lit(char c) noexcept { return omit[char_(c)]; }
7165
7166 #if defined(__cpp_char8_t) || defined(BOOST_PARSER_DOXYGEN)
7167
7168 inline constexpr auto lit(char8_t c) noexcept { return omit[char_(c)]; }
7169 #endif
7170
7171
7172 inline constexpr auto lit(char32_t c) noexcept { return omit[char_(c)]; }
7173
7174 #ifndef BOOST_PARSER_DOXYGEN
7175
7176 template<typename StrIter, typename StrSentinel>
7177 struct string_parser
7178 {
7179 constexpr string_parser() : expected_first_(), expected_last_() {}
7180
7181 #if BOOST_PARSER_USE_CONCEPTS
7182 template<parsable_range_like R>
7183 #else
7184 template<
7185 typename R,
7186 typename Enable =
7187 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
7188 #endif
7189 constexpr string_parser(R && r) :
7190 expected_first_(detail::make_view_begin(r)),
7191 expected_last_(detail::make_view_end(r))
7192 {}
7193
7194 template<
7195 typename Iter,
7196 typename Sentinel,
7197 typename Context,
7198 typename SkipParser>
7199 std::string call(
7200 Iter & first,
7201 Sentinel last,
7202 Context const & context,
7203 SkipParser const & skip,
7204 detail::flags flags,
7205 bool & success) const
7206 {
7207 std::string retval;
7208 call(first, last, context, skip, flags, success, retval);
7209 return retval;
7210 }
7211
7212 template<
7213 typename Iter,
7214 typename Sentinel,
7215 typename Context,
7216 typename SkipParser,
7217 typename Attribute>
7218 void call(
7219 Iter & first,
7220 Sentinel last,
7221 Context const & context,
7222 SkipParser const & skip,
7223 detail::flags flags,
7224 bool & success,
7225 Attribute & retval) const
7226 {
7227 [[maybe_unused]] auto _ = detail::scoped_trace(
7228 *this, first, last, context, flags, retval);
7229
7230 if (first == last) {
7231 success = false;
7232 return;
7233 }
7234
7235 if constexpr (std::is_same_v<
7236 detail::remove_cv_ref_t<decltype(*first)>,
7237 char32_t>) {
7238 auto const cps =
7239 BOOST_PARSER_SUBRANGE(expected_first_, expected_last_) |
7240 detail::text::as_utf32;
7241
7242 auto const mismatch = detail::no_case_aware_string_mismatch(
7243 first,
7244 last,
7245 cps.begin(),
7246 cps.end(),
7247 context.no_case_depth_);
7248 if (mismatch.second != cps.end()) {
7249 success = false;
7250 return;
7251 }
7252
7253 detail::append(
7254 retval, first, mismatch.first, detail::gen_attrs(flags));
7255
7256 first = mismatch.first;
7257 } else {
7258 auto const mismatch = detail::no_case_aware_string_mismatch(
7259 first,
7260 last,
7261 expected_first_,
7262 expected_last_,
7263 context.no_case_depth_);
7264 if (mismatch.second != expected_last_) {
7265 success = false;
7266 return;
7267 }
7268
7269 detail::append(
7270 retval, first, mismatch.first, detail::gen_attrs(flags));
7271
7272 first = mismatch.first;
7273 }
7274 }
7275
7276 StrIter expected_first_;
7277 StrSentinel expected_last_;
7278 };
7279
7280 #if BOOST_PARSER_USE_CONCEPTS
7281 template<parsable_range_like R>
7282 #else
7283 template<typename R>
7284 #endif
7285 string_parser(R r) -> string_parser<
7286 decltype(detail::make_view_begin(r)),
7287 decltype(detail::make_view_end(r))>;
7288
7289 #endif
7290
7291
7292
7293 #if BOOST_PARSER_USE_CONCEPTS
7294 template<parsable_range_like R>
7295 #else
7296 template<typename R>
7297 #endif
7298 constexpr auto string(R && str) noexcept
7299 {
7300 return parser_interface{string_parser(str)};
7301 }
7302
7303 template<typename Quotes, typename Escapes, typename CharParser>
7304 struct quoted_string_parser
7305 {
7306 constexpr quoted_string_parser() : chs_(), ch_('"') {}
7307
7308 #if BOOST_PARSER_USE_CONCEPTS
7309 template<parsable_range_like R>
7310 #else
7311 template<
7312 typename R,
7313 typename Enable =
7314 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
7315 #endif
7316 constexpr quoted_string_parser(
7317 R && r,
7318 parser_interface<CharParser> char_p =
7319 parser_interface{CharParser()}) :
7320 chs_((R &&)r), char_p_(char_p), ch_(0)
7321 {
7322 BOOST_PARSER_DEBUG_ASSERT(r.begin() != r.end());
7323 }
7324
7325 #if BOOST_PARSER_USE_CONCEPTS
7326 template<parsable_range_like R>
7327 #else
7328 template<
7329 typename R,
7330 typename Enable =
7331 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
7332 #endif
7333 constexpr quoted_string_parser(
7334 R && r,
7335 Escapes escapes,
7336 parser_interface<CharParser> char_p =
7337 parser_interface{CharParser()}) :
7338 chs_((R &&)r), escapes_(escapes), char_p_(char_p), ch_(0)
7339 {
7340 BOOST_PARSER_DEBUG_ASSERT(r.begin() != r.end());
7341 }
7342
7343 constexpr quoted_string_parser(
7344 char32_t cp,
7345 parser_interface<CharParser> char_p =
7346 parser_interface{CharParser()}) :
7347 chs_(), char_p_(char_p), ch_(cp)
7348 {}
7349
7350 constexpr quoted_string_parser(
7351 char32_t cp,
7352 Escapes escapes,
7353 parser_interface<CharParser> char_p =
7354 parser_interface{CharParser()}) :
7355 chs_(), escapes_(escapes), char_p_(char_p), ch_(cp)
7356 {}
7357
7358 template<
7359 typename Iter,
7360 typename Sentinel,
7361 typename Context,
7362 typename SkipParser>
7363 std::string call(
7364 Iter & first,
7365 Sentinel last,
7366 Context const & context,
7367 SkipParser const & skip,
7368 detail::flags flags,
7369 bool & success) const
7370 {
7371 std::string retval;
7372 call(first, last, context, skip, flags, success, retval);
7373 return retval;
7374 }
7375
7376 template<
7377 typename Iter,
7378 typename Sentinel,
7379 typename Context,
7380 typename SkipParser,
7381 typename Attribute>
7382 void call(
7383 Iter & first,
7384 Sentinel last,
7385 Context const & context,
7386 SkipParser const & skip,
7387 detail::flags flags,
7388 bool & success,
7389 Attribute & retval) const
7390 {
7391 [[maybe_unused]] auto _ = detail::scoped_trace(
7392 *this, first, last, context, flags, retval);
7393
7394 if (first == last) {
7395 success = false;
7396 return;
7397 }
7398
7399 auto const prev_first = first;
7400
7401 auto append = [&retval,
7402 gen_attrs = detail::gen_attrs(flags)](auto & ctx) {
7403 detail::move_back(retval, _attr(ctx), gen_attrs);
7404 };
7405
7406 auto quote_ch = [&]() {
7407 if constexpr (detail::is_nope_v<Quotes>) {
7408 detail::remove_cv_ref_t<decltype(*first)> curr = *first;
7409 if ((char32_t)curr == ch_)
7410 ++first;
7411 else
7412 success = false;
7413 return ch_;
7414 } else {
7415 detail::remove_cv_ref_t<decltype(*first)> const ch = *first;
7416 bool found = false;
7417 if constexpr (std::
7418 is_same_v<decltype(ch), char32_t const>) {
7419 auto r = chs_ | detail::text::as_utf32;
7420 found = detail::text::find(r.begin(), r.end(), ch) !=
7421 r.end();
7422 } else {
7423 found = detail::text::find(
7424 chs_.begin(), chs_.end(), ch) != chs_.end();
7425 }
7426 if (found)
7427 ++first;
7428 else
7429 success = false;
7430 return ch;
7431 }
7432 };
7433
7434 auto const ch = quote_ch();
7435 if (!success)
7436 return;
7437
7438 decltype(ch) const backslash_and_delim[] = {'\\', ch};
7439 auto const back_delim = char_(backslash_and_delim);
7440
7441 auto make_parser = [&]() {
7442 if constexpr (detail::is_nope_v<Escapes>) {
7443 return *((lit('\\') >> back_delim) |
7444 (char_p_ - back_delim))[append] > ch;
7445 } else {
7446 return *((lit('\\') >> back_delim)[append] |
7447 (lit('\\') >> parser_interface(escapes_))[append] |
7448 (char_p_ - back_delim)[append]) > ch;
7449 }
7450 };
7451
7452 auto const p = make_parser();
7453 p.parser_.call(
7454 first,
7455 last,
7456 context,
7457 skip,
7458 detail::disable_skip(flags),
7459 success);
7460
7461 if (!success) {
7462 retval = Attribute();
7463 first = prev_first;
7464 }
7465 }
7466
7467
7468
7469 #if BOOST_PARSER_USE_CONCEPTS
7470 template<typename T, typename Parser = char_parser<detail::nope>>
7471 requires(!parsable_range_like<T>)
7472 #else
7473 template<
7474 typename T,
7475 typename Parser = char_parser<detail::nope>,
7476 typename Enable =
7477 std::enable_if_t<!detail::is_parsable_range_like_v<T>>>
7478 #endif
7479 constexpr auto
7480 operator()(T x, parser_interface<Parser> char_p = char_) const noexcept
7481 {
7482 if constexpr (!detail::is_nope_v<Quotes>) {
7483 BOOST_PARSER_ASSERT(
7484 (chs_.empty() && ch_ == '"' &&
7485 "If you're seeing this, you tried to chain calls on "
7486 "quoted_string, like 'quoted_string('\"')('\\'')'. Quit "
7487 "it!'"));
7488 }
7489 return parser_interface(
7490 quoted_string_parser<detail::nope, detail::nope, Parser>(
7491 std::move(x), char_p));
7492 }
7493
7494
7495
7496
7497
7498
7499
7500
7501 #if BOOST_PARSER_USE_CONCEPTS
7502 template<
7503 parsable_range_like R,
7504 typename Parser = char_parser<detail::nope>>
7505 #else
7506 template<
7507 typename R,
7508 typename Parser = char_parser<detail::nope>,
7509 typename Enable =
7510 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
7511 #endif
7512 constexpr auto operator()(
7513 R && r, parser_interface<Parser> char_p = char_) const noexcept
7514 {
7515 BOOST_PARSER_ASSERT(((
7516 !std::is_rvalue_reference_v<R &&> ||
7517 !detail::is_range<detail::remove_cv_ref_t<
7518 R>>)&&"It looks like you tried to pass an rvalue range to "
7519 "quoted_string(). Don't do that, or you'll end up "
7520 "with dangling references."));
7521 if constexpr (!detail::is_nope_v<Quotes>) {
7522 BOOST_PARSER_ASSERT(
7523 (chs_.empty() && ch_ == '"' &&
7524 "If you're seeing this, you tried to chain calls on "
7525 "quoted_string, like "
7526 "'quoted_string(char-range)(char-range)'. Quit it!'"));
7527 }
7528 return parser_interface(
7529 quoted_string_parser<
7530 decltype(BOOST_PARSER_SUBRANGE(
7531 detail::make_view_begin(r), detail::make_view_end(r))),
7532 detail::nope,
7533 Parser>(
7534 BOOST_PARSER_SUBRANGE(
7535 detail::make_view_begin(r), detail::make_view_end(r)),
7536 char_p));
7537 }
7538
7539
7540
7541
7542
7543
7544 #if BOOST_PARSER_USE_CONCEPTS
7545 template<
7546 typename T,
7547 typename U,
7548 typename Parser = char_parser<detail::nope>>
7549 requires(!parsable_range_like<T>)
7550 #else
7551 template<
7552 typename T,
7553 typename U,
7554 typename Parser = char_parser<detail::nope>,
7555 typename Enable =
7556 std::enable_if_t<!detail::is_parsable_range_like_v<T>>>
7557 #endif
7558 auto operator()(
7559 T x,
7560 symbols<U> const & escapes,
7561 parser_interface<Parser> char_p = char_) const noexcept
7562 {
7563 if constexpr (!detail::is_nope_v<Quotes>) {
7564 BOOST_PARSER_ASSERT(
7565 (chs_.empty() && ch_ == '"' &&
7566 "If you're seeing this, you tried to chain calls on "
7567 "quoted_string, like 'quoted_string('\"')('\\'')'. Quit "
7568 "it!'"));
7569 }
7570 auto symbols = symbol_parser(escapes.parser_);
7571 auto parser =
7572 quoted_string_parser<detail::nope, decltype(symbols), Parser>(
7573 char32_t(x), symbols, char_p);
7574 return parser_interface(parser);
7575 }
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587 #if BOOST_PARSER_USE_CONCEPTS
7588 template<
7589 parsable_range_like R,
7590 typename T,
7591 typename Parser = char_parser<detail::nope>>
7592 #else
7593 template<
7594 typename R,
7595 typename T,
7596 typename Parser = char_parser<detail::nope>,
7597 typename Enable =
7598 std::enable_if_t<detail::is_parsable_range_like_v<R>>>
7599 #endif
7600 auto operator()(
7601 R && r,
7602 symbols<T> const & escapes,
7603 parser_interface<Parser> char_p = char_) const noexcept
7604 {
7605 BOOST_PARSER_ASSERT(((
7606 !std::is_rvalue_reference_v<R &&> ||
7607 !detail::is_range<detail::remove_cv_ref_t<
7608 R>>)&&"It looks like you tried to pass an rvalue range to "
7609 "quoted_string(). Don't do that, or you'll end up "
7610 "with dangling references."));
7611 if constexpr (!detail::is_nope_v<Quotes>) {
7612 BOOST_PARSER_ASSERT(
7613 (chs_.empty() && ch_ == '"' &&
7614 "If you're seeing this, you tried to chain calls on "
7615 "quoted_string, like "
7616 "'quoted_string(char-range)(char-range)'. Quit it!'"));
7617 }
7618 auto symbols = symbol_parser(escapes.parser_);
7619 auto quotes = BOOST_PARSER_SUBRANGE(
7620 detail::make_view_begin(r), detail::make_view_end(r));
7621 auto parser = quoted_string_parser<
7622 decltype(quotes),
7623 decltype(symbols),
7624 Parser>(quotes, symbols, char_p);
7625 return parser_interface(parser);
7626 }
7627
7628 Quotes chs_;
7629 Escapes escapes_;
7630 parser_interface<CharParser> char_p_;
7631 char32_t ch_;
7632 };
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653 inline constexpr parser_interface<quoted_string_parser<>> quoted_string;
7654
7655
7656 #if BOOST_PARSER_USE_CONCEPTS
7657 template<parsable_range_like R>
7658 #else
7659 template<typename R>
7660 #endif
7661 constexpr auto lit(R && str) noexcept
7662 {
7663 return omit[parser::string(str)];
7664 }
7665
7666 #ifndef BOOST_PARSER_DOXYGEN
7667
7668 template<bool NewlinesOnly, bool NoNewlines>
7669 struct ws_parser
7670 {
7671 constexpr ws_parser() {}
7672
7673 static_assert(!NewlinesOnly || !NoNewlines);
7674
7675 template<
7676 typename Iter,
7677 typename Sentinel,
7678 typename Context,
7679 typename SkipParser>
7680 detail::nope call(
7681 Iter & first,
7682 Sentinel last,
7683 Context const & context,
7684 SkipParser const & skip,
7685 detail::flags flags,
7686 bool & success) const
7687 {
7688 detail::nope nope;
7689 call(first, last, context, skip, flags, success, nope);
7690 return {};
7691 }
7692
7693 template<
7694 typename Iter,
7695 typename Sentinel,
7696 typename Context,
7697 typename SkipParser,
7698 typename Attribute>
7699 void call(
7700 Iter & first,
7701 Sentinel last,
7702 Context const & context,
7703 SkipParser const & skip,
7704 detail::flags flags,
7705 bool & success,
7706 Attribute & retval) const
7707 {
7708 [[maybe_unused]] auto _ = detail::scoped_trace(
7709 *this, first, last, context, flags, retval);
7710
7711 if (first == last) {
7712 success = false;
7713 return;
7714 }
7715 int const x = *first;
7716 if constexpr (NewlinesOnly) {
7717 if (x == 0x000a) {
7718 ++first;
7719 return;
7720 }
7721 if (x == 0x000d) {
7722 ++first;
7723 if (first != last && *first == 0x000a)
7724 ++first;
7725 return;
7726 }
7727 if (0x000b == x || x == 0x000c || x == 0x0085 || x == 0x2028 ||
7728 x == 0x2029) {
7729 ++first;
7730 return;
7731 }
7732 success = false;
7733 } else if constexpr (NoNewlines) {
7734 if (x == 0x0020) {
7735 ++first;
7736 return;
7737 }
7738 if (x == 0x0009) {
7739 ++first;
7740 return;
7741 }
7742 if (x == 0x00a0 || x == 0x1680 ||
7743 (0x2000 <= x && x <= 0x200a) || x == 0x202F ||
7744 x == 0x205F || x == 0x3000) {
7745 ++first;
7746 return;
7747 }
7748 success = false;
7749 } else {
7750 if (x == 0x0020 || x == 0x000a) {
7751 ++first;
7752 return;
7753 }
7754 if (x == 0x000d) {
7755 ++first;
7756 if (first != last && *first == 0x000a)
7757 ++first;
7758 return;
7759 }
7760 if (0x0009 <= x && x <= 0x000c) {
7761 ++first;
7762 return;
7763 }
7764 if (x == 0x0085 || x == 0x00a0 || x == 0x1680 ||
7765 (0x2000 <= x && x <= 0x200a) || x == 0x2028 ||
7766 x == 0x2029 || x == 0x202F || x == 0x205F || x == 0x3000) {
7767 ++first;
7768 return;
7769 }
7770 success = false;
7771 }
7772 }
7773 };
7774
7775 #endif
7776
7777
7778
7779
7780 inline constexpr parser_interface<ws_parser<true, false>> eol;
7781
7782
7783
7784
7785
7786 inline constexpr parser_interface<ws_parser<false, false>> ws;
7787
7788
7789
7790
7791
7792 inline constexpr parser_interface<ws_parser<false, true>> blank;
7793
7794
7795
7796
7797
7798 inline constexpr parser_interface<digit_parser> digit;
7799
7800
7801
7802
7803 inline constexpr parser_interface<
7804 char_subrange_parser<detail::hex_digit_subranges>>
7805 hex_digit;
7806
7807
7808
7809 inline constexpr parser_interface<
7810 char_subrange_parser<detail::control_subranges>>
7811 control;
7812
7813
7814
7815
7816 inline BOOST_PARSER_ALGO_CONSTEXPR
7817 parser_interface<char_set_parser<detail::punct_chars>>
7818 punct;
7819
7820
7821
7822 inline BOOST_PARSER_ALGO_CONSTEXPR
7823 parser_interface<char_set_parser<detail::symb_chars>>
7824 symb;
7825
7826
7827
7828 inline BOOST_PARSER_ALGO_CONSTEXPR
7829 parser_interface<char_set_parser<detail::lower_case_chars>>
7830 lower;
7831
7832
7833
7834 inline BOOST_PARSER_ALGO_CONSTEXPR
7835 parser_interface<char_set_parser<detail::upper_case_chars>>
7836 upper;
7837
7838 #ifndef BOOST_PARSER_DOXYGEN
7839
7840 struct bool_parser
7841 {
7842 template<
7843 typename Iter,
7844 typename Sentinel,
7845 typename Context,
7846 typename SkipParser>
7847 bool call(
7848 Iter & first,
7849 Sentinel last,
7850 Context const & context,
7851 SkipParser const & skip,
7852 detail::flags flags,
7853 bool & success) const
7854 {
7855 bool retval{};
7856 call(first, last, context, skip, flags, success, retval);
7857 return retval;
7858 }
7859
7860 template<
7861 typename Iter,
7862 typename Sentinel,
7863 typename Context,
7864 typename SkipParser,
7865 typename Attribute>
7866 void call(
7867 Iter & first,
7868 Sentinel last,
7869 Context const & context,
7870 SkipParser const & skip,
7871 detail::flags flags,
7872 bool & success,
7873 Attribute & retval) const
7874 {
7875 [[maybe_unused]] auto _ = detail::scoped_trace(
7876 *this, first, last, context, flags, retval);
7877
7878 auto compare =
7879 [no_case = context.no_case_depth_](char32_t a, char32_t b) {
7880 if (no_case && 0x41 <= b && b < 0x5b)
7881 b += 0x20;
7882 return a == b;
7883 };
7884
7885
7886
7887 char const t[] = "true";
7888 if (detail::mismatch(t, t + 4, first, last, compare).first ==
7889 t + 4) {
7890 std::advance(first, 4);
7891 detail::assign(retval, true);
7892 return;
7893 }
7894 char const f[] = "false";
7895 if (detail::mismatch(f, f + 5, first, last, compare).first ==
7896 f + 5) {
7897 std::advance(first, 5);
7898 detail::assign(retval, false);
7899 return;
7900 }
7901 success = false;
7902 }
7903 };
7904
7905 #endif
7906
7907
7908
7909 inline constexpr parser_interface<bool_parser> bool_;
7910
7911 #ifndef BOOST_PARSER_DOXYGEN
7912
7913 template<
7914 typename T,
7915 int Radix,
7916 int MinDigits,
7917 int MaxDigits,
7918 typename Expected>
7919 struct uint_parser
7920 {
7921 static_assert(2 <= Radix && Radix <= 36, "Unsupported radix.");
7922
7923 constexpr uint_parser() {}
7924 explicit constexpr uint_parser(Expected expected) : expected_(expected)
7925 {}
7926
7927 template<
7928 typename Iter,
7929 typename Sentinel,
7930 typename Context,
7931 typename SkipParser>
7932 T call(
7933 Iter & first,
7934 Sentinel last,
7935 Context const & context,
7936 SkipParser const & skip,
7937 detail::flags flags,
7938 bool & success) const
7939 {
7940 T retval{};
7941 call(first, last, context, skip, flags, success, retval);
7942 return retval;
7943 }
7944
7945 template<
7946 typename Iter,
7947 typename Sentinel,
7948 typename Context,
7949 typename SkipParser,
7950 typename Attribute>
7951 void call(
7952 Iter & first,
7953 Sentinel last,
7954 Context const & context,
7955 SkipParser const & skip,
7956 detail::flags flags,
7957 bool & success,
7958 Attribute & retval) const
7959 {
7960 [[maybe_unused]] auto _ = detail::scoped_trace(
7961 *this, first, last, context, flags, retval);
7962 T attr = 0;
7963 auto const initial = first;
7964 success =
7965 detail::numeric::parse_int<false, Radix, MinDigits, MaxDigits>(
7966 first, last, attr);
7967 if (first == initial || attr != detail::resolve(context, expected_))
7968 success = false;
7969 if (success)
7970 detail::assign(retval, attr);
7971 }
7972
7973
7974
7975 template<typename Expected2>
7976 constexpr auto operator()(Expected2 expected) const noexcept
7977 {
7978 BOOST_PARSER_ASSERT(
7979 (detail::is_nope_v<Expected> &&
7980 "If you're seeing this, you tried to chain calls on this "
7981 "parser, like 'uint_(2)(3)'. Quit it!'"));
7982 using parser_t =
7983 uint_parser<T, Radix, MinDigits, MaxDigits, Expected2>;
7984 return parser_interface{parser_t{expected}};
7985 }
7986
7987 Expected expected_;
7988 };
7989
7990 #endif
7991
7992
7993
7994 inline constexpr parser_interface<uint_parser<unsigned int, 2>> bin;
7995
7996
7997
7998 inline constexpr parser_interface<uint_parser<unsigned int, 8>> oct;
7999
8000
8001
8002 inline constexpr parser_interface<uint_parser<unsigned int, 16>> hex;
8003
8004
8005
8006 inline constexpr parser_interface<uint_parser<unsigned short>> ushort_;
8007
8008
8009
8010 inline constexpr parser_interface<uint_parser<unsigned int>> uint_;
8011
8012
8013
8014 inline constexpr parser_interface<uint_parser<unsigned long>> ulong_;
8015
8016
8017
8018 inline constexpr parser_interface<uint_parser<unsigned long long>>
8019 ulong_long;
8020
8021 #ifndef BOOST_PARSER_DOXYGEN
8022
8023 template<
8024 typename T,
8025 int Radix,
8026 int MinDigits,
8027 int MaxDigits,
8028 typename Expected>
8029 struct int_parser
8030 {
8031 static_assert(
8032 Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
8033 "Unsupported radix.");
8034
8035 constexpr int_parser() {}
8036 explicit constexpr int_parser(Expected expected) : expected_(expected)
8037 {}
8038
8039 template<
8040 typename Iter,
8041 typename Sentinel,
8042 typename Context,
8043 typename SkipParser>
8044 T call(
8045 Iter & first,
8046 Sentinel last,
8047 Context const & context,
8048 SkipParser const & skip,
8049 detail::flags flags,
8050 bool & success) const
8051 {
8052 T retval{};
8053 call(first, last, context, skip, flags, success, retval);
8054 return retval;
8055 }
8056
8057 template<
8058 typename Iter,
8059 typename Sentinel,
8060 typename Context,
8061 typename SkipParser,
8062 typename Attribute>
8063 void call(
8064 Iter & first,
8065 Sentinel last,
8066 Context const & context,
8067 SkipParser const & skip,
8068 detail::flags flags,
8069 bool & success,
8070 Attribute & retval) const
8071 {
8072 [[maybe_unused]] auto _ = detail::scoped_trace(
8073 *this, first, last, context, flags, retval);
8074 T attr = 0;
8075 auto const initial = first;
8076 success =
8077 detail::numeric::parse_int<true, Radix, MinDigits, MaxDigits>(
8078 first, last, attr);
8079 if (first == initial || attr != detail::resolve(context, expected_))
8080 success = false;
8081 if (success)
8082 detail::assign(retval, attr);
8083 }
8084
8085
8086
8087 template<typename Expected2>
8088 constexpr auto operator()(Expected2 expected) const noexcept
8089 {
8090 BOOST_PARSER_ASSERT(
8091 (detail::is_nope_v<Expected> &&
8092 "If you're seeing this, you tried to chain calls on this "
8093 "parser, like 'int_(2)(3)'. Quit it!'"));
8094 using parser_t =
8095 int_parser<T, Radix, MinDigits, MaxDigits, Expected2>;
8096 return parser_interface{parser_t{expected}};
8097 }
8098
8099 Expected expected_;
8100 };
8101
8102 #endif
8103
8104
8105
8106 inline constexpr parser_interface<int_parser<short>> short_;
8107
8108
8109
8110 inline constexpr parser_interface<int_parser<int>> int_;
8111
8112
8113
8114 inline constexpr parser_interface<int_parser<long>> long_;
8115
8116
8117
8118 inline constexpr parser_interface<int_parser<long long>> long_long;
8119
8120 #ifndef BOOST_PARSER_DOXYGEN
8121
8122 template<typename T>
8123 struct float_parser
8124 {
8125 constexpr float_parser() {}
8126
8127 template<
8128 typename Iter,
8129 typename Sentinel,
8130 typename Context,
8131 typename SkipParser>
8132 T call(
8133 Iter & first,
8134 Sentinel last,
8135 Context const & context,
8136 SkipParser const & skip,
8137 detail::flags flags,
8138 bool & success) const
8139 {
8140 T retval = 0;
8141 call(first, last, context, skip, flags, success, retval);
8142 return retval;
8143 }
8144
8145 template<
8146 typename Iter,
8147 typename Sentinel,
8148 typename Context,
8149 typename SkipParser,
8150 typename Attribute>
8151 void call(
8152 Iter & first,
8153 Sentinel last,
8154 Context const & context,
8155 SkipParser const & skip,
8156 detail::flags flags,
8157 bool & success,
8158 Attribute & retval) const
8159 {
8160 [[maybe_unused]] auto _ = detail::scoped_trace(
8161 *this, first, last, context, flags, retval);
8162 T attr = 0;
8163 auto const initial = first;
8164 success = detail::numeric::parse_real(first, last, attr);
8165 if (first == initial)
8166 success = false;
8167 if (success)
8168 detail::assign(retval, attr);
8169 }
8170 };
8171
8172 #endif
8173
8174
8175 inline constexpr parser_interface<float_parser<float>> float_;
8176
8177
8178 inline constexpr parser_interface<float_parser<double>> double_;
8179
8180
8181
8182
8183
8184 template<typename Predicate>
8185 struct if_directive
8186 {
8187 template<typename Parser2>
8188 constexpr auto operator[](parser_interface<Parser2> rhs) const noexcept
8189 {
8190 return eps(pred_) >> rhs;
8191 }
8192
8193 Predicate pred_;
8194 };
8195
8196
8197
8198
8199 template<typename Predicate>
8200 constexpr auto if_(Predicate pred) noexcept
8201 {
8202 return if_directive<Predicate>{pred};
8203 }
8204
8205 namespace detail {
8206 template<typename SwitchValue, typename Value>
8207 struct switch_parser_equal
8208 {
8209 template<typename Context>
8210 bool operator()(Context & context) const
8211 {
8212 auto const switch_value =
8213 detail::resolve(context, switch_value_);
8214 auto const value = detail::resolve(context, value_);
8215 return value == switch_value;
8216 }
8217 SwitchValue switch_value_;
8218 Value value_;
8219 };
8220 }
8221
8222 #ifndef BOOST_PARSER_DOXYGEN
8223
8224 template<typename SwitchValue, typename OrParser>
8225 struct switch_parser
8226 {
8227 switch_parser() {}
8228 switch_parser(SwitchValue switch_value) : switch_value_(switch_value) {}
8229 switch_parser(SwitchValue switch_value, OrParser or_parser) :
8230 switch_value_(switch_value), or_parser_(or_parser)
8231 {}
8232
8233 template<
8234 typename Iter,
8235 typename Sentinel,
8236 typename Context,
8237 typename SkipParser>
8238 auto call(
8239 Iter & first,
8240 Sentinel last,
8241 Context const & context,
8242 SkipParser const & skip,
8243 detail::flags flags,
8244 bool & success) const
8245 {
8246 BOOST_PARSER_ASSERT(
8247 (!detail::is_nope_v<OrParser> &&
8248 "It looks like you tried to write switch_(val). You need at "
8249 "least one alternative, like: switch_(val)(value_1, "
8250 "parser_1)(value_2, parser_2)..."));
8251 using attr_t = decltype(or_parser_.call(
8252 first, last, context, skip, flags, success));
8253 attr_t attr{};
8254 [[maybe_unused]] auto _ =
8255 detail::scoped_trace(*this, first, last, context, flags, attr);
8256 attr = or_parser_.call(first, last, context, skip, flags, success);
8257 return attr;
8258 }
8259
8260 template<
8261 typename Iter,
8262 typename Sentinel,
8263 typename Context,
8264 typename SkipParser,
8265 typename Attribute>
8266 void call(
8267 Iter & first,
8268 Sentinel last,
8269 Context const & context,
8270 SkipParser const & skip,
8271 detail::flags flags,
8272 bool & success,
8273 Attribute & retval) const
8274 {
8275 BOOST_PARSER_ASSERT(
8276 (!detail::is_nope_v<OrParser> &&
8277 "It looks like you tried to write switch_(val). You need at "
8278 "least one alternative, like: switch_(val)(value_1, "
8279 "parser_1)(value_2, parser_2)..."));
8280 [[maybe_unused]] auto _ = detail::scoped_trace(
8281 *this, first, last, context, flags, retval);
8282 or_parser_.call(first, last, context, skip, flags, success, retval);
8283 }
8284
8285
8286
8287 template<typename Value, typename Parser2>
8288 constexpr auto
8289 operator()(Value value_, parser_interface<Parser2> rhs) const noexcept
8290 {
8291 auto const match = detail::switch_parser_equal<SwitchValue, Value>{
8292 switch_value_, value_};
8293 auto or_parser = make_or_parser(or_parser_, eps(match) >> rhs);
8294 using switch_parser_type =
8295 switch_parser<SwitchValue, decltype(or_parser)>;
8296 return parser_interface{
8297 switch_parser_type{switch_value_, or_parser}};
8298 }
8299
8300 #ifndef BOOST_PARSER_DOXYGEN
8301
8302 template<typename Parser1, typename Parser2>
8303 static constexpr auto
8304 make_or_parser(Parser1 parser1, parser_interface<Parser2> parser2)
8305 {
8306 return (parser_interface{parser1} | parser2).parser_;
8307 }
8308
8309 template<typename Parser>
8310 static constexpr auto
8311 make_or_parser(detail::nope, parser_interface<Parser> parser)
8312 {
8313 return parser.parser_;
8314 }
8315
8316 #endif
8317
8318 SwitchValue switch_value_;
8319 OrParser or_parser_;
8320 };
8321
8322 #endif
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332 template<typename T>
8333 constexpr auto switch_(T x) noexcept
8334 {
8335 return switch_parser<T>{x};
8336 }
8337
8338
8339 #ifndef BOOST_PARSER_DOXYGEN
8340
8341 template<typename Parser, typename GlobalState, typename ErrorHandler>
8342 constexpr auto
8343 parser_interface<Parser, GlobalState, ErrorHandler>::operator>>(
8344 char rhs) const noexcept
8345 {
8346 return *this >> parser::lit(rhs);
8347 }
8348
8349 template<typename Parser, typename GlobalState, typename ErrorHandler>
8350 constexpr auto
8351 parser_interface<Parser, GlobalState, ErrorHandler>::operator>>(
8352 char32_t rhs) const noexcept
8353 {
8354 return *this >> parser::lit(rhs);
8355 }
8356
8357 template<typename Parser, typename GlobalState, typename ErrorHandler>
8358 #if BOOST_PARSER_USE_CONCEPTS
8359 template<parsable_range_like R>
8360 #else
8361 template<typename R, typename>
8362 #endif
8363 constexpr auto
8364 parser_interface<Parser, GlobalState, ErrorHandler>::operator>>(
8365 R && r) const noexcept
8366 {
8367 return *this >> parser::lit(r);
8368 }
8369
8370 #endif
8371
8372
8373 template<typename Parser>
8374 constexpr auto operator>>(char c, parser_interface<Parser> rhs) noexcept
8375 {
8376 if constexpr (detail::is_seq_p<Parser>{}) {
8377 return rhs.parser_.template prepend<true>(parser::lit(c));
8378 } else {
8379 return parser::lit(c) >> rhs;
8380 }
8381 }
8382
8383
8384 template<typename Parser>
8385 constexpr auto operator>>(char32_t c, parser_interface<Parser> rhs) noexcept
8386 {
8387 if constexpr (detail::is_seq_p<Parser>{}) {
8388 return rhs.parser_.template prepend<true>(parser::lit(c));
8389 } else {
8390 return parser::lit(c) >> rhs;
8391 }
8392 }
8393
8394
8395 #if BOOST_PARSER_USE_CONCEPTS
8396 template<parsable_range_like R, typename Parser>
8397 #else
8398 template<
8399 typename R,
8400 typename Parser,
8401 typename Enable = std::enable_if_t<detail::is_parsable_range_like_v<R>>>
8402 #endif
8403 constexpr auto operator>>(R && r, parser_interface<Parser> rhs) noexcept
8404 {
8405 if constexpr (detail::is_seq_p<Parser>{}) {
8406 return rhs.parser_.template prepend<true>(parser::lit(r));
8407 } else {
8408 return parser::lit(r) >> rhs;
8409 }
8410 }
8411
8412 #ifndef BOOST_PARSER_DOXYGEN
8413
8414 template<typename Parser, typename GlobalState, typename ErrorHandler>
8415 constexpr auto
8416 parser_interface<Parser, GlobalState, ErrorHandler>::operator>(
8417 char rhs) const noexcept
8418 {
8419 return *this > parser::lit(rhs);
8420 }
8421
8422 template<typename Parser, typename GlobalState, typename ErrorHandler>
8423 constexpr auto
8424 parser_interface<Parser, GlobalState, ErrorHandler>::operator>(
8425 char32_t rhs) const noexcept
8426 {
8427 return *this > parser::lit(rhs);
8428 }
8429
8430 template<typename Parser, typename GlobalState, typename ErrorHandler>
8431 #if BOOST_PARSER_USE_CONCEPTS
8432 template<parsable_range_like R>
8433 #else
8434 template<typename R, typename>
8435 #endif
8436 constexpr auto
8437 parser_interface<Parser, GlobalState, ErrorHandler>::operator>(
8438 R && r) const noexcept
8439 {
8440 return *this > parser::lit(r);
8441 }
8442
8443 #endif
8444
8445
8446 template<typename Parser>
8447 constexpr auto operator>(char c, parser_interface<Parser> rhs) noexcept
8448 {
8449 if constexpr (detail::is_seq_p<Parser>{}) {
8450 return rhs.parser_.template prepend<false>(parser::lit(c));
8451 } else {
8452 return parser::lit(c) > rhs;
8453 }
8454 }
8455
8456
8457 template<typename Parser>
8458 constexpr auto operator>(char32_t c, parser_interface<Parser> rhs) noexcept
8459 {
8460 if constexpr (detail::is_seq_p<Parser>{}) {
8461 return rhs.parser_.template prepend<false>(parser::lit(c));
8462 } else {
8463 return parser::lit(c) > rhs;
8464 }
8465 }
8466
8467
8468 #if BOOST_PARSER_USE_CONCEPTS
8469 template<parsable_range_like R, typename Parser>
8470 #else
8471 template<
8472 typename R,
8473 typename Parser,
8474 typename Enable = std::enable_if_t<detail::is_parsable_range_like_v<R>>>
8475 #endif
8476 constexpr auto operator>(R && r, parser_interface<Parser> rhs) noexcept
8477 {
8478 if constexpr (detail::is_seq_p<Parser>{}) {
8479 return rhs.parser_.template prepend<false>(parser::lit(r));
8480 } else {
8481 return parser::lit(r) > rhs;
8482 }
8483 }
8484
8485 #ifndef BOOST_PARSER_DOXYGEN
8486
8487 template<typename Parser, typename GlobalState, typename ErrorHandler>
8488 constexpr auto
8489 parser_interface<Parser, GlobalState, ErrorHandler>::operator|(
8490 char rhs) const noexcept
8491 {
8492 return *this | parser::lit(rhs);
8493 }
8494
8495 template<typename Parser, typename GlobalState, typename ErrorHandler>
8496 constexpr auto
8497 parser_interface<Parser, GlobalState, ErrorHandler>::operator|(
8498 char32_t rhs) const noexcept
8499 {
8500 return *this | parser::lit(rhs);
8501 }
8502
8503 template<typename Parser, typename GlobalState, typename ErrorHandler>
8504 #if BOOST_PARSER_USE_CONCEPTS
8505 template<parsable_range_like R>
8506 #else
8507 template<typename R, typename>
8508 #endif
8509 constexpr auto
8510 parser_interface<Parser, GlobalState, ErrorHandler>::operator|(
8511 R && r) const noexcept
8512 {
8513 return *this | parser::lit(r);
8514 }
8515
8516 #endif
8517
8518
8519 template<typename Parser>
8520 constexpr auto operator|(char c, parser_interface<Parser> rhs) noexcept
8521 {
8522 if constexpr (detail::is_or_p<Parser>{}) {
8523 return rhs.parser_.prepend(parser::lit(c));
8524 } else {
8525 return parser::lit(c) | rhs;
8526 }
8527 }
8528
8529
8530 template<typename Parser>
8531 constexpr auto operator|(char32_t c, parser_interface<Parser> rhs) noexcept
8532 {
8533 if constexpr (detail::is_or_p<Parser>{}) {
8534 return rhs.parser_.prepend(parser::lit(c));
8535 } else {
8536 return parser::lit(c) | rhs;
8537 }
8538 }
8539
8540
8541 #if BOOST_PARSER_USE_CONCEPTS
8542 template<parsable_range_like R, typename Parser>
8543 #else
8544 template<
8545 typename R,
8546 typename Parser,
8547 typename Enable = std::enable_if_t<detail::is_parsable_range_like_v<R>>>
8548 #endif
8549 constexpr auto operator|(R && r, parser_interface<Parser> rhs) noexcept
8550 {
8551 if constexpr (detail::is_or_p<Parser>{}) {
8552 return rhs.parser_.prepend(parser::lit(r));
8553 } else {
8554 return parser::lit(r) | rhs;
8555 }
8556 }
8557
8558 #ifndef BOOST_PARSER_DOXYGEN
8559
8560 template<typename Parser, typename GlobalState, typename ErrorHandler>
8561 constexpr auto
8562 parser_interface<Parser, GlobalState, ErrorHandler>::operator-(
8563 char rhs) const noexcept
8564 {
8565 return !parser::lit(rhs) >> *this;
8566 }
8567
8568 template<typename Parser, typename GlobalState, typename ErrorHandler>
8569 constexpr auto
8570 parser_interface<Parser, GlobalState, ErrorHandler>::operator-(
8571 char32_t rhs) const noexcept
8572 {
8573 return !parser::lit(rhs) >> *this;
8574 }
8575
8576 template<typename Parser, typename GlobalState, typename ErrorHandler>
8577 #if BOOST_PARSER_USE_CONCEPTS
8578 template<parsable_range_like R>
8579 #else
8580 template<typename R, typename>
8581 #endif
8582 constexpr auto
8583 parser_interface<Parser, GlobalState, ErrorHandler>::operator-(
8584 R && r) const noexcept
8585 {
8586 return !parser::lit(r) >> *this;
8587 }
8588
8589 #endif
8590
8591
8592 template<typename Parser>
8593 constexpr auto operator-(char c, parser_interface<Parser> rhs) noexcept
8594 {
8595 return !rhs >> parser::lit(c);
8596 }
8597
8598
8599 template<typename Parser>
8600 constexpr auto operator-(char32_t c, parser_interface<Parser> rhs) noexcept
8601 {
8602 return !rhs >> parser::lit(c);
8603 }
8604
8605
8606 #if BOOST_PARSER_USE_CONCEPTS
8607 template<parsable_range_like R, typename Parser>
8608 #else
8609 template<
8610 typename R,
8611 typename Parser,
8612 typename Enable = std::enable_if_t<detail::is_parsable_range_like_v<R>>>
8613 #endif
8614 constexpr auto operator-(R && r, parser_interface<Parser> rhs) noexcept
8615 {
8616 return !rhs >> parser::lit(r);
8617 }
8618
8619 #ifndef BOOST_PARSER_DOXYGEN
8620
8621 template<typename Parser, typename GlobalState, typename ErrorHandler>
8622 constexpr auto
8623 parser_interface<Parser, GlobalState, ErrorHandler>::operator%(
8624 char rhs) const noexcept
8625 {
8626 return *this % parser::lit(rhs);
8627 }
8628
8629 template<typename Parser, typename GlobalState, typename ErrorHandler>
8630 constexpr auto
8631 parser_interface<Parser, GlobalState, ErrorHandler>::operator%(
8632 char32_t rhs) const noexcept
8633 {
8634 return *this % parser::lit(rhs);
8635 }
8636
8637 template<typename Parser, typename GlobalState, typename ErrorHandler>
8638 #if BOOST_PARSER_USE_CONCEPTS
8639 template<parsable_range_like R>
8640 #else
8641 template<typename R, typename>
8642 #endif
8643 constexpr auto
8644 parser_interface<Parser, GlobalState, ErrorHandler>::operator%(
8645 R && r) const noexcept
8646 {
8647 return *this % parser::lit(r);
8648 }
8649
8650 #endif
8651
8652
8653 template<typename Parser>
8654 constexpr auto operator%(char c, parser_interface<Parser> rhs) noexcept
8655 {
8656 return parser::lit(c) % rhs;
8657 }
8658
8659
8660 template<typename Parser>
8661 constexpr auto operator%(char32_t c, parser_interface<Parser> rhs) noexcept
8662 {
8663 return parser::lit(c) % rhs;
8664 }
8665
8666
8667 #if BOOST_PARSER_USE_CONCEPTS
8668 template<parsable_range_like R, typename Parser>
8669 #else
8670 template<
8671 typename R,
8672 typename Parser,
8673 typename Enable = std::enable_if_t<detail::is_parsable_range_like_v<R>>>
8674 #endif
8675 constexpr auto operator%(R && r, parser_interface<Parser> rhs) noexcept
8676 {
8677 return parser::lit(r) % rhs;
8678 }
8679
8680 }}
8681
8682 #include <boost/parser/detail/printing_impl.hpp>
8683
8684 namespace boost { namespace parser {
8685
8686
8687
8688 enum class trace { off, on };
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699 #if BOOST_PARSER_USE_CONCEPTS
8700 template<
8701 parsable_iter I,
8702 std::sentinel_for<I> S,
8703 typename Parser,
8704 typename GlobalState,
8705 error_handler<I, S, GlobalState> ErrorHandler,
8706 typename Attr>
8707 #else
8708 template<
8709 typename I,
8710 typename S,
8711 typename Parser,
8712 typename GlobalState,
8713 typename ErrorHandler,
8714 typename Attr,
8715 typename Enable = std::enable_if_t<
8716 detail::is_parsable_iter_v<I> &&
8717 detail::is_equality_comparable_with_v<I, S> &&
8718 !detail::derived_from_parser_interface_v<
8719 detail::remove_cv_ref_t<Attr>>>>
8720 #endif
8721 bool prefix_parse(
8722 I & first,
8723 S last,
8724 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
8725 Attr & attr,
8726 trace trace_mode = trace::off)
8727 #if BOOST_PARSER_USE_CONCEPTS
8728 requires(
8729 !detail::derived_from_parser_interface_v<std::remove_cvref_t<Attr>>)
8730 #endif
8731 {
8732 detail::attr_reset reset(attr);
8733 if constexpr (!detail::is_char8_iter_v<I>) {
8734 static_assert(
8735 decltype(detail::has_attribute(first, last, parser)){},
8736 "If you're seeing this error, you're trying to get parse() to "
8737 "fill in attr above, using the attribute generated by parser. "
8738 "However, parser does not generate an attribute.");
8739 if (trace_mode == trace::on) {
8740 return reset = detail::parse_impl<true>(
8741 first, last, parser, parser.error_handler_, attr);
8742 } else {
8743 return reset = detail::parse_impl<false>(
8744 first, last, parser, parser.error_handler_, attr);
8745 }
8746 } else {
8747 auto r =
8748 BOOST_PARSER_SUBRANGE(first, last) | detail::text::as_utf32;
8749 auto f = r.begin();
8750 auto const l = r.end();
8751 auto _ = detail::scoped_base_assign(first, f);
8752 static_assert(
8753 decltype(detail::has_attribute(f, l, parser)){},
8754 "If you're seeing this error, you're trying to get parse() to "
8755 "fill in attr above, using the attribute generated by parser. "
8756 "However, parser does not generate an attribute.");
8757 if (trace_mode == trace::on) {
8758 return reset = detail::parse_impl<true>(
8759 f, l, parser, parser.error_handler_, attr);
8760 } else {
8761 return reset = detail::parse_impl<false>(
8762 f, l, parser, parser.error_handler_, attr);
8763 }
8764 }
8765 }
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781 #if BOOST_PARSER_USE_CONCEPTS
8782 template<
8783 parsable_range R,
8784 typename Parser,
8785 typename GlobalState,
8786 typename ErrorHandler,
8787 typename Attr>
8788 #else
8789 template<
8790 typename R,
8791 typename Parser,
8792 typename GlobalState,
8793 typename ErrorHandler,
8794 typename Attr,
8795 typename Enable = std::enable_if_t<
8796 detail::is_parsable_range_v<R> &&
8797 !detail::derived_from_parser_interface_v<
8798 detail::remove_cv_ref_t<Attr>>>>
8799 #endif
8800 bool parse(
8801 R const & r,
8802 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
8803 Attr & attr,
8804 trace trace_mode = trace::off)
8805 #if BOOST_PARSER_USE_CONCEPTS
8806
8807 requires error_handler<
8808 ErrorHandler,
8809 std::ranges::iterator_t<decltype(detail::make_input_subrange(r))>,
8810 std::ranges::sentinel_t<decltype(detail::make_input_subrange(r))>,
8811 GlobalState> &&
8812 (!detail::derived_from_parser_interface_v<std::remove_cvref_t<Attr>>)
8813
8814 #endif
8815 {
8816 detail::attr_reset reset(attr);
8817 auto r_ = detail::make_input_subrange(r);
8818 auto first = r_.begin();
8819 auto const last = r_.end();
8820 return reset = detail::if_full_parse(
8821 first,
8822 last,
8823 parser::prefix_parse(first, last, parser, attr, trace_mode));
8824 }
8825
8826
8827
8828
8829
8830
8831
8832
8833 #if BOOST_PARSER_USE_CONCEPTS
8834 template<
8835 parsable_iter I,
8836 std::sentinel_for<I> S,
8837 typename Parser,
8838 typename GlobalState,
8839 error_handler<I, S, GlobalState> ErrorHandler>
8840 #else
8841 template<
8842 typename I,
8843 typename S,
8844 typename Parser,
8845 typename GlobalState,
8846 typename ErrorHandler,
8847 typename Enable = std::enable_if_t<
8848 detail::is_parsable_iter_v<I> &&
8849 detail::is_equality_comparable_with_v<I, S>>>
8850 #endif
8851 auto prefix_parse(
8852 I & first,
8853 S last,
8854 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
8855 trace trace_mode = trace::off)
8856 {
8857 if constexpr (!detail::is_char8_iter_v<I>) {
8858 if (trace_mode == trace::on) {
8859 return detail::parse_impl<true>(
8860 first, last, parser, parser.error_handler_);
8861 } else {
8862 return detail::parse_impl<false>(
8863 first, last, parser, parser.error_handler_);
8864 }
8865 } else {
8866 auto r =
8867 BOOST_PARSER_SUBRANGE(first, last) | detail::text::as_utf32;
8868 auto f = r.begin();
8869 auto const l = r.end();
8870 auto _ = detail::scoped_base_assign(first, f);
8871 if (trace_mode == trace::on) {
8872 return detail::parse_impl<true>(
8873 f, l, parser, parser.error_handler_);
8874 } else {
8875 return detail::parse_impl<false>(
8876 f, l, parser, parser.error_handler_);
8877 }
8878 }
8879 }
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894 #if BOOST_PARSER_USE_CONCEPTS
8895 template<
8896 parsable_range R,
8897 typename Parser,
8898 typename GlobalState,
8899 typename ErrorHandler>
8900 #else
8901 template<
8902 typename R,
8903 typename Parser,
8904 typename GlobalState,
8905 typename ErrorHandler,
8906 typename Enable = std::enable_if_t<detail::is_parsable_range_v<R>>>
8907 #endif
8908 auto parse(
8909 R const & r,
8910 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
8911 trace trace_mode = trace::off)
8912 #if BOOST_PARSER_USE_CONCEPTS
8913
8914 requires error_handler<
8915 ErrorHandler,
8916 std::ranges::iterator_t<decltype(detail::make_input_subrange(r))>,
8917 std::ranges::sentinel_t<decltype(detail::make_input_subrange(r))>,
8918 GlobalState>
8919
8920 #endif
8921 {
8922 auto r_ = detail::make_input_subrange(r);
8923 auto first = r_.begin();
8924 auto const last = r_.end();
8925 return detail::if_full_parse(
8926 first, last, parser::prefix_parse(first, last, parser, trace_mode));
8927 }
8928
8929
8930
8931
8932
8933
8934
8935 #if BOOST_PARSER_USE_CONCEPTS
8936 template<
8937 parsable_iter I,
8938 std::sentinel_for<I> S,
8939 typename Parser,
8940 typename GlobalState,
8941 error_handler<I, S, GlobalState> ErrorHandler,
8942 typename SkipParser,
8943 typename Attr>
8944 #else
8945 template<
8946 typename I,
8947 typename S,
8948 typename Parser,
8949 typename GlobalState,
8950 typename ErrorHandler,
8951 typename SkipParser,
8952 typename Attr,
8953 typename Enable = std::enable_if_t<
8954 detail::is_parsable_iter_v<I> &&
8955 detail::is_equality_comparable_with_v<I, S>>>
8956 #endif
8957 bool prefix_parse(
8958 I & first,
8959 S last,
8960 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
8961 parser_interface<SkipParser> const & skip,
8962 Attr & attr,
8963 trace trace_mode = trace::off)
8964 {
8965 detail::attr_reset reset(attr);
8966 if constexpr (!detail::is_char8_iter_v<I>) {
8967 static_assert(
8968 decltype(detail::has_attribute(first, last, parser)){},
8969 "If you're seeing this error, you're trying to get parse() to "
8970 "fill in attr above, using the attribute generated by parser. "
8971 "However, parser does not generate an attribute.");
8972 if (trace_mode == trace::on) {
8973 return reset = detail::skip_parse_impl<true>(
8974 first,
8975 last,
8976 parser,
8977 skip,
8978 parser.error_handler_,
8979 attr);
8980 } else {
8981 return reset = detail::skip_parse_impl<false>(
8982 first,
8983 last,
8984 parser,
8985 skip,
8986 parser.error_handler_,
8987 attr);
8988 }
8989 } else {
8990 auto r =
8991 BOOST_PARSER_SUBRANGE(first, last) | detail::text::as_utf32;
8992 auto f = r.begin();
8993 auto const l = r.end();
8994 auto _ = detail::scoped_base_assign(first, f);
8995 static_assert(
8996 decltype(detail::has_attribute(f, l, parser)){},
8997 "If you're seeing this error, you're trying to get parse() to "
8998 "fill in attr above, using the attribute generated by parser. "
8999 "However, parser does not generate an attribute.");
9000 if (trace_mode == trace::on) {
9001 return reset = detail::skip_parse_impl<true>(
9002 f, l, parser, skip, parser.error_handler_, attr);
9003 } else {
9004 return reset = detail::skip_parse_impl<false>(
9005 f, l, parser, skip, parser.error_handler_, attr);
9006 }
9007 }
9008 }
9009
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023 #if BOOST_PARSER_USE_CONCEPTS
9024 template<
9025 parsable_range R,
9026 typename Parser,
9027 typename GlobalState,
9028 typename ErrorHandler,
9029 typename SkipParser,
9030 typename Attr>
9031 #else
9032 template<
9033 typename R,
9034 typename Parser,
9035 typename GlobalState,
9036 typename ErrorHandler,
9037 typename SkipParser,
9038 typename Attr,
9039 typename Enable = std::enable_if_t<detail::is_parsable_range_v<R>>>
9040 #endif
9041 bool parse(
9042 R const & r,
9043 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
9044 parser_interface<SkipParser> const & skip,
9045 Attr & attr,
9046 trace trace_mode = trace::off)
9047 #if BOOST_PARSER_USE_CONCEPTS
9048
9049 requires error_handler<
9050 ErrorHandler,
9051 std::ranges::iterator_t<decltype(detail::make_input_subrange(r))>,
9052 std::ranges::sentinel_t<decltype(detail::make_input_subrange(r))>,
9053 GlobalState>
9054
9055 #endif
9056 {
9057 detail::attr_reset reset(attr);
9058 auto r_ = detail::make_input_subrange(r);
9059 auto first = r_.begin();
9060 auto const last = r_.end();
9061 return reset = detail::if_full_parse(
9062 first,
9063 last,
9064 parser::prefix_parse(
9065 first, last, parser, skip, attr, trace_mode));
9066 }
9067
9068
9069
9070
9071
9072
9073
9074 #if BOOST_PARSER_USE_CONCEPTS
9075 template<
9076 parsable_iter I,
9077 std::sentinel_for<I> S,
9078 typename Parser,
9079 typename GlobalState,
9080 error_handler<I, S, GlobalState> ErrorHandler,
9081 typename SkipParser>
9082 #else
9083 template<
9084 typename I,
9085 typename S,
9086 typename Parser,
9087 typename GlobalState,
9088 typename ErrorHandler,
9089 typename SkipParser,
9090 typename Enable = std::enable_if_t<
9091 detail::is_parsable_iter_v<I> &&
9092 detail::is_equality_comparable_with_v<I, S>>>
9093 #endif
9094 auto prefix_parse(
9095 I & first,
9096 S last,
9097 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
9098 parser_interface<SkipParser> const & skip,
9099 trace trace_mode = trace::off)
9100 {
9101 if constexpr (!detail::is_char8_iter_v<I>) {
9102 if (trace_mode == trace::on) {
9103 return detail::skip_parse_impl<true>(
9104 first, last, parser, skip, parser.error_handler_);
9105 } else {
9106 return detail::skip_parse_impl<false>(
9107 first, last, parser, skip, parser.error_handler_);
9108 }
9109 } else {
9110 auto r =
9111 BOOST_PARSER_SUBRANGE(first, last) | detail::text::as_utf32;
9112 auto f = r.begin();
9113 auto const l = r.end();
9114 auto _ = detail::scoped_base_assign(first, f);
9115 if (trace_mode == trace::on) {
9116 return detail::skip_parse_impl<true>(
9117 f, l, parser, skip, parser.error_handler_);
9118 } else {
9119 return detail::skip_parse_impl<false>(
9120 f, l, parser, skip, parser.error_handler_);
9121 }
9122 }
9123 }
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
9137
9138 #if BOOST_PARSER_USE_CONCEPTS
9139 template<
9140 parsable_range R,
9141 typename Parser,
9142 typename GlobalState,
9143 typename ErrorHandler,
9144 typename SkipParser>
9145 #else
9146 template<
9147 typename R,
9148 typename Parser,
9149 typename GlobalState,
9150 typename ErrorHandler,
9151 typename SkipParser,
9152 typename Enable = std::enable_if_t<detail::is_parsable_range_v<R>>>
9153 #endif
9154 auto parse(
9155 R const & r,
9156 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
9157 parser_interface<SkipParser> const & skip,
9158 trace trace_mode = trace::off)
9159 #if BOOST_PARSER_USE_CONCEPTS
9160
9161 requires error_handler<
9162 ErrorHandler,
9163 std::ranges::iterator_t<decltype(detail::make_input_subrange(r))>,
9164 std::ranges::sentinel_t<decltype(detail::make_input_subrange(r))>,
9165 GlobalState>
9166
9167 #endif
9168 {
9169 auto r_ = detail::make_input_subrange(r);
9170 auto first = r_.begin();
9171 auto const last = r_.end();
9172 return detail::if_full_parse(
9173 first,
9174 last,
9175 parser::prefix_parse(first, last, parser, skip, trace_mode));
9176 }
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188 #if BOOST_PARSER_USE_CONCEPTS
9189 template<
9190 parsable_iter I,
9191 std::sentinel_for<I> S,
9192 typename Parser,
9193 typename GlobalState,
9194 error_handler<I, S, GlobalState> ErrorHandler,
9195 typename Callbacks>
9196 #else
9197 template<
9198 typename I,
9199 typename S,
9200 typename Parser,
9201 typename GlobalState,
9202 typename ErrorHandler,
9203 typename Callbacks,
9204 typename Enable = std::enable_if_t<
9205 detail::is_parsable_iter_v<I> &&
9206 detail::is_equality_comparable_with_v<I, S>>>
9207 #endif
9208 bool callback_prefix_parse(
9209 I & first,
9210 S last,
9211 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
9212 Callbacks const & callbacks,
9213 trace trace_mode = trace::off)
9214 {
9215 if constexpr (!detail::is_char8_iter_v<I>) {
9216 if (trace_mode == trace::on) {
9217 return detail::callback_parse_impl<true>(
9218 first, last, parser, parser.error_handler_, callbacks);
9219 } else {
9220 return detail::callback_parse_impl<false>(
9221 first, last, parser, parser.error_handler_, callbacks);
9222 }
9223 } else {
9224 auto r =
9225 BOOST_PARSER_SUBRANGE(first, last) | detail::text::as_utf32;
9226 auto f = r.begin();
9227 auto const l = r.end();
9228 auto _ = detail::scoped_base_assign(first, f);
9229 if (trace_mode == trace::on) {
9230 return detail::callback_parse_impl<true>(
9231 f, l, parser, parser.error_handler_, callbacks);
9232 } else {
9233 return detail::callback_parse_impl<false>(
9234 f, l, parser, parser.error_handler_, callbacks);
9235 }
9236 }
9237 }
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256 #if BOOST_PARSER_USE_CONCEPTS
9257 template<
9258 parsable_range R,
9259 typename Parser,
9260 typename GlobalState,
9261 typename ErrorHandler,
9262 typename Callbacks>
9263 #else
9264 template<
9265 typename R,
9266 typename Parser,
9267 typename GlobalState,
9268 typename ErrorHandler,
9269 typename Callbacks,
9270 typename Enable = std::enable_if_t<detail::is_parsable_range_v<R>>>
9271 #endif
9272 bool callback_parse(
9273 R const & r,
9274 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
9275 Callbacks const & callbacks,
9276 trace trace_mode = trace::off)
9277 #if BOOST_PARSER_USE_CONCEPTS
9278
9279 requires error_handler<
9280 ErrorHandler,
9281 std::ranges::iterator_t<decltype(detail::make_input_subrange(r))>,
9282 std::ranges::sentinel_t<decltype(detail::make_input_subrange(r))>,
9283 GlobalState>
9284
9285 #endif
9286 {
9287 auto r_ = detail::make_input_subrange(r);
9288 auto first = r_.begin();
9289 auto const last = r_.end();
9290 return detail::if_full_parse(
9291 first,
9292 last,
9293 parser::callback_prefix_parse(first, last, parser, callbacks));
9294 }
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307 #if BOOST_PARSER_USE_CONCEPTS
9308 template<
9309 parsable_iter I,
9310 std::sentinel_for<I> S,
9311 typename Parser,
9312 typename GlobalState,
9313 error_handler<I, S, GlobalState> ErrorHandler,
9314 typename SkipParser,
9315 typename Callbacks>
9316 #else
9317 template<
9318 typename I,
9319 typename S,
9320 typename Parser,
9321 typename GlobalState,
9322 typename ErrorHandler,
9323 typename SkipParser,
9324 typename Callbacks,
9325 typename Enable = std::enable_if_t<
9326 detail::is_parsable_iter_v<I> &&
9327 detail::is_equality_comparable_with_v<I, S>>>
9328 #endif
9329 bool callback_prefix_parse(
9330 I & first,
9331 S last,
9332 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
9333 parser_interface<SkipParser> const & skip,
9334 Callbacks const & callbacks,
9335 trace trace_mode = trace::off)
9336 {
9337 if constexpr (!detail::is_char8_iter_v<I>) {
9338 if (trace_mode == trace::on) {
9339 return detail::callback_skip_parse_impl<true>(
9340 first,
9341 last,
9342 parser,
9343 skip,
9344 parser.error_handler_,
9345 callbacks);
9346 } else {
9347 return detail::callback_skip_parse_impl<false>(
9348 first,
9349 last,
9350 parser,
9351 skip,
9352 parser.error_handler_,
9353 callbacks);
9354 }
9355 } else {
9356 auto r =
9357 BOOST_PARSER_SUBRANGE(first, last) | detail::text::as_utf32;
9358 auto f = r.begin();
9359 auto const l = r.end();
9360 auto _ = detail::scoped_base_assign(first, f);
9361 if (trace_mode == trace::on) {
9362 return detail::callback_skip_parse_impl<true>(
9363 f, l, parser, skip, parser.error_handler_, callbacks);
9364 } else {
9365 return detail::callback_skip_parse_impl<false>(
9366 f, l, parser, skip, parser.error_handler_, callbacks);
9367 }
9368 }
9369 }
9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389 #if BOOST_PARSER_USE_CONCEPTS
9390 template<
9391 parsable_range R,
9392 typename Parser,
9393 typename GlobalState,
9394 typename ErrorHandler,
9395 typename SkipParser,
9396 typename Callbacks>
9397 #else
9398 template<
9399 typename R,
9400 typename Parser,
9401 typename GlobalState,
9402 typename ErrorHandler,
9403 typename SkipParser,
9404 typename Callbacks,
9405 typename Enable = std::enable_if_t<detail::is_parsable_range_v<R>>>
9406 #endif
9407 bool callback_parse(
9408 R const & r,
9409 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
9410 parser_interface<SkipParser> const & skip,
9411 Callbacks const & callbacks,
9412 trace trace_mode = trace::off)
9413 #if BOOST_PARSER_USE_CONCEPTS
9414
9415 requires error_handler<
9416 ErrorHandler,
9417 std::ranges::iterator_t<decltype(detail::make_input_subrange(r))>,
9418 std::ranges::sentinel_t<decltype(detail::make_input_subrange(r))>,
9419 GlobalState>
9420
9421 #endif
9422 {
9423 auto r_ = detail::make_input_subrange(r);
9424 auto first = r_.begin();
9425 auto const last = r_.end();
9426 return detail::if_full_parse(
9427 first,
9428 last,
9429 parser::callback_prefix_parse(
9430 first, last, parser, skip, callbacks, trace_mode));
9431 }
9432
9433 namespace literals {
9434
9435 constexpr auto operator""_l(char c) { return parser::lit(c); }
9436 #if defined(__cpp_char8_t) || defined(BOOST_PARSER_DOXYGEN)
9437
9438 constexpr auto operator""_l(char8_t c) { return parser::lit(c); }
9439 #endif
9440
9441 constexpr auto operator""_l(char32_t c) { return parser::lit(c); }
9442
9443 constexpr auto operator""_l(char const * str, std::size_t)
9444 {
9445 return parser::lit(str);
9446 }
9447 #if defined(__cpp_char8_t) || defined(BOOST_PARSER_DOXYGEN)
9448
9449 constexpr auto operator""_l(char8_t const * str, std::size_t)
9450 {
9451 return parser::lit(str);
9452 }
9453 #endif
9454
9455 constexpr auto operator""_l(char32_t const * str, std::size_t)
9456 {
9457 return parser::lit(str);
9458 }
9459
9460
9461 constexpr auto operator""_p(char c) { return char_(c); }
9462 #if defined(__cpp_char8_t) || defined(BOOST_PARSER_DOXYGEN)
9463
9464 constexpr auto operator""_p(char8_t c) { return char_(c); }
9465 #endif
9466
9467 constexpr auto operator""_p(char32_t c) { return char_(c); }
9468
9469 constexpr auto operator""_p(char const * str, std::size_t)
9470 {
9471 return parser::string(str);
9472 }
9473 #if defined(__cpp_char8_t) || defined(BOOST_PARSER_DOXYGEN)
9474
9475 constexpr auto operator""_p(char8_t const * str, std::size_t)
9476 {
9477 return parser::string(str);
9478 }
9479 #endif
9480
9481 constexpr auto operator""_p(char32_t const * str, std::size_t)
9482 {
9483 return parser::string(str);
9484 }
9485 }
9486
9487 namespace detail {
9488 template<typename R, typename Parser>
9489 struct attribute_impl
9490 {
9491 using parser_type = typename Parser::parser_type;
9492 using global_state_type = typename Parser::global_state_type;
9493 using error_handler_type = typename Parser::error_handler_type;
9494
9495 using iterator = detail::iterator_t<R>;
9496 using sentinel = detail::sentinel_t<R>;
9497
9498 using context = decltype(detail::make_context<false, false>(
9499 std::declval<iterator>(),
9500 std::declval<sentinel>(),
9501 std::declval<bool &>(),
9502 std::declval<int &>(),
9503 std::declval<error_handler_type>(),
9504 std::declval<global_state_type &>(),
9505 std::declval<detail::symbol_table_tries_t &>(),
9506 std::declval<detail::pending_symbol_table_operations_t &>()));
9507 using type = decltype(std::declval<Parser>()(
9508 std::declval<iterator &>(),
9509 std::declval<sentinel>(),
9510 std::declval<context>(),
9511 detail::null_parser{},
9512 detail::flags::gen_attrs,
9513 std::declval<bool &>()));
9514 };
9515
9516 template<typename Iter, typename Sentinel, typename Parser>
9517 auto has_attribute(Iter first, Sentinel last, Parser parser)
9518 {
9519 using attr_t = typename attribute_impl<
9520 BOOST_PARSER_SUBRANGE<Iter, Sentinel>,
9521 Parser>::type;
9522 return std::integral_constant<bool, !is_nope_v<attr_t>>{};
9523 }
9524
9525 template<typename T>
9526 constexpr wrapper<T> attr_wrapped_final;
9527 template<>
9528 inline constexpr wrapper<none> attr_wrapped_final<nope>;
9529 }
9530
9531 template<typename R, typename Parser>
9532 struct attribute
9533 {
9534 using initial_type = typename detail::attribute_impl<
9535 decltype(detail::make_input_subrange(std::declval<R>())),
9536 Parser>::type;
9537 using type =
9538 typename decltype(detail::attr_wrapped_final<initial_type>)::type;
9539 };
9540
9541
9542 namespace detail {
9543 template<typename... Args>
9544 constexpr void static_assert_merge_attributes(tuple<Args...> parsers)
9545 {
9546 using context_t = parse_context<
9547 false,
9548 false,
9549 char const *,
9550 char const *,
9551 default_error_handler>;
9552 using skipper_t = parser_interface<ws_parser<false, false>>;
9553 using use_parser_t = dummy_use_parser_t<
9554 char const *,
9555 char const *,
9556 context_t,
9557 skipper_t> const;
9558 using all_types =
9559 decltype(hl::transform(parsers, std::declval<use_parser_t>()));
9560 auto all_types_wrapped = hl::transform(all_types{}, detail::wrap{});
9561 auto first_non_nope = hl::fold_left(
9562 all_types_wrapped,
9563 wrapper<nope>{},
9564 [=](auto result, auto type) {
9565 if constexpr (is_nope_v<typename decltype(result)::type>) {
9566 return type;
9567 } else {
9568 return result;
9569 }
9570 });
9571 using first_t = typename decltype(first_non_nope)::type;
9572 static_assert(
9573 !is_nope_v<first_t>,
9574 "It looks like you wrote merge[p1 >> p2 >> ... pn], and none "
9575 "of the parsers p1, p2, ... pn produces an attribute. Please "
9576 "fix.");
9577 if constexpr (is_nope_v<first_t>) {
9578 [[maybe_unused]] detail::print_type<tuple<Args...>> tuple_types;
9579 [[maybe_unused]] detail::print_type<all_types> attribute_types;
9580 }
9581 hl::for_each(all_types_wrapped, [=](auto type) {
9582 using t = typename decltype(type)::type;
9583 if constexpr (!is_nope_v<t>) {
9584 static_assert(
9585 std::is_same_v<t, first_t>,
9586 "If you see an error here, you wrote merge[p1 >> "
9587 "p2 >> ... pn] where at least one of the types in "
9588 "ATTR(p1), ATTR(p2), ... ATTR(pn) is not the same "
9589 "type as one of the others.");
9590 if constexpr (!std::is_same_v<t, first_t>) {
9591 [[maybe_unused]] detail::print_type<tuple<Args...>>
9592 tuple_types(parsers);
9593 [[maybe_unused]] detail::print_type<all_types>
9594 attribute_types;
9595 [[maybe_unused]] detail::print_type<first_t> first_type;
9596 [[maybe_unused]] detail::print_type<t> this_type;
9597 }
9598 }
9599 });
9600 }
9601 }
9602 }}
9603
9604 #endif