mirror of
https://github.com/boostorg/parser.git
synced 2026-01-19 16:32:13 +00:00
Compare commits
6 Commits
boost-1.88
...
issue_160
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88abb615aa | ||
|
|
54f8eecfe6 | ||
|
|
fcd257abca | ||
|
|
2f7e5964a6 | ||
|
|
2fff00b3e1 | ||
|
|
28e9b61735 |
@@ -57,7 +57,7 @@ Master status:
|
||||
|
||||
[](https://github.com/tzlaine/parser/actions/workflows/windows.yml)
|
||||
|
||||
[](https://github.com/tzlaine/parser/actions/workflows/macos-13.yml)
|
||||
[](https://github.com/tzlaine/parser/actions/workflows/macos-12.yml)
|
||||
|
||||
Develop status:
|
||||
|
||||
@@ -67,6 +67,6 @@ Develop status:
|
||||
|
||||
[](https://github.com/tzlaine/parser/actions/workflows/windows.yml)
|
||||
|
||||
[](https://github.com/tzlaine/parser/actions/workflows/macos-13.yml)
|
||||
[](https://github.com/tzlaine/parser/actions/workflows/macos-12.yml)
|
||||
|
||||
[](LICENSE_1_0.txt)
|
||||
|
||||
@@ -110,7 +110,6 @@
|
||||
|
||||
|
||||
[def _std_str_ `std::string`]
|
||||
[def _std_strs_ `std::string`s]
|
||||
[def _std_vec_char_ `std::vector<char>`]
|
||||
[def _std_vec_char32_ `std::vector<char32_t>`]
|
||||
|
||||
@@ -202,7 +201,6 @@
|
||||
[def _merge_ [globalref boost::parser::merge `merge[]`]]
|
||||
[def _sep_ [globalref boost::parser::separate `separate[]`]]
|
||||
[def _transform_ [globalref boost::parser::transform `transform(f)[]`]]
|
||||
[def _delimiter_ [globalref boost::parser::delimiter `delimiter(p)[]`]]
|
||||
|
||||
[def _omit_np_ [globalref boost::parser::omit `omit`]]
|
||||
[def _raw_np_ [globalref boost::parser::raw `raw`]]
|
||||
@@ -213,13 +211,11 @@
|
||||
[def _merge_np_ [globalref boost::parser::merge `merge`]]
|
||||
[def _sep_np_ [globalref boost::parser::separate `separate`]]
|
||||
[def _transform_np_ [globalref boost::parser::transform `transform`]]
|
||||
[def _delimiter_np_ [globalref boost::parser::delimiter `delimiter`]]
|
||||
|
||||
[def _blank_ [globalref boost::parser::blank `blank`]]
|
||||
[def _control_ [globalref boost::parser::control `control`]]
|
||||
[def _digit_ [globalref boost::parser::digit `digit`]]
|
||||
[def _punct_ [globalref boost::parser::punct `punct`]]
|
||||
[def _symb_ [globalref boost::parser::symb `symb`]]
|
||||
[def _hex_digit_ [globalref boost::parser::hex_digit `hex_digit`]]
|
||||
[def _lower_ [globalref boost::parser::lower `lower`]]
|
||||
[def _upper_ [globalref boost::parser::upper `upper`]]
|
||||
@@ -243,7 +239,6 @@
|
||||
[def _more_about_rules_ [link boost_parser.tutorial.more_about_rules More About Rules]]
|
||||
[def _unicode_ [link boost_parser.tutorial.unicode_support Unicode Support]]
|
||||
[def _concepts_ [link boost_parser.concepts Concepts]]
|
||||
[def _seq_parser_example_ [link boost_parser.tutorial.attribute_generation.a_sequence_parser_attribute_example A sequence parser attribute example]]
|
||||
[def _ex_json_ [link boost_parser.extended_examples.parsing_json Parsing JSON]]
|
||||
[def _ex_cb_json_ [link boost_parser.extended_examples.parsing_json_with_callbacks Parsing JSON With Callbacks]]
|
||||
[def _rationale_ [link boost_parser.rationale Rationale]]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -132,11 +132,6 @@ the input they match unless otherwise stated in the table below.]
|
||||
[ The code point type in Unicode parsing, or `char` in non-Unicode parsing. See the entry for _ch_. ]
|
||||
[]]
|
||||
|
||||
[[ `_symb_` ]
|
||||
[ Matches a single symbol code point. ]
|
||||
[ The code point type in Unicode parsing, or `char` in non-Unicode parsing. See the entry for _ch_. ]
|
||||
[]]
|
||||
|
||||
[[ `_hex_digit_` ]
|
||||
[ Matches a single hexidecimal digit code point. ]
|
||||
[ The code point type in Unicode parsing, or `char` in non-Unicode parsing. See the entry for _ch_. ]
|
||||
@@ -390,10 +385,10 @@ consume the input they match unless otherwise stated in the table below.]
|
||||
[[`*p`] [ Parses using `p` repeatedly until `p` no longer matches; always matches. ] [`std::string` if `_ATTR_np_(p)` is `char` or `char32_t`, otherwise `std::vector<_ATTR_np_(p)>`] [ Matching _e_ an unlimited number of times creates an infinite loop, which is undefined behavior in C++. _Parser_ will assert in debug mode when it encounters `*_e_` (this applies to unconditional _e_ only). ]]
|
||||
[[`+p`] [ Parses using `p` repeatedly until `p` no longer matches; matches iff `p` matches at least once. ] [`std::string` if `_ATTR_np_(p)` is `char` or `char32_t`, otherwise `std::vector<_ATTR_np_(p)>`] [ Matching _e_ an unlimited number of times creates an infinite loop, which is undefined behavior in C++. _Parser_ will assert in debug mode when it encounters `+_e_` (this applies to unconditional _e_ only). ]]
|
||||
[[`-p`] [ Equivalent to `p | _e_`. ] [`std::optional<_ATTR_np_(p)>`] []]
|
||||
[[`p1 >> p2`] [ Matches iff `p1` matches and then `p2` matches. ] [`_bp_tup_<_ATTR_np_(p1), _ATTR_np_(p2)>` (See note.)] [ `>>` is associative; `p1 >> p2 >> p3`, `(p1 >> p2) >> p3`, and `p1 >> (p2 >> p3)` are all equivalent. This attribute type only applies to the case where `p1` and `p2` both generate attributes; see _attr_gen_ for the full rules. Differs in precedence from `operator>`. ]]
|
||||
[[`p1 >> p2`] [ Matches iff `p1` matches and then `p2` matches. ] [`_bp_tup_<_ATTR_np_(p1), _ATTR_np_(p2)>` (See note.)] [ `>>` is associative; `p1 >> p2 >> p3`, `(p1 >> p2) >> p3`, and `p1 >> (p2 >> p3)` are all equivalent. This attribute type only applies to the case where `p1` and `p2` both generate attributes; see _attr_gen_ for the full rules. ]]
|
||||
[[`p >> c`] [ Equivalent to `p >> lit(c)`. ] [`_ATTR_np_(p)`] []]
|
||||
[[`p >> r`] [ Equivalent to `p >> lit(r)`. ] [`_ATTR_np_(p)`] []]
|
||||
[[`p1 > p2`] [ Matches iff `p1` matches and then `p2` matches. No back-tracking is allowed after `p1` matches; if `p1` matches but then `p2` does not, the top-level parse fails. ] [`_bp_tup_<_ATTR_np_(p1), _ATTR_np_(p2)>` (See note.)] [ `>` is associative; `p1 > p2 > p3`, `(p1 > p2) > p3`, and `p1 > (p2 > p3)` are all equivalent. This attribute type only applies to the case where `p1` and `p2` both generate attributes; see _attr_gen_ for the full rules. Differs in precedence from `operator>>`. ]]
|
||||
[[`p1 > p2`] [ Matches iff `p1` matches and then `p2` matches. No back-tracking is allowed after `p1` matches; if `p1` matches but then `p2` does not, the top-level parse fails. ] [`_bp_tup_<_ATTR_np_(p1), _ATTR_np_(p2)>` (See note.)] [ `>` is associative; `p1 > p2 > p3`, `(p1 > p2) > p3`, and `p1 > (p2 > p3)` are all equivalent. This attribute type only applies to the case where `p1` and `p2` both generate attributes; see _attr_gen_ for the full rules. ]]
|
||||
[[`p > c`] [ Equivalent to `p > lit(c)`. ] [`_ATTR_np_(p)`] []]
|
||||
[[`p > r`] [ Equivalent to `p > lit(r)`. ] [`_ATTR_np_(p)`] []]
|
||||
[[`p1 | p2`] [ Matches iff either `p1` matches or `p2` matches. ] [`std::variant<_ATTR_np_(p1), _ATTR_np_(p2)>` (See note.)] [ `|` is associative; `p1 | p2 | p3`, `(p1 | p2) | p3`, and `p1 | (p2 | p3)` are all equivalent. This attribute type only applies to the case where `p1` and `p2` both generate attributes, and where the attribute types are different; see _attr_gen_ for the full rules. ]]
|
||||
@@ -429,15 +424,6 @@ because, for any parser `p`, `_e_ | p` is equivalent to _e_, since _e_ always
|
||||
matches. This is not true for _e_ parameterized with a condition. For any
|
||||
condition `cond`, `_e_(cond)` is allowed to appear anywhere within an
|
||||
alternative parser.
|
||||
|
||||
[important The C++ operators `>` and `>>` have different precedences. This
|
||||
will sometimes come up in warnings from your compiler. No matter how you do
|
||||
or do not parenthesize chains of parsers separated by `>` and `>>`, the
|
||||
resulting expression evaluates the same. Feel free to add parentheses if your
|
||||
compiler complains. More broadly, keep the C++ operator precedence rules in
|
||||
mind when writing your parsers _emdash_ the simplest thing to write may not
|
||||
have your intended semantics. ]
|
||||
|
||||
]
|
||||
|
||||
[template table_attribute_generation
|
||||
|
||||
@@ -65,7 +65,7 @@ subparsers does.
|
||||
|
||||
Finally, there is a /permutation parser/; it is created using `operator||`,
|
||||
as in `p1 || p2 || p3`. A permutation parser tries to match all of its
|
||||
subparsers to the input, in any order. So the parser `p1 || p2 || p3` is equivalent to `(p1 >> p2 >> p3) | (p1 >> p3 >> p2) | (p2 >> p1 >> p3) | (p2 >> p3 >> p1) | (p3 >> p1 >> p2) | (p3 >> p2 >> p1)`. Hopefully the advantage of its terseness is self-explanatory. It matches the
|
||||
subparsers to the input, in any order. So the parser `p1 || p2 || p3` is equivalent to `(p1 >> p2 >> p3) | (p1 >> p3 >> p2) | (p2 >> p1 >> p3) | (p2 >> p3 >> p1) | (p3 >> p1 >> p2) | (p3 >> p2 >> p1)`. Hopefully its terseness is self-explanatory. It matches the
|
||||
input iff all of its subparsers do, regardless of the order they match in.
|
||||
|
||||
_Parser_ parsers each have an /attribute/ associated with them, or explicitly
|
||||
@@ -836,14 +836,6 @@ escaped quote character, since those always work.
|
||||
|
||||
[quoted_string_example_5]
|
||||
|
||||
Additionally, with each of the forms shown above, you can optionally provide a
|
||||
parser as a final argument, to will be used to parse each character inside the
|
||||
quotes. You have to provide an actual full parser here; you cannot provide a
|
||||
character or string literal. If you do not provide a character parser, _ch_
|
||||
is used.
|
||||
|
||||
[quoted_string_example_6]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Parsing In Detail]
|
||||
@@ -1450,24 +1442,6 @@ _merge_ and _sep_ create a copy of the given _seq_p_.
|
||||
|
||||
_transform_ creates a _xfm_p_.
|
||||
|
||||
[heading _delimiter_]
|
||||
|
||||
The _delimiter_np_ directive enables the use of a delimiter within a
|
||||
permutation parser. It *only* applies to permutation parsers, just as _merge_
|
||||
and _sep_ only apply to sequence parsers. Consider this permutation parser.
|
||||
|
||||
constexpr auto parser = bp::int_ || bp::string("foo") || bp::char_('g');
|
||||
|
||||
This will match all of: an integer, `"foo"`, and `'g'`, in any order (for
|
||||
example, `"foo g 42"`). If you also want for those three elements to be
|
||||
delimited by commas, you could write this parser instead.
|
||||
|
||||
constexpr auto delimited_parser =
|
||||
bp::delimiter(bp::lit(','))[bp::int_ || bp::string("foo") || bp::char_('g')];
|
||||
|
||||
`delimited_parser` will parse the same elements as `parser`, but will also
|
||||
require commas between the elements (as in `"foo, g, 42"`).
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Combining Operations]
|
||||
@@ -1616,71 +1590,6 @@ attribute becomes `T`.
|
||||
[container_concept]
|
||||
]
|
||||
|
||||
[heading A sequence parser attribute example]
|
||||
|
||||
Note that the application of `OP` is done in the style of a left-fold, and
|
||||
is therefore greedy. This can lead to some non-obvious results. For example,
|
||||
consider this program. Thanks to Duncan Paterson for this very nice example!
|
||||
|
||||
#include <boost/parser/parser.hpp>
|
||||
#include <print>
|
||||
|
||||
namespace bp = boost::parser;
|
||||
int main() {
|
||||
const auto id_set_action = [](auto &ctx) {
|
||||
const auto& [left, right] = _attr(ctx);
|
||||
std::println("{} = {}", left, right);
|
||||
};
|
||||
|
||||
const auto id_parser = bp::char_('a', 'z') > *bp::char_('a', 'z');
|
||||
|
||||
const auto id_set = (id_parser >> '=' >> id_parser)[id_set_action];
|
||||
bp::parse("left=right", id_set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Perhaps surprisingly, this program prints `leftr = ight`! Why is this? This
|
||||
happens because `id_parser` seems to impose structure, but does not. `id_set`
|
||||
is exactly equivalent to this (comments added to clarify which parts are which
|
||||
below).
|
||||
|
||||
const auto id_set = (
|
||||
/*A*/ bp::char_('a', 'z') > /*B*/ *bp::char_('a', 'z') >>
|
||||
/*C*/ '=' >>
|
||||
/*D*/ bp::char_('a', 'z') > /*E*/ *bp::char_('a', 'z')
|
||||
)[id_set_action];
|
||||
|
||||
As _Parser_ applies `OP` to this sequence parser, the individual steps are:
|
||||
`A` and `B` get merged into a single _std_str_; `C` is ignored, since it
|
||||
produces no attribute; and `D` gets merged into the _std_str_ formed earlier
|
||||
by `A` and `B`; finally, we have `E`. `E` does not combine with `D`, as `D`
|
||||
was already consumed. `E` also does not combine with the _std_str_ we formed
|
||||
from `A`, `B`, and `D`, since we don't combine adjacent containers. In the
|
||||
end, we have a 2-tuple of _std_strs_, in which the first element contains all
|
||||
the characters parsed by `A`, `B`, and `D`, and in which the second element
|
||||
contains all the characters parsed by `E`.
|
||||
|
||||
That's clearly not what we wanted here, though. How do we get a top-level
|
||||
parser that would print `left = right`? We use a _r_. The parser used inside
|
||||
a _r_ can never combine with any parser(s) outside the _r_. Instances of a
|
||||
rule are inherently separate from all parsers with which they are used,
|
||||
whether those parsers are _rs_ or non-_r_ parsers. So, consider a _r_
|
||||
equivalent to the previous `id_parser` above.
|
||||
|
||||
namespace bp = boost::parser;
|
||||
bp::rule<struct id_parser_tag, std::string> id_parser = "identifier";
|
||||
auto const id_parser_def = bp::char_('a', 'z') > *bp::char_('a', 'z');
|
||||
BOOST_PARSER_DEFINE_RULES(id_parser);
|
||||
|
||||
Later, we can use it just as we used the previous non-rule version.
|
||||
|
||||
const auto id_set = (id_parser >> '=' >> id_parser)[id_set_action];
|
||||
|
||||
This produces the results you might expect, since only the `bp::char_('a',
|
||||
'z') > *bp::char_('a', 'z')` parser inside the `id_parser` _r_ is ever
|
||||
eligible for combining via `OP`.
|
||||
|
||||
|
||||
[heading Alternative parser attribute rules]
|
||||
|
||||
The rules for alternative parsers are much simpler. For an alternative parer
|
||||
@@ -2302,8 +2211,6 @@ common use cases for _rs_. Use a _r_ if you want to:
|
||||
* fix the attribute type produced by a parser to something other than the
|
||||
default;
|
||||
|
||||
* control the attributes generated by adjacent sequence parsers;
|
||||
|
||||
* create a parser that produces useful diagnostic text;
|
||||
|
||||
* create a recursive rule (more on this below);
|
||||
@@ -2444,10 +2351,6 @@ action if:
|
||||
|
||||
The notion of "compatible" is defined in _p_api_.
|
||||
|
||||
[heading Controlling the attributes generated]
|
||||
|
||||
See the _seq_parser_example_ in the _attr_gen_ section for details.
|
||||
|
||||
[heading Creating a parser for better diagnostics]
|
||||
|
||||
Each _r_ has associated diagnostic text that _Parser_ can use for failures of
|
||||
|
||||
@@ -73,12 +73,6 @@
|
||||
|
||||
#endif
|
||||
|
||||
// Follows logic in boost/config/detail/select_compiler_config.hpp.
|
||||
#if defined(__clang__) && !defined(__ibmxl__) && !defined(__CODEGEARC__)
|
||||
#elif defined(__GNUC__) && !defined(__ibmxl__)
|
||||
#define BOOST_PARSER_GCC
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_lib_constexpr_algorithms)
|
||||
# define BOOST_PARSER_ALGO_CONSTEXPR constexpr
|
||||
#else
|
||||
|
||||
@@ -52,110 +52,118 @@ namespace boost { namespace parser { namespace detail {
|
||||
typename Parser,
|
||||
typename DelimiterParser,
|
||||
typename MinType,
|
||||
typename MaxType>
|
||||
void print_parser(
|
||||
typename MaxType,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
repeat_parser<Parser, DelimiterParser, MinType, MaxType> const & parser,
|
||||
repeat_parser<
|
||||
Parser,
|
||||
DelimiterParser,
|
||||
MinType,
|
||||
MaxType,
|
||||
ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename Parser>
|
||||
void print_parser(
|
||||
template<typename Context, typename Parser, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
opt_parser<Parser> const & parser,
|
||||
opt_parser<Parser, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename ParserTuple>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserTuple, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
or_parser<ParserTuple> const & parser,
|
||||
or_parser<ParserTuple, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename ParserTuple, typename DelimiterParser>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserTuple, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
perm_parser<ParserTuple, DelimiterParser> const & parser,
|
||||
perm_parser<ParserTuple, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<
|
||||
typename Context,
|
||||
typename ParserTuple,
|
||||
typename BacktrackingTuple,
|
||||
typename CombiningGroups>
|
||||
void print_parser(
|
||||
typename CombiningGroups,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
|
||||
parser,
|
||||
seq_parser<
|
||||
ParserTuple,
|
||||
BacktrackingTuple,
|
||||
CombiningGroups,
|
||||
ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename Parser, typename Action>
|
||||
void print_parser(
|
||||
template<
|
||||
typename Context,
|
||||
typename Parser,
|
||||
typename Action,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
action_parser<Parser, Action> const & parser,
|
||||
action_parser<Parser, Action, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename Parser, typename F>
|
||||
void print_parser(
|
||||
template<typename Context, typename Parser, typename F, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
transform_parser<Parser, F> const & parser,
|
||||
transform_parser<Parser, F, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename Parser>
|
||||
void print_parser(
|
||||
template<typename Context, typename Parser, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
omit_parser<Parser> const & parser,
|
||||
raw_parser<Parser, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
|
||||
template<typename Context, typename Parser>
|
||||
void print_parser(
|
||||
Context const & context,
|
||||
raw_parser<Parser> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
#if defined(BOOST_PARSER_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS
|
||||
template<typename Context, typename Parser>
|
||||
void print_parser(
|
||||
template<typename Context, typename Parser, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
string_view_parser<Parser> const & parser,
|
||||
string_view_parser<Parser, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
#endif
|
||||
|
||||
template<typename Context, typename Parser>
|
||||
void print_parser(
|
||||
template<typename Context, typename Parser, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
lexeme_parser<Parser> const & parser,
|
||||
lexeme_parser<Parser, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename Parser>
|
||||
void print_parser(
|
||||
template<
|
||||
typename Context,
|
||||
typename Parser,
|
||||
typename SkipParser,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
no_case_parser<Parser> const & parser,
|
||||
skip_parser<Parser, SkipParser, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename Parser, typename SkipParser>
|
||||
void print_parser(
|
||||
template<
|
||||
typename Context,
|
||||
typename Parser,
|
||||
expect_match_t ExpectMatch,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
skip_parser<Parser, SkipParser> const & parser,
|
||||
expect_parser<Parser, ExpectMatch, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
|
||||
template<typename Context, typename Parser, bool FailOnMatch>
|
||||
void print_parser(
|
||||
Context const & context,
|
||||
expect_parser<Parser, FailOnMatch> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<
|
||||
typename Context,
|
||||
@@ -163,154 +171,147 @@ namespace boost { namespace parser { namespace detail {
|
||||
typename Parser,
|
||||
typename Attribute,
|
||||
typename LocalState,
|
||||
typename ParamsTuple>
|
||||
void print_parser(
|
||||
typename ParamsTuple,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
rule_parser<
|
||||
UseCallbacks,
|
||||
Parser,
|
||||
Attribute,
|
||||
LocalState,
|
||||
ParamsTuple> const & parser,
|
||||
ParamsTuple,
|
||||
ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename T>
|
||||
void print_parser(
|
||||
template<typename Context, typename T, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
symbol_parser<T> const & parser,
|
||||
symbol_parser<T, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename Predicate>
|
||||
void print_parser(
|
||||
template<typename Context, typename Predicate, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
eps_parser<Predicate> const & parser,
|
||||
eps_parser<Predicate, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
eps_parser<nope> const & parser,
|
||||
eps_parser<nope, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
eoi_parser const & parser,
|
||||
eoi_parser<ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename Atribute>
|
||||
void print_parser(
|
||||
template<typename Context, typename Atribute, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
attr_parser<Atribute> const & parser,
|
||||
attr_parser<Atribute, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename Expected, typename AttributeType>
|
||||
void print_parser(
|
||||
template<
|
||||
typename Context,
|
||||
typename Expected,
|
||||
typename AttributeType,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
char_parser<Expected, AttributeType> const & parser,
|
||||
char_parser<Expected, AttributeType, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
digit_parser const & parser,
|
||||
digit_parser<ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
char_subrange_parser<hex_digit_subranges> const & parser,
|
||||
char_subrange_parser<hex_digit_subranges, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
char_subrange_parser<control_subranges> const & parser,
|
||||
char_subrange_parser<control_subranges, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
char_set_parser<punct_chars> const & parser,
|
||||
char_set_parser<punct_chars, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
char_set_parser<symb_chars> const & parser,
|
||||
char_set_parser<lower_case_chars, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
char_set_parser<lower_case_chars> const & parser,
|
||||
char_set_parser<upper_case_chars, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<
|
||||
typename Context,
|
||||
typename StrIter,
|
||||
typename StrSentinel,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
char_set_parser<upper_case_chars> const & parser,
|
||||
string_parser<StrIter, StrSentinel, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
|
||||
template<typename Context, typename Expected, typename AttributeType>
|
||||
void print_parser(
|
||||
Context const & context,
|
||||
omit_parser<char_parser<Expected, AttributeType>> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
|
||||
template<typename Context, typename StrIter, typename StrSentinel>
|
||||
void print_parser(
|
||||
Context const & context,
|
||||
string_parser<StrIter, StrSentinel> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
|
||||
template<typename Context, typename StrIter, typename StrSentinel>
|
||||
void print_parser(
|
||||
Context const & context,
|
||||
omit_parser<string_parser<StrIter, StrSentinel>> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<
|
||||
typename Context,
|
||||
typename Quotes,
|
||||
typename Escapes,
|
||||
typename CharParser>
|
||||
void print_parser(
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
quoted_string_parser<Quotes, Escapes, CharParser> const & parser,
|
||||
quoted_string_parser<Quotes, Escapes, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, bool NewlinesOnly, bool NoNewlines>
|
||||
void print_parser(
|
||||
template<
|
||||
typename Context,
|
||||
bool NewlinesOnly,
|
||||
bool NoNewlines,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
ws_parser<NewlinesOnly, NoNewlines> const & parser,
|
||||
ws_parser<NewlinesOnly, NoNewlines, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
bool_parser const & parser,
|
||||
bool_parser<ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<
|
||||
typename Context,
|
||||
@@ -318,12 +319,19 @@ namespace boost { namespace parser { namespace detail {
|
||||
int Radix,
|
||||
int MinDigits,
|
||||
int MaxDigits,
|
||||
typename Expected>
|
||||
void print_parser(
|
||||
typename Expected,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
uint_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
|
||||
uint_parser<
|
||||
T,
|
||||
Radix,
|
||||
MinDigits,
|
||||
MaxDigits,
|
||||
Expected,
|
||||
ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<
|
||||
typename Context,
|
||||
@@ -331,38 +339,51 @@ namespace boost { namespace parser { namespace detail {
|
||||
int Radix,
|
||||
int MinDigits,
|
||||
int MaxDigits,
|
||||
typename Expected>
|
||||
void print_parser(
|
||||
typename Expected,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
int_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
|
||||
int_parser<T, Radix, MinDigits, MaxDigits, Expected, ParserMods> const &
|
||||
parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename T>
|
||||
void print_parser(
|
||||
template<typename Context, typename T, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
float_parser<T> const & parser,
|
||||
float_parser<T, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
float_parser<float> const & parser,
|
||||
float_parser<float, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context>
|
||||
void print_parser(
|
||||
template<typename Context, typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
float_parser<double> const & parser,
|
||||
float_parser<double, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
int components);
|
||||
|
||||
template<typename Context, typename SwitchValue, typename OrParser>
|
||||
template<
|
||||
typename Context,
|
||||
typename SwitchValue,
|
||||
typename OrParser,
|
||||
typename ParserMods>
|
||||
void print_parser_impl(
|
||||
Context const & context,
|
||||
switch_parser<SwitchValue, OrParser, ParserMods> const & parser,
|
||||
std::ostream & os,
|
||||
int components);
|
||||
|
||||
template<bool SuppressOmit = false, typename Context, typename Parser>
|
||||
void print_parser(
|
||||
Context const & context,
|
||||
switch_parser<SwitchValue, OrParser> const & parser,
|
||||
Parser const & parser,
|
||||
std::ostream & os,
|
||||
int components = 0);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,9 +24,8 @@
|
||||
#define BOOST_PARSER_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE 0
|
||||
#endif
|
||||
|
||||
#if !BOOST_PARSER_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE && \
|
||||
BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS && \
|
||||
defined(BOOST_PARSER_GCC) && 12 <= __GNUC__
|
||||
#if !BOOST_PARSER_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE && \
|
||||
BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS && defined(__GNUC__) && 12 <= __GNUC__
|
||||
#define BOOST_PARSER_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE 1
|
||||
#else
|
||||
#define BOOST_PARSER_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE 0
|
||||
|
||||
@@ -42,8 +42,7 @@ namespace boost::parser::detail::text::detail {
|
||||
template<typename R>
|
||||
constexpr bool view =
|
||||
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS || \
|
||||
(defined(__cpp_lib_concepts) && \
|
||||
(!defined(BOOST_PARSER_GCC) || 12 <= __GNUC__))
|
||||
(defined(__cpp_lib_concepts) && (!defined(__GNUC__) || 12 <= __GNUC__))
|
||||
std::ranges::view<R>
|
||||
#else
|
||||
range_<R> && !container_<R> &&
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -143,14 +143,41 @@ namespace boost { namespace parser {
|
||||
|
||||
struct punct_chars
|
||||
{};
|
||||
struct symb_chars
|
||||
{};
|
||||
struct lower_case_chars
|
||||
{};
|
||||
struct upper_case_chars
|
||||
{};
|
||||
}
|
||||
|
||||
enum struct omit_attr_t { no, yes };
|
||||
enum struct ignore_case_t { no, yes };
|
||||
enum struct expect_match_t { no, yes };
|
||||
|
||||
template<typename Parser, expect_match_t ExpectMatch>
|
||||
struct expected_parser
|
||||
{
|
||||
static constexpr expect_match_t expect_match = ExpectMatch;
|
||||
|
||||
Parser parser;
|
||||
};
|
||||
|
||||
template<
|
||||
omit_attr_t OmitAttr = omit_attr_t::no,
|
||||
ignore_case_t IgnoreCase = ignore_case_t::no,
|
||||
typename PreParser = detail::nope,
|
||||
typename PostParser = detail::nope>
|
||||
struct parser_modifiers
|
||||
{
|
||||
using pre_parser_type = PreParser;
|
||||
using post_parser_type = PostParser;
|
||||
|
||||
static constexpr omit_attr_t omit_attr = OmitAttr;
|
||||
static constexpr ignore_case_t ignore_case = IgnoreCase;
|
||||
|
||||
[[no_unique_address]] PreParser pre_parser;
|
||||
[[no_unique_address]] PostParser post_parser;
|
||||
};
|
||||
|
||||
/** Repeats the application of another parser `p` of type `Parser`,
|
||||
optionally applying another parser `d` of type `DelimiterParser` in
|
||||
between each pair of applications of `p`. The parse succeeds if `p`
|
||||
@@ -161,20 +188,21 @@ namespace boost { namespace parser {
|
||||
typename Parser,
|
||||
typename DelimiterParser = detail::nope,
|
||||
typename MinType = int64_t,
|
||||
typename MaxType = int64_t>
|
||||
typename MaxType = int64_t,
|
||||
typename ParserMods = parser_modifiers<>>
|
||||
struct repeat_parser;
|
||||
|
||||
/** Repeats the application of another parser `p` of type `Parser`, `[0,
|
||||
Inf)` times. The parse always succeeds. The attribute produced is a
|
||||
sequence of the type of attribute produced by `Parser`. */
|
||||
template<typename Parser>
|
||||
template<typename Parser, typename ParserMods>
|
||||
struct zero_plus_parser;
|
||||
|
||||
/** Repeats the application of another parser `p` of type `Parser`, `[1,
|
||||
Inf)` times. The parse succeeds iff `p` succeeds at least once. The
|
||||
attribute produced is a sequence of the type of attribute produced by
|
||||
`Parser`. */
|
||||
template<typename Parser>
|
||||
template<typename Parser, typename ParserMods>
|
||||
struct one_plus_parser;
|
||||
|
||||
/** Repeats the application of another parser `p` of type `Parser`, `[1,
|
||||
@@ -183,14 +211,14 @@ namespace boost { namespace parser {
|
||||
succeeds at least once, and `d` succeeds each time it is applied. The
|
||||
attribute produced is a sequence of the type of attribute produced by
|
||||
`Parser`. */
|
||||
template<typename Parser, typename DelimiterParser>
|
||||
template<typename Parser, typename DelimiterParser, typename ParserMods>
|
||||
struct delimited_seq_parser;
|
||||
|
||||
/** Repeats the application of another parser of type `Parser`, `[0, 1]`
|
||||
times. The parse always succeeds. The attribute produced is a
|
||||
`std::optional<T>`, where `T` is the type of attribute produced by
|
||||
`Parser`. */
|
||||
template<typename Parser>
|
||||
template<typename Parser, typename ParserMods>
|
||||
struct opt_parser;
|
||||
|
||||
/** Applies each parser in `ParserTuple`, in order, stopping after the
|
||||
@@ -198,7 +226,7 @@ namespace boost { namespace parser {
|
||||
one of the sub-parsers succeeds. The attribute produced is a
|
||||
`std::variant` over the types of attribute produced by the parsers in
|
||||
`ParserTuple`. */
|
||||
template<typename ParserTuple>
|
||||
template<typename ParserTuple, typename ParserMods>
|
||||
struct or_parser;
|
||||
|
||||
/** Applies each parsers in `ParserTuple`, an any order, stopping after
|
||||
@@ -209,7 +237,7 @@ namespace boost { namespace parser {
|
||||
`ParserTuple`, not the order of the parsers' matches. It is an error
|
||||
to specialize `perm_parser` with a `ParserTuple` template parameter
|
||||
that includes an `eps_parser`. */
|
||||
template<typename ParserTuple, typename DelimiterParser>
|
||||
template<typename ParserTuple, typename ParserMods>
|
||||
struct perm_parser;
|
||||
|
||||
/** Applies each parser in `ParserTuple`, in order. The parse succeeds
|
||||
@@ -222,14 +250,15 @@ namespace boost { namespace parser {
|
||||
template<
|
||||
typename ParserTuple,
|
||||
typename BacktrackingTuple,
|
||||
typename CombiningGroups>
|
||||
typename CombiningGroups,
|
||||
typename ParserMods>
|
||||
struct seq_parser;
|
||||
|
||||
/** Applies the given parser `p` of type `Parser` and an invocable `a` of
|
||||
type `Action`. `Action` shall model `semantic_action`, and `a` will
|
||||
only be invoked if `p` succeeds. The parse succeeds iff `p` succeeds.
|
||||
Produces no attribute. */
|
||||
template<typename Parser, typename Action>
|
||||
template<typename Parser, typename Action, typename ParserMods>
|
||||
struct action_parser;
|
||||
|
||||
/** Applies the given parser `p` of type `Parser`. The attribute produced
|
||||
@@ -237,21 +266,14 @@ namespace boost { namespace parser {
|
||||
only be invoked if `p` succeeds and sttributes are currently being
|
||||
generated. The parse succeeds iff `p` succeeds. The attribute
|
||||
produced is the the result of the call to `f`. */
|
||||
template<typename Parser, typename F>
|
||||
template<typename Parser, typename F, typename ParserMods>
|
||||
struct transform_parser;
|
||||
|
||||
/** Applies the given parser `p` of type `Parser`. This parser produces
|
||||
no attribute, and suppresses the production of any attributes that
|
||||
would otherwise be produced by `p`. The parse succeeds iff `p`
|
||||
succeeds. */
|
||||
template<typename Parser>
|
||||
struct omit_parser;
|
||||
|
||||
/** Applies the given parser `p` of type `Parser`; regardless of the
|
||||
attribute produced by `Parser`, this parser's attribute is equivalent
|
||||
to `_where(ctx)` within a semantic action on `p`. The parse succeeds
|
||||
iff `p` succeeds. */
|
||||
template<typename Parser>
|
||||
template<typename Parser, typename ParserMods>
|
||||
struct raw_parser;
|
||||
|
||||
#if defined(BOOST_PARSER_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS
|
||||
@@ -264,34 +286,30 @@ namespace boost { namespace parser {
|
||||
non-contiguous, code using `string_view_parser` is ill-formed. The
|
||||
parse succeeds iff `p` succeeds. This parser is only available in
|
||||
C++20 and later. */
|
||||
template<typename Parser>
|
||||
template<typename Parser, typename ParserMods>
|
||||
struct string_view_parser;
|
||||
#endif
|
||||
|
||||
/** Applies the given parser `p` of type `Parser`, disabling the current
|
||||
skipper in use, if any. The parse succeeds iff `p` succeeds. The
|
||||
attribute produced is the type of attribute produced by `Parser`. */
|
||||
template<typename Parser>
|
||||
template<typename Parser, typename ParserMods>
|
||||
struct lexeme_parser;
|
||||
|
||||
/** Applies the given parser `p` of type `Parser`, enabling
|
||||
case-insensitive matching, based on Unicode case folding. The parse
|
||||
succeeds iff `p` succeeds. The attribute produced is the type of
|
||||
attribute produced by `Parser`. */
|
||||
template<typename Parser>
|
||||
struct no_case_parser;
|
||||
|
||||
/** Applies the given parser `p` of type `Parser`, using a parser of type
|
||||
`SkipParser` as the skipper. The parse succeeds iff `p` succeeds.
|
||||
The attribute produced is the type of attribute produced by
|
||||
`Parser`. */
|
||||
template<typename Parser, typename SkipParser = detail::nope>
|
||||
template<
|
||||
typename Parser,
|
||||
typename SkipParser = detail::nope,
|
||||
typename ParserMods = parser_modifiers<>>
|
||||
struct skip_parser;
|
||||
|
||||
/** Applies the given parser `p` of type `Parser`, producing no attributes
|
||||
and consuming no input. The parse succeeds iff `p`'s success is
|
||||
unequal to `FailOnMatch`. */
|
||||
template<typename Parser, bool FailOnMatch>
|
||||
and consuming no input. The parse succeeds iff `p`'s success is equal
|
||||
to `ExpectMatch == expect_match_t::yes`. */
|
||||
template<typename Parser, expect_match_t ExpectMatch, typename ParserMods>
|
||||
struct expect_parser;
|
||||
|
||||
/** Matches one of a set S of possible inputs, each of which is associated
|
||||
@@ -300,7 +318,7 @@ namespace boost { namespace parser {
|
||||
from S dynamically, during parsing; any such changes are reverted at
|
||||
the end of parsing. The parse succeeds iff an element of S is
|
||||
matched. \see `symbols` */
|
||||
template<typename T>
|
||||
template<typename T, typename ParserMods>
|
||||
struct symbol_parser;
|
||||
|
||||
/** Applies another parser `p`, associated with this parser via `TagType`.
|
||||
@@ -319,22 +337,24 @@ namespace boost { namespace parser {
|
||||
typename TagType,
|
||||
typename Attribute,
|
||||
typename LocalState,
|
||||
typename ParamsTuple>
|
||||
typename ParamsTuple,
|
||||
typename ParserMods>
|
||||
struct rule_parser;
|
||||
|
||||
/** Matches anything, and consumes no input. If `Predicate` is anything
|
||||
other than `detail::nope` (which it is by default), and `pred_(ctx)`
|
||||
evaluates to false, where `ctx` is the parser context, the parse
|
||||
fails. */
|
||||
template<typename Predicate>
|
||||
template<typename Predicate, typename ParserMods>
|
||||
struct eps_parser;
|
||||
|
||||
/** Matches only the end of input. Produces no attribute. */
|
||||
template<typename ParserMods>
|
||||
struct eoi_parser;
|
||||
|
||||
/** Matches anything, consumes no input, and produces an attribute of type
|
||||
`RESOLVE(Attribute)`. */
|
||||
template<typename Attribute>
|
||||
template<typename Attribute, typename ParserMods>
|
||||
struct attr_parser;
|
||||
|
||||
/** A tag type that can be passed as the first parameter to `char_()` when
|
||||
@@ -351,7 +371,10 @@ namespace boost { namespace parser {
|
||||
parse fails only if the parser is constructed with a specific set of
|
||||
expected code point values that does not include the matched code
|
||||
point. */
|
||||
template<typename Expected, typename AttributeType = void>
|
||||
template<
|
||||
typename Expected,
|
||||
typename AttributeType = void,
|
||||
typename ParserMods = parser_modifiers<>>
|
||||
struct char_parser;
|
||||
|
||||
/** Matches a single code point that is equal to one of the code points
|
||||
@@ -359,7 +382,7 @@ namespace boost { namespace parser {
|
||||
characters for matching Unicode character classes like punctuation or
|
||||
lower case. Attribute type is the attribute type of the character
|
||||
being matched. */
|
||||
template<typename Tag>
|
||||
template<typename Tag, typename ParserMods>
|
||||
struct char_set_parser;
|
||||
|
||||
/** Matches a single code point that falls into one of the subranges of
|
||||
@@ -367,17 +390,18 @@ namespace boost { namespace parser {
|
||||
sets of characters for matching Unicode character classes like hex
|
||||
digits or control characters. Attribute type is the attribute type of
|
||||
the character being matched. */
|
||||
template<typename Tag>
|
||||
template<typename Tag, typename ParserMods>
|
||||
struct char_subrange_parser;
|
||||
|
||||
/** Matches a single decimal digit code point, using the Unicode character
|
||||
class Hex_Digit. Attribute type is the attribute type of the
|
||||
character being matched. */
|
||||
template<typename ParserMods>
|
||||
struct digit_parser;
|
||||
|
||||
/** Matches a particular string, delimited by an iterator sentinel pair;
|
||||
produces no attribute. */
|
||||
template<typename StrIter, typename StrSentinel>
|
||||
template<typename StrIter, typename StrSentinel, typename ParserMods>
|
||||
struct string_parser;
|
||||
|
||||
/** Matches a string delimited by quotation marks; produces a
|
||||
@@ -385,7 +409,7 @@ namespace boost { namespace parser {
|
||||
template<
|
||||
typename Quotes = detail::nope,
|
||||
typename Escapes = detail::nope,
|
||||
typename CharParser = char_parser<detail::nope>>
|
||||
typename ParserMods = parser_modifiers<>>
|
||||
struct quoted_string_parser;
|
||||
|
||||
/** Matches an end-of-line (`NewlinesOnly == true`), whitespace
|
||||
@@ -393,11 +417,12 @@ namespace boost { namespace parser {
|
||||
but not newline) code point, based on the Unicode definitions of each
|
||||
(also matches the two code points `"\r\n"`). Produces no
|
||||
attribute. */
|
||||
template<bool NewlinesOnly, bool NoNewlines>
|
||||
template<bool NewlinesOnly, bool NoNewlines, typename ParserMods>
|
||||
struct ws_parser;
|
||||
|
||||
/** Matches the strings "true" and "false", producing an attribute of
|
||||
`true` or `false`, respectively, and fails on any other input. */
|
||||
template<typename ParserMods>
|
||||
struct bool_parser;
|
||||
|
||||
/** Matches an unsigned number of radix `Radix`, of at least `MinDigits`
|
||||
@@ -411,7 +436,8 @@ namespace boost { namespace parser {
|
||||
int Radix = 10,
|
||||
int MinDigits = 1,
|
||||
int MaxDigits = -1,
|
||||
typename Expected = detail::nope>
|
||||
typename Expected = detail::nope,
|
||||
typename ParserMods = parser_modifiers<>>
|
||||
struct uint_parser;
|
||||
|
||||
/** Matches a signed number of radix `Radix`, of at least `MinDigits` and
|
||||
@@ -425,12 +451,13 @@ namespace boost { namespace parser {
|
||||
int Radix = 10,
|
||||
int MinDigits = 1,
|
||||
int MaxDigits = -1,
|
||||
typename Expected = detail::nope>
|
||||
typename Expected = detail::nope,
|
||||
typename ParserMods = parser_modifiers<>>
|
||||
struct int_parser;
|
||||
|
||||
/** Matches a floating point number, producing an attribute of type
|
||||
`T`. */
|
||||
template<typename T>
|
||||
template<typename T, typename ParserMods>
|
||||
struct float_parser;
|
||||
|
||||
/** Applies at most one of the parsers in `OrParser`. If `switch_value_`
|
||||
@@ -438,7 +465,10 @@ namespace boost { namespace parser {
|
||||
first such parser is applied, and the success or failure and attribute
|
||||
of the parse are those of the applied parser. Otherwise, the parse
|
||||
fails. */
|
||||
template<typename SwitchValue, typename OrParser = detail::nope>
|
||||
template<
|
||||
typename SwitchValue,
|
||||
typename OrParser = detail::nope,
|
||||
typename ParserMods = parser_modifiers<>>
|
||||
struct switch_parser;
|
||||
|
||||
/** A wrapper for parsers that provides the operations that must be
|
||||
|
||||
@@ -451,7 +451,7 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>>;
|
||||
|
||||
template<
|
||||
typename V,
|
||||
@@ -469,7 +469,7 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>>;
|
||||
|
||||
namespace detail {
|
||||
template<
|
||||
@@ -571,7 +571,8 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>>
|
||||
[[nodiscard]] constexpr auto operator()(
|
||||
R && r,
|
||||
parser_interface<Parser, GlobalState, ErrorHandler> const &
|
||||
@@ -582,7 +583,8 @@ namespace boost::parser {
|
||||
return (*this)(
|
||||
(R &&)r,
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
(ReplacementR &&)replacement,
|
||||
trace_mode);
|
||||
}
|
||||
@@ -623,10 +625,11 @@ namespace boost::parser {
|
||||
std::is_same_v<Trace, trace>) {
|
||||
// (r, parser, replacement, trace) case
|
||||
return impl(
|
||||
(R &&) r,
|
||||
(R &&)r,
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
(SkipParser &&) skip,
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
(SkipParser &&)skip,
|
||||
replacement);
|
||||
} else {
|
||||
static_assert(
|
||||
|
||||
@@ -116,7 +116,9 @@ namespace boost::parser {
|
||||
return BOOST_PARSER_SUBRANGE(first, first);
|
||||
|
||||
auto const search_parser = omit[*(char_ - parser)] >> -raw[parser];
|
||||
if constexpr (std::is_same_v<SkipParser, eps_parser<phony>>) {
|
||||
if constexpr (std::is_same_v<
|
||||
SkipParser,
|
||||
eps_parser<phony, parser_modifiers<>>>) {
|
||||
auto result = parser::prefix_parse(
|
||||
first, last, search_parser, trace_mode);
|
||||
if (*result)
|
||||
@@ -255,9 +257,9 @@ namespace boost::parser {
|
||||
trace trace_mode = trace::off)
|
||||
{
|
||||
return parser::search(
|
||||
(R &&) r,
|
||||
(R &&)r,
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
trace_mode);
|
||||
}
|
||||
|
||||
@@ -292,7 +294,7 @@ namespace boost::parser {
|
||||
return parser::search(
|
||||
BOOST_PARSER_SUBRANGE(first, last),
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
trace_mode);
|
||||
}
|
||||
|
||||
@@ -483,7 +485,7 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>>;
|
||||
|
||||
template<
|
||||
typename V,
|
||||
@@ -496,7 +498,7 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>>;
|
||||
|
||||
namespace detail {
|
||||
template<
|
||||
@@ -569,7 +571,8 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>>
|
||||
[[nodiscard]] constexpr auto operator()(
|
||||
R && r,
|
||||
parser_interface<Parser, GlobalState, ErrorHandler> const &
|
||||
@@ -579,7 +582,8 @@ namespace boost::parser {
|
||||
return (*this)(
|
||||
(R &&)r,
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
trace_mode);
|
||||
}
|
||||
|
||||
@@ -590,8 +594,8 @@ namespace boost::parser {
|
||||
typename Parser,
|
||||
typename GlobalState,
|
||||
typename ErrorHandler,
|
||||
typename SkipParser =
|
||||
parser_interface<eps_parser<detail::phony>>,
|
||||
typename SkipParser = parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>,
|
||||
typename Trace = trace,
|
||||
typename Enable = std::enable_if_t<is_parsable_range_v<R>>>
|
||||
[[nodiscard]] constexpr auto operator()(
|
||||
@@ -607,9 +611,10 @@ namespace boost::parser {
|
||||
std::is_same_v<Trace, trace>) {
|
||||
// (r, parser, trace) case
|
||||
return impl(
|
||||
(R &&) r,
|
||||
(R &&)r,
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
skip);
|
||||
} else if constexpr (
|
||||
detail::is_parser_iface<SkipParser> &&
|
||||
|
||||
@@ -193,14 +193,13 @@ namespace boost::parser {
|
||||
typename Parser,
|
||||
typename GlobalState,
|
||||
typename ErrorHandler>
|
||||
split_view(
|
||||
V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
|
||||
split_view(V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
|
||||
-> split_view<
|
||||
detail::text::detail::all_t<V>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>>;
|
||||
|
||||
template<
|
||||
typename V,
|
||||
@@ -213,7 +212,7 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>>;
|
||||
|
||||
namespace detail {
|
||||
template<
|
||||
@@ -286,7 +285,8 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>>
|
||||
[[nodiscard]] constexpr auto operator()(
|
||||
R && r,
|
||||
parser_interface<Parser, GlobalState, ErrorHandler> const &
|
||||
@@ -296,7 +296,8 @@ namespace boost::parser {
|
||||
return (*this)(
|
||||
(R &&)r,
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
trace_mode);
|
||||
}
|
||||
|
||||
@@ -307,8 +308,8 @@ namespace boost::parser {
|
||||
typename Parser,
|
||||
typename GlobalState,
|
||||
typename ErrorHandler,
|
||||
typename SkipParser =
|
||||
parser_interface<eps_parser<detail::phony>>,
|
||||
typename SkipParser = parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>,
|
||||
typename Trace = trace,
|
||||
typename Enable = std::enable_if_t<is_parsable_range_v<R>>>
|
||||
[[nodiscard]] constexpr auto operator()(
|
||||
@@ -324,9 +325,10 @@ namespace boost::parser {
|
||||
std::is_same_v<Trace, trace>) {
|
||||
// (r, parser, trace) case
|
||||
return impl(
|
||||
(R &&) r,
|
||||
(R &&)r,
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
skip);
|
||||
} else if constexpr (
|
||||
detail::is_parser_iface<SkipParser> &&
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
#include <boost/parser/replace.hpp>
|
||||
|
||||
#if (!defined(_MSC_VER) || BOOST_PARSER_USE_CONCEPTS) && \
|
||||
(!defined(BOOST_PARSER_GCC) || 12 <= __GNUC__ || \
|
||||
!BOOST_PARSER_USE_CONCEPTS)
|
||||
(!defined(__GNUC__) || 12 <= __GNUC__ || !BOOST_PARSER_USE_CONCEPTS)
|
||||
|
||||
|
||||
namespace boost::parser {
|
||||
@@ -255,7 +254,9 @@ namespace boost::parser {
|
||||
BOOST_PARSER_SUBRANGE(first, first), parse_result{});
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<SkipParser, eps_parser<phony>>) {
|
||||
if constexpr (std::is_same_v<
|
||||
SkipParser,
|
||||
eps_parser<phony, parser_modifiers<>>>) {
|
||||
auto result = parser::prefix_parse(
|
||||
first, last, search_parser, trace_mode);
|
||||
if (*result) {
|
||||
@@ -579,7 +580,7 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>>;
|
||||
|
||||
template<
|
||||
typename V,
|
||||
@@ -595,7 +596,7 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
parser_interface<eps_parser<detail::phony, parser_modifiers<>>>>;
|
||||
|
||||
namespace detail {
|
||||
template<
|
||||
@@ -698,7 +699,8 @@ namespace boost::parser {
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>>
|
||||
[[nodiscard]] constexpr auto operator()(
|
||||
R && r,
|
||||
parser_interface<Parser, GlobalState, ErrorHandler> const &
|
||||
@@ -709,7 +711,8 @@ namespace boost::parser {
|
||||
return (*this)(
|
||||
(R &&)r,
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
(F &&)f,
|
||||
trace_mode);
|
||||
}
|
||||
@@ -754,10 +757,11 @@ namespace boost::parser {
|
||||
std::is_same_v<Trace, trace>) {
|
||||
// (r, parser, f, trace) case
|
||||
return impl(
|
||||
to_range<R>::call((R &&) r),
|
||||
to_range<R>::call((R &&)r),
|
||||
parser,
|
||||
parser_interface<eps_parser<detail::phony>>{},
|
||||
(SkipParser &&) skip,
|
||||
parser_interface<
|
||||
eps_parser<detail::phony, parser_modifiers<>>>{},
|
||||
(SkipParser &&)skip,
|
||||
f);
|
||||
} else {
|
||||
static_assert(
|
||||
|
||||
@@ -185,10 +185,14 @@ namespace boost { namespace parser {
|
||||
template<typename T>
|
||||
operator T() const && noexcept
|
||||
{
|
||||
#if defined(__GNUC__) && __GNUC__ < 13
|
||||
// Yuck.
|
||||
std::remove_reference_t<T> * ptr = nullptr;
|
||||
ptr += 1; // warning mitigation
|
||||
return *ptr;
|
||||
#else
|
||||
return std::declval<T>();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -237,27 +237,6 @@ void github_issue_125()
|
||||
}
|
||||
}
|
||||
|
||||
void github_issue_209()
|
||||
{
|
||||
namespace bp = boost::parser;
|
||||
|
||||
BOOST_TEST(std::is_sorted(
|
||||
std::begin(bp::detail::char_set<detail::punct_chars>::chars),
|
||||
std::end(bp::detail::char_set<detail::punct_chars>::chars)));
|
||||
|
||||
BOOST_TEST(std::is_sorted(
|
||||
std::begin(bp::detail::char_set<detail::symb_chars>::chars),
|
||||
std::end(bp::detail::char_set<detail::symb_chars>::chars)));
|
||||
|
||||
BOOST_TEST(std::is_sorted(
|
||||
std::begin(bp::detail::char_set<detail::lower_case_chars>::chars),
|
||||
std::end(bp::detail::char_set<detail::lower_case_chars>::chars)));
|
||||
|
||||
BOOST_TEST(std::is_sorted(
|
||||
std::begin(bp::detail::char_set<detail::upper_case_chars>::chars),
|
||||
std::end(bp::detail::char_set<detail::upper_case_chars>::chars)));
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -267,6 +246,5 @@ int main()
|
||||
github_issue_78();
|
||||
github_issue_90();
|
||||
github_issue_125();
|
||||
github_issue_209();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ constexpr auto double_s = u8"sS"; // U+0073 U+0073
|
||||
|
||||
// basic)
|
||||
{
|
||||
constexpr auto char_p = no_case[char_('a') | char_('B')];
|
||||
auto char_p = no_case[char_('a') | char_('B')];
|
||||
|
||||
{
|
||||
auto const result = parse("a", char_p);
|
||||
@@ -461,12 +461,12 @@ constexpr auto double_s = u8"sS"; // U+0073 U+0073
|
||||
{
|
||||
constexpr auto mixed_sharp_s1 = U"ẞs";
|
||||
constexpr auto mixed_sharp_s2 = U"sẞ";
|
||||
auto const result = detail::no_case_aware_string_mismatch(
|
||||
mixed_sharp_s1,
|
||||
detail::text::null_sentinel,
|
||||
mixed_sharp_s2,
|
||||
detail::text::null_sentinel,
|
||||
true);
|
||||
auto const result =
|
||||
detail::no_case_aware_string_mismatch<ignore_case_t::yes>(
|
||||
mixed_sharp_s1,
|
||||
detail::text::null_sentinel,
|
||||
mixed_sharp_s2,
|
||||
detail::text::null_sentinel);
|
||||
BOOST_TEST(result.first == detail::text::null_sentinel);
|
||||
BOOST_TEST(result.second == detail::text::null_sentinel);
|
||||
}
|
||||
|
||||
@@ -2753,16 +2753,6 @@ int main()
|
||||
BOOST_TEST(result == std::vector<uint32_t>({0x21, 0xfda}));
|
||||
}
|
||||
|
||||
// symb_
|
||||
{
|
||||
auto parser = +symb;
|
||||
|
||||
std::u32string str = U"$^\u20AC!\u2194\u220F\U0001D7C6b\u2280\U0001FACE\U0001039F";
|
||||
std::vector<uint32_t> result;
|
||||
BOOST_TEST(parse(str, parser, char_ - symb, result));
|
||||
BOOST_TEST(result == std::vector<uint32_t>({U'$', U'^', 0x20AC, 0x2194, 0x220F, 0x2280, 0x1FACE}));
|
||||
}
|
||||
|
||||
// lower_
|
||||
{
|
||||
auto parser = +lower;
|
||||
|
||||
@@ -88,66 +88,5 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
using namespace bp::literals;
|
||||
constexpr auto parser =
|
||||
bp::delimiter(','_l)[bp::int_ || bp::string("foo") || bp::char_('g')];
|
||||
|
||||
{
|
||||
auto result = bp::parse("42 foo g", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
result = bp::parse("42, foo ,g", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(
|
||||
*result ==
|
||||
(bp::tuple<int, std::string, double>(42, "foo"s, 'g')));
|
||||
}
|
||||
{
|
||||
auto result = bp::parse(",42, g, foo", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
result = bp::parse("42, g , foo", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(
|
||||
*result ==
|
||||
(bp::tuple<int, std::string, double>(42, "foo"s, 'g')));
|
||||
}
|
||||
{
|
||||
auto result = bp::parse("foo, 42, g,", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
result = bp::parse("foo, 42, g", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(
|
||||
*result ==
|
||||
(bp::tuple<int, std::string, double>(42, "foo"s, 'g')));
|
||||
}
|
||||
{
|
||||
auto result = bp::parse("foo g 42", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
result = bp::parse("foo, g, 42", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(
|
||||
*result ==
|
||||
(bp::tuple<int, std::string, double>(42, "foo"s, 'g')));
|
||||
}
|
||||
{
|
||||
auto result = bp::parse("g foo 42", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
result = bp::parse("g ,foo ,42", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(
|
||||
*result ==
|
||||
(bp::tuple<int, std::string, double>(42, "foo"s, 'g')));
|
||||
}
|
||||
{
|
||||
auto result = bp::parse("g 42 foo", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
result = bp::parse("g , 42 , foo", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(
|
||||
*result ==
|
||||
(bp::tuple<int, std::string, double>(42, "foo"s, 'g')));
|
||||
}
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
// different_quote
|
||||
// different_char
|
||||
{
|
||||
constexpr auto parser = bp::quoted_string('\'');
|
||||
|
||||
@@ -75,18 +75,9 @@ int main()
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(*result == "'foo'");
|
||||
}
|
||||
|
||||
{
|
||||
constexpr auto parser = bp::quoted_string('\'', bp::char_("g\t"));
|
||||
|
||||
auto result = bp::parse(R"('\'ggg\'')", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(*result == "'ggg'");
|
||||
BOOST_TEST(!bp::parse(R"('\'fff\'')", parser, bp::ws));
|
||||
}
|
||||
}
|
||||
|
||||
// different_quote_with_escapes
|
||||
// different_char_with_escapes
|
||||
{
|
||||
{
|
||||
auto parser = bp::quoted_string('\'', cu_escapes);
|
||||
@@ -128,58 +119,6 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
// different_quote_with_escapes_and_char_p
|
||||
{
|
||||
{
|
||||
auto parser = bp::quoted_string('\'', cu_escapes, bp::char_("g\t"));
|
||||
|
||||
{
|
||||
auto result = bp::parse("", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
}
|
||||
|
||||
{
|
||||
auto result = bp::parse("'ggg'", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
}
|
||||
|
||||
{
|
||||
auto result = bp::parse("'fff'", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
}
|
||||
|
||||
{
|
||||
auto result = bp::parse(R"('ggg\t')", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(*result == "ggg\t");
|
||||
}
|
||||
|
||||
{
|
||||
auto result = bp::parse(R"('ggg\g')", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto parser = bp::quoted_string('\'', cp_escapes);
|
||||
|
||||
{
|
||||
auto result = bp::parse("", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
}
|
||||
|
||||
{
|
||||
auto result = bp::parse(R"('\tggg')", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(*result == "\tggg");
|
||||
}
|
||||
|
||||
{
|
||||
auto result = bp::parse(R"('g\ggg')", parser, bp::ws);
|
||||
BOOST_TEST(!result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// char_set
|
||||
{
|
||||
constexpr auto parser = bp::quoted_string("'\"");
|
||||
@@ -232,15 +171,6 @@ int main()
|
||||
// character.
|
||||
BOOST_TEST(!bp::parse(R"("\'foo")", parser, bp::ws));
|
||||
}
|
||||
|
||||
{
|
||||
constexpr auto parser = bp::quoted_string("'\"", bp::char_("g"));
|
||||
|
||||
auto result = bp::parse(R"('\'ggg\'')", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(*result == "'ggg'");
|
||||
BOOST_TEST(!bp::parse(R"('\'fff\'')", parser, bp::ws));
|
||||
}
|
||||
}
|
||||
|
||||
// char_set_with_escapes
|
||||
@@ -303,15 +233,6 @@ int main()
|
||||
BOOST_TEST(!result);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto parser = bp::quoted_string("'\"", cu_escapes, bp::char_("g"));
|
||||
|
||||
auto result = bp::parse(R"('\'ggg\'')", parser, bp::ws);
|
||||
BOOST_TEST(result);
|
||||
BOOST_TEST(*result == "'ggg'");
|
||||
BOOST_TEST(!bp::parse(R"('\'fff\'')", parser, bp::ws));
|
||||
}
|
||||
}
|
||||
|
||||
// doc_examples
|
||||
@@ -358,16 +279,6 @@ int main()
|
||||
assert(result5);
|
||||
std::cout << *result5 << "\n"; // Prints (with a CRLF newline): some text
|
||||
//]
|
||||
|
||||
//[ quoted_string_example_6
|
||||
auto result6 = bp::parse(
|
||||
"'some text'", bp::quoted_string("'\"", bp::char_('g')), bp::ws);
|
||||
assert(!result6);
|
||||
result6 =
|
||||
bp::parse("'gggg'", bp::quoted_string("'\"", bp::char_('g')), bp::ws);
|
||||
assert(result6);
|
||||
std::cout << *result6 << "\n"; // Prints: gggg
|
||||
//]
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -144,7 +144,7 @@ int main()
|
||||
|
||||
std::cout << "\n\n"
|
||||
<< "----------------------------------------\n"
|
||||
<< "| transform)f_[] |\n"
|
||||
<< "| transform(f)[] |\n"
|
||||
<< "----------------------------------------\n";
|
||||
|
||||
auto f = [](auto x) { return x; };
|
||||
@@ -156,6 +156,8 @@ int main()
|
||||
<< "----------------------------------------\n";
|
||||
|
||||
PARSE(omit[char_]);
|
||||
PARSE(omit[omit[char_]]);
|
||||
PARSE(omit[*omit[char_]]);
|
||||
|
||||
std::cout << "\n\n"
|
||||
<< "----------------------------------------\n"
|
||||
@@ -188,6 +190,15 @@ int main()
|
||||
PARSE(skip[char_]);
|
||||
PARSE(skip(ws)[char_]);
|
||||
|
||||
std::cout << "\n\n"
|
||||
<< "----------------------------------------\n"
|
||||
<< "| no_case[] |\n"
|
||||
<< "----------------------------------------\n";
|
||||
|
||||
PARSE(no_case[char_]);
|
||||
PARSE(no_case[no_case[char_]]);
|
||||
PARSE(no_case[*no_case[char_]]);
|
||||
|
||||
std::cout << "\n\n"
|
||||
<< "----------------------------------------\n"
|
||||
<< "| merge[] |\n"
|
||||
@@ -218,6 +229,16 @@ int main()
|
||||
PARSE(!char_);
|
||||
PARSE(!(*char_ >> char_));
|
||||
|
||||
PARSE(!char_ >> char_);
|
||||
PARSE(*char_ >> !char_);
|
||||
PARSE(!char_ >> *char_ >> char_ >> !char_);
|
||||
try {
|
||||
PARSE((!char_) > char_);
|
||||
} catch (...) {
|
||||
}
|
||||
PARSE(*char_ > !char_);
|
||||
PARSE((!char_) > *char_ >> char_ > !char_);
|
||||
|
||||
std::cout << "\n\n"
|
||||
<< "----------------------------------------\n"
|
||||
<< "| operator& |\n"
|
||||
@@ -226,6 +247,16 @@ int main()
|
||||
PARSE(&char_);
|
||||
PARSE(&(*char_ >> char_));
|
||||
|
||||
PARSE(&char_ >> char_);
|
||||
PARSE(*char_ >> &char_);
|
||||
PARSE(&char_ >> *char_ >> char_ >> &char_);
|
||||
try {
|
||||
PARSE(&char_ > char_);
|
||||
} catch (...) {
|
||||
}
|
||||
PARSE(*char_ > &char_);
|
||||
PARSE(&char_ >>*char_ >> char_ > &char_);
|
||||
|
||||
std::cout << "\n\n"
|
||||
<< "----------------------------------------\n"
|
||||
<< "| symbols<T> |\n"
|
||||
|
||||
Reference in New Issue
Block a user