2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-20 04:42:22 +00:00

15 Commits

Author SHA1 Message Date
Zach Laine
88abb615aa Add pre_- and post_parser members to parser_modifiers; these are used as
look-ahead/-behind positive or negative assertions.

When combining parsers using op>> and op>, if either side is an expect_parser
and the other side has an open pre_-/post_parser slot, take the subparser out
of the expect_parser, and use it directly in the pre_-/post_parser slot.

See #160.
2024-12-16 19:24:39 -06:00
Zach Laine
54f8eecfe6 Change the no_case[] directive to use the parser_modifiers struct, like omit[]
does; remove no_case_parser.

See #160.
2024-12-16 19:24:39 -06:00
Zach Laine
fcd257abca Generalize with_parser_mods(), so that some functions can be recursive, and
others can be non-recursive.

See #160.
2024-12-16 19:24:39 -06:00
Zach Laine
2f7e5964a6 Apply the same sort of change as the previous two commits, but to all the
parsers not already modified.  Generalize with_parser_mods().  Remove
omit_parser, since it is now moot.

See #160.
2024-12-16 19:24:39 -06:00
Zach Laine
2fff00b3e1 Change string_parser to support the use of parser_modifiers, and change lit()
to return a parameterized string_parser instead of string_parser wrapped in an
omit_parser.

See #160.
2024-12-16 19:24:39 -06:00
Zach Laine
28e9b61735 Add a new template, parser_modifiers, that will hold common modifications to
parsers, like turning off attribute generation (replacing omit_parser).
Change char_parser to support the use of parser_modifiers, and change lit() to
return a parameterized char_parser instead of char_parser wrapped in an
omit_parser.

See #160.
2024-12-16 19:24:39 -06:00
Zach Laine
354586dd76 Github runner macos-12 -> macos-13. 2024-12-16 19:24:39 -06:00
Zach Laine
305bba875b Grooming. 2024-12-09 01:57:04 -06:00
Zach Laine
f468d529fe Fix stale comment in doc example. 2024-11-29 16:29:20 -06:00
Zach Laine
b5d4339f2c Fix semicolon-delimited bullet list in parsers table. 2024-11-29 16:29:13 -06:00
Zach Laine
6d7fa6f105 Add missing Docbook tag to fix broken reference in docs. 2024-11-29 16:20:14 -06:00
Mohammad Nejati
c975f57908 Add index.html
This redirects links pointing to the root directory to the documentation
page, such as:
https://www.boost.org/doc/libs/develop/libs/parser/
2024-11-27 20:10:11 -06:00
Zach Laine
063291b78c Correct the parser used in the second half of the "Parse Into a Class"
example.

Fixes #206.
2024-11-24 22:55:21 -06:00
Zach Laine
3eb827dcd6 Fix error in seq_parser::append() that causes AllowBacktracking=false to be treated as =true. 2024-11-14 22:49:51 -06:00
Zach Laine
6d796287b6 Disable the tests for in-Boost builds. 2024-11-13 20:54:34 -06:00
24 changed files with 4482 additions and 2789 deletions

View File

@@ -1,4 +1,4 @@
name: macos-12 - Clang 14
name: macos-13 - Clang 14
on:
push:
@@ -16,7 +16,7 @@ jobs:
matrix:
cxx_std: [17]
runs-on: macos-12
runs-on: macos-13
steps:
- uses: actions/checkout@v4

View File

@@ -22,12 +22,6 @@ target_link_libraries(boost_parser
Boost::type_index
)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()
else()
cmake_minimum_required(VERSION 3.14...3.20)

View File

@@ -34,9 +34,9 @@ itself be used as a parser; it must be called. In the table below:
* `a` is a semantic action;
* `r` is an object whose type models `parsable_range`; and
* `r` is an object whose type models `parsable_range`;
* `p`, `p1`, `p2`, ... are parsers.
* `p`, `p1`, `p2`, ... are parsers; and
* `escapes` is a _symbols_t_ object, where `T` is `char` or `char32_t`.

View File

@@ -351,7 +351,7 @@ so this directive is only available in C++20 and later.
namespace bp = boost::parser;
auto int_parser = bp::int_ % ','; // ATTR(int_parser) is std::vector<int>
auto sv_parser = bp::string_view[int_parser]; // ATTR(subrange_parser) is a string_view
auto sv_parser = bp::string_view[int_parser]; // ATTR(sv_parser) is a string_view
auto const str = std::string("1, 2, 3, 4, a, b, c");
auto first = str.begin();

View File

@@ -33,7 +33,7 @@ int main()
std::cout << input << "\n";
//[ parsing_into_a_class_vec_of_strs
constexpr auto uint_string = bp::uint_ >> bp::char_ >> bp::char_;
constexpr auto uint_string = bp::uint_ >> +bp::char_;
std::vector<std::string> vector_from_parse;
if (parse(input, uint_string, bp::ws, vector_from_parse)) {
std::cout << "That yields this vector of strings:\n";

View File

@@ -31,9 +31,11 @@ namespace boost { namespace parser {
std::forward_iterator<T> && code_unit<std::iter_value_t<T>>;
//[ parsable_range_like_concept
//[ parsable_range_concept
template<typename T>
concept parsable_range = std::ranges::forward_range<T> &&
code_unit<std::ranges::range_value_t<T>>;
//]
template<typename T>
concept parsable_pointer = std::is_pointer_v<std::remove_cvref_t<T>> &&

View File

@@ -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>
void print_parser(
template<typename Context, typename ParserTuple, typename ParserMods>
void print_parser_impl(
Context const & context,
perm_parser<ParserTuple> 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,143 +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<lower_case_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<upper_case_chars> const & parser,
char_set_parser<upper_case_chars, 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 StrIter,
typename StrSentinel,
typename ParserMods>
void print_parser_impl(
Context const & context,
omit_parser<char_parser<Expected, AttributeType>> const & parser,
string_parser<StrIter, StrSentinel, ParserMods> const & parser,
std::ostream & os,
int components = 0);
int components);
template<typename Context, typename StrIter, typename StrSentinel>
void print_parser(
template<
typename Context,
typename Quotes,
typename Escapes,
typename ParserMods>
void print_parser_impl(
Context const & context,
string_parser<StrIter, StrSentinel> const & parser,
quoted_string_parser<Quotes, Escapes, ParserMods> const & parser,
std::ostream & os,
int components = 0);
int components);
template<typename Context, typename StrIter, typename StrSentinel>
void print_parser(
template<
typename Context,
bool NewlinesOnly,
bool NoNewlines,
typename ParserMods>
void print_parser_impl(
Context const & context,
omit_parser<string_parser<StrIter, StrSentinel>> const & parser,
ws_parser<NewlinesOnly, NoNewlines, ParserMods> const & parser,
std::ostream & os,
int components = 0);
int components);
template<typename Context, typename Quotes, typename Escapes>
void print_parser(
template<typename Context, typename ParserMods>
void print_parser_impl(
Context const & context,
quoted_string_parser<Quotes, Escapes> const & parser,
bool_parser<ParserMods> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, bool NewlinesOnly, bool NoNewlines>
void print_parser(
Context const & context,
ws_parser<NewlinesOnly, NoNewlines> const & parser,
std::ostream & os,
int components = 0);
template<typename Context>
void print_parser(
Context const & context,
bool_parser const & parser,
std::ostream & os,
int components = 0);
int components);
template<
typename Context,
@@ -307,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,
@@ -320,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);

View File

@@ -43,36 +43,44 @@ namespace boost { namespace parser { namespace detail {
typename Parser,
typename DelimiterParser,
typename MinType,
typename MaxType>
typename MaxType,
typename ParserMods>
struct n_aray_parser<
repeat_parser<Parser, DelimiterParser, MinType, MaxType>>
repeat_parser<Parser, DelimiterParser, MinType, MaxType, ParserMods>>
: std::true_type
{};
template<typename Parser, typename MinType, typename MaxType>
struct n_aray_parser<repeat_parser<Parser, detail::nope, MinType, MaxType>>
template<
typename Parser,
typename MinType,
typename MaxType,
typename ParserMods>
struct n_aray_parser<
repeat_parser<Parser, detail::nope, MinType, MaxType, ParserMods>>
: std::false_type
{};
template<typename Parser, typename DelimiterParser>
struct n_aray_parser<delimited_seq_parser<Parser, DelimiterParser>>
template<typename Parser, typename DelimiterParser, typename ParserMods>
struct n_aray_parser<
delimited_seq_parser<Parser, DelimiterParser, ParserMods>>
: std::true_type
{};
template<typename ParserTuple>
struct n_aray_parser<or_parser<ParserTuple>> : std::true_type
template<typename ParserTuple, typename ParserMods>
struct n_aray_parser<or_parser<ParserTuple, ParserMods>> : std::true_type
{};
template<typename ParserTuple>
struct n_aray_parser<perm_parser<ParserTuple>> : std::true_type
template<typename ParserTuple, typename ParserMods>
struct n_aray_parser<perm_parser<ParserTuple, ParserMods>> : std::true_type
{};
template<
typename ParserTuple,
typename BacktrackingTuple,
typename CombiningGroups>
typename CombiningGroups,
typename ParserMods>
struct n_aray_parser<
seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups>>
seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups, ParserMods>>
: std::true_type
{};
@@ -101,10 +109,16 @@ 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)
{
@@ -116,7 +130,7 @@ namespace boost { namespace parser { namespace detail {
os << "*";
if (n_ary_child)
os << "(";
detail::print_parser(
detail::print_parser_impl(
context, parser.parser_, os, components + 1);
if (n_ary_child)
os << ")";
@@ -124,7 +138,7 @@ namespace boost { namespace parser { namespace detail {
os << "+";
if (n_ary_child)
os << "(";
detail::print_parser(
detail::print_parser_impl(
context, parser.parser_, os, components + 1);
if (n_ary_child)
os << ")";
@@ -141,22 +155,22 @@ namespace boost { namespace parser { namespace detail {
detail::print(os, max_);
os << ")[";
}
detail::print_parser(
detail::print_parser_impl(
context, parser.parser_, os, components + 1);
os << "]";
}
} else {
detail::print_parser(context, parser.parser_, os, components + 1);
detail::print_parser_impl(context, parser.parser_, os, components + 1);
os << " % ";
detail::print_parser(
detail::print_parser_impl(
context, parser.delimiter_parser_, os, components + 2);
}
}
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)
{
@@ -164,7 +178,7 @@ namespace boost { namespace parser { namespace detail {
constexpr bool n_ary_child = n_aray_parser_v<Parser>;
if (n_ary_child)
os << "(";
detail::print_parser(context, parser.parser_, os, components + 1);
detail::print_parser_impl(context, parser.parser_, os, components + 1);
if (n_ary_child)
os << ")";
}
@@ -189,16 +203,16 @@ namespace boost { namespace parser { namespace detail {
}
if (i)
os << ws_or;
detail::print_parser(context, parser, os, components);
detail::print_parser_impl(context, parser, os, components);
++components;
++i;
});
}
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)
{
@@ -206,10 +220,10 @@ namespace boost { namespace parser { namespace detail {
context, parser, os, components, " | ...", " | ");
}
template<typename Context, typename ParserTuple>
void print_parser(
template<typename Context, typename ParserTuple, typename ParserMods>
void print_parser_impl(
Context const & context,
perm_parser<ParserTuple> const & parser,
perm_parser<ParserTuple, ParserMods> const & parser,
std::ostream & os,
int components)
{
@@ -221,11 +235,15 @@ namespace boost { namespace parser { namespace detail {
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)
{
@@ -264,14 +282,18 @@ namespace boost { namespace parser { namespace detail {
os << ']';
}
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)
{
detail::print_parser(context, parser.parser_, os, components);
detail::print_parser_impl(context, parser.parser_, os, components);
os << "[<<action>>]";
}
@@ -287,14 +309,14 @@ namespace boost { namespace parser { namespace detail {
if (++components == parser_component_limit)
os << "...";
else
detail::print_parser(context, parser, os, components + 1);
detail::print_parser_impl(context, parser, os, components + 1);
os << "]";
}
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)
{
@@ -302,21 +324,10 @@ namespace boost { namespace parser { namespace detail {
context, "transform(<<f>>)", parser.parser_, os, 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,
std::ostream & os,
int components)
{
detail::print_directive(
context, "omit", parser.parser_, os, components);
}
template<typename Context, typename Parser>
void print_parser(
Context const & context,
raw_parser<Parser> const & parser,
raw_parser<Parser, ParserMods> const & parser,
std::ostream & os,
int components)
{
@@ -324,10 +335,10 @@ namespace boost { namespace parser { namespace detail {
}
#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)
{
@@ -336,10 +347,10 @@ namespace boost { namespace parser { namespace detail {
}
#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)
{
@@ -347,21 +358,14 @@ namespace boost { namespace parser { namespace detail {
context, "lexeme", parser.parser_, os, 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,
std::ostream & os,
int components)
{
detail::print_directive(
context, "no_case", parser.parser_, os, components);
}
template<typename Context, typename Parser, typename SkipParser>
void print_parser(
Context const & context,
skip_parser<Parser, SkipParser> const & parser,
skip_parser<Parser, SkipParser, ParserMods> const & parser,
std::ostream & os,
int components)
{
@@ -370,7 +374,7 @@ namespace boost { namespace parser { namespace detail {
context, "skip", parser.parser_, os, components);
} else {
os << "skip(";
detail::print_parser(
detail::print_parser_impl(
context, parser.skip_parser_.parser_, os, components);
os << ")";
detail::print_directive(
@@ -378,21 +382,25 @@ namespace boost { namespace parser { namespace detail {
}
}
template<typename Context, typename Parser, bool FailOnMatch>
void print_parser(
template<
typename Context,
typename Parser,
expect_match_t ExpectMatch,
typename ParserMods>
void print_parser_impl(
Context const & context,
expect_parser<Parser, FailOnMatch> const & parser,
expect_parser<Parser, ExpectMatch, ParserMods> const & parser,
std::ostream & os,
int components)
{
if (FailOnMatch)
os << "!";
else
if constexpr (ExpectMatch == expect_match_t::yes)
os << "&";
else
os << "!";
constexpr bool n_ary_child = n_aray_parser_v<Parser>;
if (n_ary_child)
os << "(";
detail::print_parser(context, parser.parser_, os, components + 1);
detail::print_parser_impl(context, parser.parser_, os, components + 1);
if (n_ary_child)
os << ")";
}
@@ -403,15 +411,17 @@ 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)
{
@@ -428,10 +438,10 @@ namespace boost { namespace parser { namespace detail {
}
}
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)
{
@@ -441,40 +451,40 @@ namespace boost { namespace parser { namespace detail {
os << parser.diagnostic_text_;
}
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)
{
os << "eps(<<pred>>)";
}
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)
{
os << "eps";
}
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)
{
os << "eoi";
}
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)
{
@@ -527,7 +537,7 @@ namespace boost { namespace parser { namespace detail {
}
template<typename Context, typename T>
struct char_print_parser_impl
struct char_print_parser_impl_impl
{
static void call(Context const & context, std::ostream & os, T expected)
{
@@ -536,7 +546,7 @@ namespace boost { namespace parser { namespace detail {
};
template<typename Context, typename T, typename U>
struct char_print_parser_impl<Context, char_pair<T, U>>
struct char_print_parser_impl_impl<Context, char_pair<T, U>>
{
static void call(
Context const & context,
@@ -550,7 +560,7 @@ namespace boost { namespace parser { namespace detail {
};
template<typename Context, typename Iter, typename Sentinel, bool B>
struct char_print_parser_impl<Context, char_range<Iter, Sentinel, B>>
struct char_print_parser_impl_impl<Context, char_range<Iter, Sentinel, B>>
{
static void call(
Context const & context,
@@ -566,139 +576,134 @@ namespace boost { namespace parser { namespace detail {
}
};
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)
{
if (std::is_same_v<AttributeType, uint32_t>)
os << "cp";
else if (std::is_same_v<AttributeType, char>)
os << "cu";
else
os << "char_";
if constexpr (!is_nope_v<Expected>) {
os << "(";
char_print_parser_impl<Context, Expected>::call(
context, os, parser.expected_);
os << ")";
if constexpr (parser.mods_.omit_attr == parser::omit_attr_t::yes) {
if constexpr (is_nope_v<Expected>) {
os << "char_";
} else {
char_print_parser_impl_impl<Context, Expected>::call(
context, os, parser.expected_);
}
} else {
if (std::is_same_v<AttributeType, uint32_t>)
os << "cp";
else if (std::is_same_v<AttributeType, char>)
os << "cu";
else
os << "char_";
if constexpr (!is_nope_v<Expected>) {
os << "(";
char_print_parser_impl_impl<Context, Expected>::call(
context, os, parser.expected_);
os << ")";
}
}
}
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)
{
os << "digit";
}
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)
{
os << "hex_digit";
}
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)
{
os << "control";
}
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)
{
os << "punct";
}
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<lower_case_chars, ParserMods> const & parser,
std::ostream & os,
int components)
{
os << "lower";
}
template<typename Context>
void print_parser(
template<typename Context, typename ParserMods>
void print_parser_impl(
Context const & context,
char_set_parser<upper_case_chars> const & parser,
char_set_parser<upper_case_chars, ParserMods> const & parser,
std::ostream & os,
int components)
{
os << "upper";
}
template<typename Context, typename Expected, typename AttributeType>
void print_parser(
template<
typename Context,
typename StrIter,
typename StrSentinel,
typename ParserMods>
void print_parser_impl(
Context const & context,
omit_parser<char_parser<Expected, AttributeType>> const & parser,
string_parser<StrIter, StrSentinel, ParserMods> const & parser,
std::ostream & os,
int components)
{
if constexpr (is_nope_v<Expected>) {
os << "omit[char_]";
} else {
char_print_parser_impl<Context, Expected>::call(
context, os, parser.parser_.expected_);
if constexpr (parser.mods_.omit_attr == parser::omit_attr_t::no) {
os << "string(";
}
}
template<typename Context, typename StrIter, typename StrSentinel>
void print_parser(
Context const & context,
string_parser<StrIter, StrSentinel> const & parser,
std::ostream & os,
int components)
{
os << "string(\"";
os << "\"";
for (auto c : BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
parser.expected_first_, parser.expected_last_) |
text::as_utf8) {
detail::print_char(os, c);
}
os << "\")";
}
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)
{
os << "\"";
for (auto c : BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
parser.parser_.expected_first_,
parser.parser_.expected_last_) |
text::as_utf8) {
detail::print_char(os, c);
if constexpr (parser.mods_.omit_attr == parser::omit_attr_t::no) {
os << ")";
}
os << "\"";
}
template<typename Context, typename Quotes, typename Escapes>
void print_parser(
template<
typename Context,
typename Quotes,
typename Escapes,
typename ParserMods>
void print_parser_impl(
Context const & context,
quoted_string_parser<Quotes, Escapes> const & parser,
quoted_string_parser<Quotes, Escapes, ParserMods> const & parser,
std::ostream & os,
int components)
{
@@ -716,10 +721,14 @@ namespace boost { namespace parser { namespace detail {
os << ')';
}
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)
{
@@ -731,10 +740,10 @@ namespace boost { namespace parser { namespace detail {
os << "ws";
}
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)
{
@@ -747,10 +756,17 @@ 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)
{
@@ -791,27 +807,29 @@ 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)
{
if (Radix == 10 && MinDigits == 1 && MaxDigits == -1) {
if (std::is_same_v<T, short>) {
if constexpr (std::is_same_v<T, short>) {
os << "short_";
detail::print_expected(context, os, parser.expected_);
return;
} else if (std::is_same_v<T, int>) {
} else if constexpr (std::is_same_v<T, int>) {
os << "int_";
detail::print_expected(context, os, parser.expected_);
return;
} else if (std::is_same_v<T, long>) {
} else if constexpr (std::is_same_v<T, long>) {
os << "long_";
detail::print_expected(context, os, parser.expected_);
return;
} else if (std::is_same_v<T, long long>) {
} else if constexpr (std::is_same_v<T, long long>) {
os << "long_long";
detail::print_expected(context, os, parser.expected_);
return;
@@ -821,61 +839,31 @@ namespace boost { namespace parser { namespace detail {
<< MinDigits << ", " << MaxDigits << ">";
detail::print_expected(context, os, parser.expected_);
}
template<typename Context>
void print_parser(
template<typename Context, typename T, typename ParserMods>
void print_parser_impl(
Context const & context,
int_parser<short> const & parser,
std::ostream & os,
int components)
{
os << "short_";
}
template<typename Context>
void print_parser(
Context const & context,
int_parser<long> const & parser,
std::ostream & os,
int components)
{
os << "long_";
}
template<typename Context>
void print_parser(
Context const & context,
int_parser<long long> const & parser,
std::ostream & os,
int components)
{
os << "long_long";
}
template<typename Context, typename T>
void print_parser(
Context const & context,
float_parser<T> const & parser,
float_parser<T, ParserMods> const & parser,
std::ostream & os,
int components)
{
os << "float<" << detail::type_name<T>() << ">";
}
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)
{
os << "float_";
}
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)
{
@@ -886,10 +874,11 @@ namespace boost { namespace parser { namespace detail {
typename Context,
typename ParserTuple,
typename BacktrackingTuple,
typename CombiningGroups>
typename CombiningGroups,
typename ParserMods>
void print_switch_matchers(
Context const & context,
seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups, ParserMods> const &
parser,
std::ostream & os,
int components)
@@ -901,15 +890,15 @@ namespace boost { namespace parser { namespace detail {
detail::resolve(
context, parser::get(parser.parsers_, 0_c).pred_.value_));
os << ", ";
detail::print_parser(
detail::print_parser_impl(
context, parser::get(parser.parsers_, 1_c), os, components);
os << ")";
}
template<typename Context, typename ParserTuple>
template<typename Context, typename ParserTuple, typename ParserMods>
void print_switch_matchers(
Context const & context,
or_parser<ParserTuple> const & parser,
or_parser<ParserTuple, ParserMods> const & parser,
std::ostream & os,
int components)
{
@@ -928,10 +917,14 @@ namespace boost { namespace parser { namespace detail {
});
}
template<typename Context, typename SwitchValue, typename OrParser>
void print_parser(
template<
typename Context,
typename SwitchValue,
typename OrParser,
typename ParserMods>
void print_parser_impl(
Context const & context,
switch_parser<SwitchValue, OrParser> const & parser,
switch_parser<SwitchValue, OrParser, ParserMods> const & parser,
std::ostream & os,
int components)
{
@@ -942,6 +935,123 @@ namespace boost { namespace parser { namespace detail {
context, parser.or_parser_, os, components);
}
template<typename Context, typename Parser>
struct scoped_print_parser_mods
{
using parser_mods = decltype(std::declval<Parser>().mods_);
scoped_print_parser_mods(
Context const & context,
Parser const & parser,
std::ostream & os,
int & components,
bool suppress_omit) :
context_(context),
parser_(parser),
os_(os),
components_(components),
skip_omit_(suppress_omit)
{
if constexpr (parser_mods::omit_attr == parser::omit_attr_t::yes) {
if (!skip_omit_ && !skip_omit(parser_))
os_ << "omit[";
}
if constexpr (
parser_mods::ignore_case == parser::ignore_case_t::yes) {
os_ << "no_case[";
}
if constexpr (!is_nope_v<typename parser_mods::pre_parser_type>) {
print_expected_operator<
typename parser_mods::pre_parser_type>();
detail::print_parser<true>(
context_,
parser_.mods_.pre_parser.parser,
os_,
components_);
os_ << " >> ";
}
}
~scoped_print_parser_mods()
{
if constexpr (!is_nope_v<typename parser_mods::post_parser_type>) {
os_ << " >> ";
print_expected_operator<
typename parser_mods::post_parser_type>();
detail::print_parser<true>(
context_,
parser_.mods_.post_parser.parser,
os_,
components_);
}
if constexpr (
parser_mods::ignore_case == parser::ignore_case_t::yes) {
os_ << "]";
}
if constexpr (parser_mods::omit_attr == parser::omit_attr_t::yes) {
if (!skip_omit_ && !skip_omit(parser_))
os_ << "]";
}
}
template<typename ExpectedParser>
void print_expected_operator()
{
if constexpr (ExpectedParser::expect_match == expect_match_t::yes) {
os_ << "&";
} else {
os_ << "!";
}
}
template<typename T>
static bool skip_omit(T const &)
{
return false;
}
template<typename Expected, typename AttributeType, typename ParserMods>
static bool
skip_omit(char_parser<Expected, AttributeType, ParserMods> const &)
{
return !std::is_same_v<Expected, detail::nope>;
}
template<typename StrIter, typename StrSentinel, typename ParserMods>
static bool
skip_omit(string_parser<StrIter, StrSentinel, ParserMods> const &)
{
return true;
}
template<
typename Parser2,
expect_match_t ExpectMatch,
typename ParserMods>
static bool
skip_omit(expect_parser<Parser2, ExpectMatch, ParserMods> const &)
{
return true;
}
Context const & context_;
Parser const & parser_;
std::ostream & os_;
int & components_;
bool skip_omit_;
};
// TODO: Document how recursive directives like 'omit[]' and
// `no_case[]`will reappear for subparsers sometimes, as in
// omt[*omit[char_]] (see test/tracing.cpp).
template<bool SuppressOmit, typename Context, typename Parser>
void print_parser(
Context const & context,
Parser const & parser,
std::ostream & os,
int components)
{
scoped_print_parser_mods _(
context, parser, os, components, SuppressOmit);
detail::print_parser_impl(context, parser, os, components);
}
}}}
#endif

View File

@@ -47,11 +47,9 @@ namespace boost::parser::detail { namespace stl_interfaces {
`T`. */
template<typename T>
#if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS
// clang-format off
requires std::is_object_v<T>
#endif
struct proxy_arrow_result
// clang-format on
{
constexpr proxy_arrow_result(T const & value) noexcept(
noexcept(T(value))) :
@@ -619,33 +617,25 @@ namespace boost::parser::detail { namespace stl_interfaces { BOOST_PARSER_DETAIL
using iter_concept_t = typename iter_concept<Iterator>::type;
template<typename D, typename DifferenceType>
// clang-format off
concept plus_eq = requires (D d) { d += DifferenceType(1); };
// clang-format on
concept plus_eq = requires(D d) { d += DifferenceType(1); };
template<typename D, typename D2 = D>
// clang-format off
concept base_3way =
#if defined(__cpp_impl_three_way_comparison)
requires (D d, D2 d2) { access::base(d) <=> access::base(d2); };
requires(D d, D2 d2) { access::base(d) <=> access::base(d2); };
#else
false;
#endif
// clang-format on
template<typename D1, typename D2 = D1>
// clang-format off
concept base_eq =
requires (D1 d1, D2 d2) { access::base(d1) == access::base(d2); };
// clang-format on
requires(D1 d1, D2 d2) { access::base(d1) == access::base(d2); };
template<typename D, typename D2 = D>
// clang-format off
concept iter_sub = requires (D d, D2 d2) {
concept iter_sub = requires(D d, D2 d2) {
typename D::difference_type;
{d - d2} -> std::convertible_to<typename D::difference_type>;
{ d - d2 } -> std::convertible_to<typename D::difference_type>;
};
// clang-format on
// This iterator concept -> category mapping scheme follows the one
// from zip_transform_view; see

View File

@@ -328,23 +328,20 @@ namespace boost::parser::detail { namespace stl_interfaces {
{
constexpr adaptor(F f) : f_(f) {}
// clang-format off
template<typename... Args>
constexpr auto operator()(Args &&... args) const
// clang-format on
{
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
if constexpr (std::is_invocable_v<F const &, Args...>) {
return f_((Args &&) args...);
return f_((Args &&)args...);
} else {
return closure(
stl_interfaces::bind_back(f_, (Args &&) args...));
return closure(stl_interfaces::bind_back(f_, (Args &&)args...));
}
#else
return detail::adaptor_impl<
F const &,
detail::is_invocable_v<F const &, Args...>,
Args...>::call(f_, (Args &&) args...);
Args...>::call(f_, (Args &&)args...);
#endif
}

View File

@@ -97,17 +97,14 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
template<typename T>
concept grapheme_iter =
// clang-format off
std::input_iterator<T> &&
code_point_range<std::iter_reference_t<T>> &&
std::input_iterator<T> && code_point_range<std::iter_reference_t<T>> &&
requires(T t) {
{ t.base() } -> code_point_iter;
// clang-format on
};
{ t.base() } -> code_point_iter;
};
template<typename T>
concept grapheme_range = std::ranges::input_range<T> &&
grapheme_iter<std::ranges::iterator_t<T>>;
grapheme_iter<std::ranges::iterator_t<T>>;
template<typename R>
using code_point_iterator_t = decltype(std::declval<R>().begin().base());
@@ -116,75 +113,63 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
using code_point_sentinel_t = decltype(std::declval<R>().end().base());
template<typename T, format F>
concept grapheme_iter_code_unit =
// clang-format off
grapheme_iter<T> &&
requires(T t) {
concept grapheme_iter_code_unit = grapheme_iter<T> && requires(T t) {
{ t.base().base() } -> code_unit_iter<F>;
// clang-format on
};
template<typename T, format F>
concept grapheme_range_code_unit = grapheme_range<T> &&
concept grapheme_range_code_unit =
grapheme_range<T> &&
grapheme_iter_code_unit<std::ranges::iterator_t<T>, F>;
namespace dtl {
template<typename T, class CodeUnit>
concept eraseable_insertable_sized_bidi_range =
// clang-format off
std::ranges::sized_range<T> &&
std::ranges::input_range<T> &&
std::ranges::sized_range<T> && std::ranges::input_range<T> &&
requires(T t, CodeUnit const * it) {
{ t.erase(t.begin(), t.end()) } ->
std::same_as<std::ranges::iterator_t<T>>;
{ t.insert(t.end(), it, it) } ->
std::same_as<std::ranges::iterator_t<T>>;
{
t.erase(t.begin(), t.end())
} -> std::same_as<std::ranges::iterator_t<T>>;
{
t.insert(t.end(), it, it)
} -> std::same_as<std::ranges::iterator_t<T>>;
};
// clang-format on
}
template<typename T>
concept utf8_string =
// clang-format off
utf8_code_unit<std::ranges::range_value_t<T>> &&
dtl::eraseable_insertable_sized_bidi_range<
T, std::ranges::range_value_t<T>>;
// clang-format on
concept utf8_string = utf8_code_unit<std::ranges::range_value_t<T>> &&
dtl::eraseable_insertable_sized_bidi_range<
T,
std::ranges::range_value_t<T>>;
template<typename T>
concept utf16_string =
// clang-format off
utf16_code_unit<std::ranges::range_value_t<T>> &&
dtl::eraseable_insertable_sized_bidi_range<
T, std::ranges::range_value_t<T>>;
// clang-format on
concept utf16_string = utf16_code_unit<std::ranges::range_value_t<T>> &&
dtl::eraseable_insertable_sized_bidi_range<
T,
std::ranges::range_value_t<T>>;
template<typename T>
concept utf_string = utf8_string<T> || utf16_string<T>;
template<typename T>
// clang-format off
concept transcoding_error_handler = requires(T t, std::string_view msg) {
concept transcoding_error_handler = requires(T t, std::string_view msg) {
{ t(msg) } -> std::same_as<char32_t>;
// clang-format on
};
//]
// Clang 13 defines __cpp_lib_concepts but not std::indirectly copyable.
#if defined(__clang_major__) && __clang_major__ <= 13
template<typename In, typename Out>
// clang-format off
concept indirectly_copyable =
std::indirectly_readable<In> &&
std::indirectly_writable<Out, std::iter_reference_t<In>>;
// clang-format on
#else
template<typename In, typename Out>
concept indirectly_copyable = std::indirectly_copyable<In, Out>;
#endif
}}}
}
}}
#endif

View File

@@ -51,13 +51,10 @@ namespace boost::parser::detail { namespace text { namespace detail {
// that is comparable with T's interator type.
template<typename T>
concept cp_sentinel_gr_rng =
// clang-format off
grapheme_range<T> &&
!grapheme_iter<sentinel_t<T>> &&
grapheme_range<T> && !grapheme_iter<sentinel_t<T>> &&
requires(iterator_t<T> first, sentinel_t<T> last) {
{ first.base() == last } -> std::convertible_to<bool>;
// clang-format on
};
{ first.base() == last } -> std::convertible_to<bool>;
};
template<typename T>
using gr_rng_cp_iter_t = decltype(std::declval<iterator_t<T>>().base());

View File

@@ -2350,11 +2350,9 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
}
template<typename Cont>
// clang-format off
requires requires { typename Cont::value_type; } &&
utf_code_unit<typename Cont::value_type>
utf_code_unit<typename Cont::value_type>
constexpr auto from_utf8_inserter(Cont & c, typename Cont::iterator it)
// clang-format on
{
if constexpr (sizeof(typename Cont::value_type) == 1) {
return std::insert_iterator<Cont>(c, it);
@@ -2366,11 +2364,9 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
}
template<typename Cont>
// clang-format off
requires requires { typename Cont::value_type; } &&
utf_code_unit<typename Cont::value_type>
utf_code_unit<typename Cont::value_type>
constexpr auto from_utf16_inserter(Cont & c, typename Cont::iterator it)
// clang-format on
{
if constexpr (sizeof(typename Cont::value_type) == 1) {
return utf_16_to_8_insert_iterator<Cont>(c, it);
@@ -2382,11 +2378,9 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
}
template<typename Cont>
// clang-format off
requires requires { typename Cont::value_type; } &&
utf_code_unit<typename Cont::value_type>
utf_code_unit<typename Cont::value_type>
constexpr auto from_utf32_inserter(Cont & c, typename Cont::iterator it)
// clang-format on
{
if constexpr (sizeof(typename Cont::value_type) == 1) {
return utf_32_to_8_insert_iterator<Cont>(c, it);
@@ -2398,11 +2392,9 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
}
template<typename Cont>
// clang-format off
requires requires { typename Cont::value_type; } &&
utf_code_unit<typename Cont::value_type>
utf_code_unit<typename Cont::value_type>
constexpr auto from_utf8_back_inserter(Cont & c)
// clang-format on
{
if constexpr (sizeof(typename Cont::value_type) == 1) {
return std::back_insert_iterator<Cont>(c);
@@ -2414,11 +2406,9 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
}
template<typename Cont>
// clang-format off
requires requires { typename Cont::value_type; } &&
utf_code_unit<typename Cont::value_type>
utf_code_unit<typename Cont::value_type>
constexpr auto from_utf16_back_inserter(Cont & c)
// clang-format on
{
if constexpr (sizeof(typename Cont::value_type) == 1) {
return utf_16_to_8_back_insert_iterator<Cont>(c);
@@ -2430,11 +2420,9 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
}
template<typename Cont>
// clang-format off
requires requires { typename Cont::value_type; } &&
utf_code_unit<typename Cont::value_type>
utf_code_unit<typename Cont::value_type>
constexpr auto from_utf32_back_inserter(Cont & c)
// clang-format on
{
if constexpr (sizeof(typename Cont::value_type) == 1) {
return utf_32_to_8_back_insert_iterator<Cont>(c);
@@ -2446,11 +2434,9 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
}
template<typename Cont>
// clang-format off
requires requires { typename Cont::value_type; } &&
utf_code_unit<typename Cont::value_type>
utf_code_unit<typename Cont::value_type>
constexpr auto from_utf8_front_inserter(Cont & c)
// clang-format on
{
if constexpr (sizeof(typename Cont::value_type) == 1) {
return std::front_insert_iterator<Cont>(c);
@@ -2462,11 +2448,9 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
}
template<typename Cont>
// clang-format off
requires requires { typename Cont::value_type; } &&
utf_code_unit<typename Cont::value_type>
utf_code_unit<typename Cont::value_type>
constexpr auto from_utf16_front_inserter(Cont & c)
// clang-format on
{
if constexpr (sizeof(typename Cont::value_type) == 1) {
return utf_16_to_8_front_insert_iterator<Cont>(c);
@@ -2478,11 +2462,9 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
}
template<typename Cont>
// clang-format off
requires requires { typename Cont::value_type; } &&
utf_code_unit<typename Cont::value_type>
utf_code_unit<typename Cont::value_type>
constexpr auto from_utf32_front_inserter(Cont & c)
// clang-format on
{
if constexpr (sizeof(typename Cont::value_type) == 1) {
return utf_32_to_8_front_insert_iterator<Cont>(c);
@@ -2492,7 +2474,6 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
return std::front_insert_iterator<Cont>(c);
}
}
}}}
#endif

View File

@@ -423,49 +423,57 @@ namespace boost::parser::detail { namespace text {
#if defined(__cpp_char8_t)
inline constexpr detail::as_charn_impl<char8_view, format::utf8> as_char8_t;
#endif
inline constexpr detail::as_charn_impl<char16_view, format::utf16> as_char16_t;
inline constexpr detail::as_charn_impl<char32_view, format::utf32> as_char32_t;
inline constexpr detail::as_charn_impl<char16_view, format::utf16>
as_char16_t;
inline constexpr detail::as_charn_impl<char32_view, format::utf32>
as_char32_t;
// clang-format off
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<utf_range V>
requires std::ranges::view<V> && std::ranges::forward_range<V>
requires std::ranges::view<V> && std::ranges::forward_range<V>
#else
template<typename V>
#endif
class unpacking_view : public stl_interfaces::view_interface<unpacking_view<V>> {
V base_ = V();
class unpacking_view
: public stl_interfaces::view_interface<unpacking_view<V>>
{
V base_ = V();
public:
constexpr unpacking_view()
constexpr unpacking_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::default_initializable<V>
requires std::default_initializable<V>
#endif
= default;
constexpr unpacking_view(V base) : base_(std::move(base)) {}
= default;
constexpr unpacking_view(V base) : base_(std::move(base)) {}
constexpr V base() const &
constexpr V base() const &
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::copy_constructible<V>
requires std::copy_constructible<V>
#endif
{ return base_; }
constexpr V base() && { return std::move(base_); }
{
return base_;
}
constexpr V base() && { return std::move(base_); }
constexpr auto code_units() const noexcept {
auto unpacked = boost::parser::detail::text::unpack_iterator_and_sentinel(detail::begin(base_), detail::end(base_));
return BOOST_PARSER_DETAIL_TEXT_SUBRANGE(unpacked.first, unpacked.last);
}
constexpr auto code_units() const noexcept
{
auto unpacked =
boost::parser::detail::text::unpack_iterator_and_sentinel(
detail::begin(base_), detail::end(base_));
return BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
unpacked.first, unpacked.last);
}
constexpr auto begin() { return code_units().begin(); }
constexpr auto begin() const { return code_units().begin(); }
constexpr auto begin() { return code_units().begin(); }
constexpr auto begin() const { return code_units().begin(); }
constexpr auto end() { return code_units().end(); }
constexpr auto end() const { return code_units().end(); }
constexpr auto end() { return code_units().end(); }
constexpr auto end() const { return code_units().end(); }
};
template<class R>
unpacking_view(R &&) -> unpacking_view<detail::all_t<R>>;
// clang-format on
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<format Format, utf_range V>

File diff suppressed because it is too large Load Diff

View File

@@ -149,6 +149,35 @@ namespace boost { namespace parser {
{};
}
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`
@@ -159,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,
@@ -181,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
@@ -196,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
@@ -207,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>
template<typename ParserTuple, typename ParserMods>
struct perm_parser;
/** Applies each parser in `ParserTuple`, in order. The parse succeeds
@@ -220,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
@@ -235,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
@@ -262,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
@@ -298,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`.
@@ -317,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
@@ -349,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
@@ -357,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
@@ -365,22 +390,26 @@ 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
`std::string` attribute. */
template<typename Quotes = detail::nope, typename Escapes = detail::nope>
template<
typename Quotes = detail::nope,
typename Escapes = detail::nope,
typename ParserMods = parser_modifiers<>>
struct quoted_string_parser;
/** Matches an end-of-line (`NewlinesOnly == true`), whitespace
@@ -388,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`
@@ -406,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
@@ -420,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_`
@@ -433,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

View File

@@ -77,22 +77,16 @@ namespace boost::parser {
range_rvalue_reference_t<V2>>;
#if BOOST_PARSER_USE_CONCEPTS
// clang-format off
template<typename ReplacementV, typename V>
concept concatable = requires {
typename detail::concat_reference_t<ReplacementV, V>;
typename detail::concat_value_t<ReplacementV, V>;
typename detail::concat_rvalue_reference_t<ReplacementV, V>;
};
// clang-format on
#else
template<typename ReplacementV, typename V>
// clang-format off
using concatable_expr = decltype(
std::declval<concat_reference_t<ReplacementV, V>>(),
std::declval<concat_value_t<ReplacementV, V>>(),
std::declval<concat_rvalue_reference_t<ReplacementV, V>>());
// clang-format on
using concatable_expr =
decltype(std::declval<concat_reference_t<ReplacementV, V>>(), std::declval<concat_value_t<ReplacementV, V>>(), std::declval<concat_rvalue_reference_t<ReplacementV, V>>());
template<typename ReplacementV, typename V>
constexpr bool concatable =
is_detected_v<concatable_expr, ReplacementV, V>;
@@ -107,7 +101,7 @@ namespace boost::parser {
#endif
>
#if BOOST_PARSER_USE_CONCEPTS
requires concatable<V1, V2>
requires concatable<V1, V2>
#endif
struct either_iterator_impl
: detail::stl_interfaces::iterator_interface<
@@ -169,14 +163,12 @@ namespace boost::parser {
either_iterator_impl<V1, V2>>;
#if BOOST_PARSER_USE_CONCEPTS
// clang-format off
template<typename ReplacementV, typename V>
concept replacement_for = requires (ReplacementV replacement, V base) {
concept replacement_for = requires(ReplacementV replacement, V base) {
{ either_iterator<V, ReplacementV>(replacement.begin()) };
{ either_iterator<V, ReplacementV>(replacement.end()) };
{ either_iterator<V, ReplacementV>(base.begin()) };
};
// clang-format on
#else
template<typename ReplacementV, typename V>
using replacement_for_expr = decltype(
@@ -459,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,
@@ -477,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<
@@ -528,23 +520,19 @@ namespace boost::parser {
typename GlobalState,
typename ErrorHandler,
typename SkipParser>
requires
// clang-format off
std::ranges::viewable_range<R> &&
std::ranges::viewable_range<ReplacementR> &&
// clang-format on
can_replace_view<
to_range_t<R>,
decltype(to_range<
ReplacementR,
true,
detail::range_utf_format_v<R>>::
call(std::declval<ReplacementR>())),
Parser,
GlobalState,
ErrorHandler,
SkipParser>
// clang-format off
requires std::ranges::viewable_range<R> &&
std::ranges::viewable_range<ReplacementR> &&
can_replace_view<
to_range_t<R>,
decltype(to_range<
ReplacementR,
true,
detail::range_utf_format_v<R>>::
call(std::declval<ReplacementR>())),
Parser,
GlobalState,
ErrorHandler,
SkipParser>
[[nodiscard]] constexpr auto operator()(
R && r,
parser_interface<Parser, GlobalState, ErrorHandler> const &
@@ -552,10 +540,9 @@ namespace boost::parser {
parser_interface<SkipParser> const & skip,
ReplacementR && replacement,
trace trace_mode = trace::off) const
// clang-format on
{
return replace_view(
to_range<R>::call((R &&) r),
to_range<R>::call((R &&)r),
parser,
skip,
to_range<
@@ -572,36 +559,33 @@ namespace boost::parser {
typename Parser,
typename GlobalState,
typename ErrorHandler>
requires
// clang-format off
std::ranges::viewable_range<R> &&
std::ranges::viewable_range<ReplacementR> &&
// clang-format on
can_replace_view<
to_range_t<R>,
decltype(to_range<
ReplacementR,
true,
detail::range_utf_format_v<R>>::
call(std::declval<ReplacementR>())),
Parser,
GlobalState,
ErrorHandler,
parser_interface<eps_parser<detail::phony>>>
// clang-format off
requires std::ranges::viewable_range<R> &&
std::ranges::viewable_range<ReplacementR> &&
can_replace_view<
to_range_t<R>,
decltype(to_range<
ReplacementR,
true,
detail::range_utf_format_v<R>>::
call(std::declval<ReplacementR>())),
Parser,
GlobalState,
ErrorHandler,
parser_interface<
eps_parser<detail::phony, parser_modifiers<>>>>
[[nodiscard]] constexpr auto operator()(
R && r,
parser_interface<Parser, GlobalState, ErrorHandler> const &
parser,
ReplacementR && replacement,
trace trace_mode = trace::off) const
// clang-format on
{
return (*this)(
(R &&) r,
(R &&)r,
parser,
parser_interface<eps_parser<detail::phony>>{},
(ReplacementR &&) replacement,
parser_interface<
eps_parser<detail::phony, parser_modifiers<>>>{},
(ReplacementR &&)replacement,
trace_mode);
}
@@ -641,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(

View File

@@ -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<
@@ -541,25 +543,21 @@ namespace boost::parser {
typename GlobalState,
typename ErrorHandler,
typename SkipParser>
requires(
std::ranges::viewable_range<R>) &&
can_search_all_view<
to_range_t<R>,
Parser,
GlobalState,
ErrorHandler,
SkipParser>
// clang-format off
requires(std::ranges::viewable_range<R>) && can_search_all_view<
to_range_t<R>,
Parser,
GlobalState,
ErrorHandler,
SkipParser>
[[nodiscard]] constexpr auto operator()(
R && r,
parser_interface<Parser, GlobalState, ErrorHandler> const &
parser,
parser_interface<SkipParser> const & skip,
trace trace_mode = trace::off) const
// clang-format on
{
return search_all_view(
to_range<R>::call((R &&) r), parser, skip, trace_mode);
to_range<R>::call((R &&)r), parser, skip, trace_mode);
}
template<
@@ -567,26 +565,25 @@ namespace boost::parser {
typename Parser,
typename GlobalState,
typename ErrorHandler>
requires(
std::ranges::viewable_range<R>) &&
can_search_all_view<
to_range_t<R>,
Parser,
GlobalState,
ErrorHandler,
parser_interface<eps_parser<detail::phony>>>
// clang-format off
requires(std::ranges::viewable_range<R>) &&
can_search_all_view<
to_range_t<R>,
Parser,
GlobalState,
ErrorHandler,
parser_interface<
eps_parser<detail::phony, parser_modifiers<>>>>
[[nodiscard]] constexpr auto operator()(
R && r,
parser_interface<Parser, GlobalState, ErrorHandler> const &
parser,
trace trace_mode = trace::off) const
// clang-format on
{
return (*this)(
(R &&) r,
(R &&)r,
parser,
parser_interface<eps_parser<detail::phony>>{},
parser_interface<
eps_parser<detail::phony, parser_modifiers<>>>{},
trace_mode);
}
@@ -597,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()(
@@ -614,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> &&

View File

@@ -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<
@@ -258,25 +257,21 @@ namespace boost::parser {
typename GlobalState,
typename ErrorHandler,
typename SkipParser>
requires(
std::ranges::viewable_range<R>) &&
can_split_view<
to_range_t<R>,
Parser,
GlobalState,
ErrorHandler,
SkipParser>
// clang-format off
requires(std::ranges::viewable_range<R>) && can_split_view<
to_range_t<R>,
Parser,
GlobalState,
ErrorHandler,
SkipParser>
[[nodiscard]] constexpr auto operator()(
R && r,
parser_interface<Parser, GlobalState, ErrorHandler> const &
parser,
parser_interface<SkipParser> const & skip,
trace trace_mode = trace::off) const
// clang-format on
{
return split_view(
to_range<R>::call((R &&) r), parser, skip, trace_mode);
to_range<R>::call((R &&)r), parser, skip, trace_mode);
}
template<
@@ -284,26 +279,25 @@ namespace boost::parser {
typename Parser,
typename GlobalState,
typename ErrorHandler>
requires(
std::ranges::viewable_range<R>) &&
can_split_view<
to_range_t<R>,
Parser,
GlobalState,
ErrorHandler,
parser_interface<eps_parser<detail::phony>>>
// clang-format off
requires(std::ranges::viewable_range<R>) &&
can_split_view<
to_range_t<R>,
Parser,
GlobalState,
ErrorHandler,
parser_interface<
eps_parser<detail::phony, parser_modifiers<>>>>
[[nodiscard]] constexpr auto operator()(
R && r,
parser_interface<Parser, GlobalState, ErrorHandler> const &
parser,
trace trace_mode = trace::off) const
// clang-format on
{
return (*this)(
(R &&) r,
(R &&)r,
parser,
parser_interface<eps_parser<detail::phony>>{},
parser_interface<
eps_parser<detail::phony, parser_modifiers<>>>{},
trace_mode);
}
@@ -314,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()(
@@ -331,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> &&

View File

@@ -28,16 +28,15 @@ namespace boost::parser {
using range_attr_t = attr_type<iterator_t<R>, sentinel_t<R>, Parser>;
#if BOOST_PARSER_USE_CONCEPTS
// clang-format off
template<typename F, typename V, typename Parser>
concept transform_replacement_for =
std::regular_invocable<F &, range_attr_t<V, Parser>> &&
detail::replacement_for<
std::invoke_result_t<F &, range_attr_t<V, Parser>>, V> &&
std::invoke_result_t<F &, range_attr_t<V, Parser>>,
V> &&
(detail::range_utf_format_v<V> ==
detail::range_utf_format_v<
std::invoke_result_t<F &, range_attr_t<V, Parser>>>);
// clang-format on
#else
template<typename F, typename V, typename Parser>
using transform_replacement_for_expr = decltype(std::declval<F &>()(
@@ -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<
@@ -646,24 +647,20 @@ namespace boost::parser {
typename GlobalState,
typename ErrorHandler,
typename SkipParser>
requires
// clang-format off
std::ranges::viewable_range<R> &&
std::regular_invocable<
F &,
range_attr_t<to_range_t<R>, Parser>> &&
// clang-format on
can_transform_replace_view<
to_range_t<R>,
utf_rvalue_shim<
to_range_t<R>,
std::remove_cvref_t<F>,
range_attr_t<to_range_t<R>, Parser>>,
Parser,
GlobalState,
ErrorHandler,
SkipParser>
// clang-format off
requires std::ranges::viewable_range<R> &&
std::regular_invocable<
F &,
range_attr_t<to_range_t<R>, Parser>> &&
can_transform_replace_view<
to_range_t<R>,
utf_rvalue_shim<
to_range_t<R>,
std::remove_cvref_t<F>,
range_attr_t<to_range_t<R>, Parser>>,
Parser,
GlobalState,
ErrorHandler,
SkipParser>
[[nodiscard]] constexpr auto operator()(
R && r,
parser_interface<Parser, GlobalState, ErrorHandler> const &
@@ -671,16 +668,15 @@ namespace boost::parser {
parser_interface<SkipParser> const & skip,
F && f,
trace trace_mode = trace::off) const
// clang-format on
{
return transform_replace_view(
to_range<R>::call((R &&) r),
to_range<R>::call((R &&)r),
parser,
skip,
utf_rvalue_shim<
to_range_t<R>,
std::remove_cvref_t<F>,
range_attr_t<to_range_t<R>, Parser>>((F &&) f),
range_attr_t<to_range_t<R>, Parser>>((F &&)f),
trace_mode);
}
@@ -690,37 +686,34 @@ namespace boost::parser {
typename Parser,
typename GlobalState,
typename ErrorHandler>
requires
// clang-format off
std::ranges::viewable_range<R> &&
std::regular_invocable<
F &,
range_attr_t<to_range_t<R>, Parser>> &&
// clang-format on
can_transform_replace_view<
to_range_t<R>,
utf_rvalue_shim<
to_range_t<R>,
std::remove_cvref_t<F>,
range_attr_t<to_range_t<R>, Parser>>,
Parser,
GlobalState,
ErrorHandler,
parser_interface<eps_parser<detail::phony>>>
// clang-format off
requires std::ranges::viewable_range<R> &&
std::regular_invocable<
F &,
range_attr_t<to_range_t<R>, Parser>> &&
can_transform_replace_view<
to_range_t<R>,
utf_rvalue_shim<
to_range_t<R>,
std::remove_cvref_t<F>,
range_attr_t<to_range_t<R>, Parser>>,
Parser,
GlobalState,
ErrorHandler,
parser_interface<
eps_parser<detail::phony, parser_modifiers<>>>>
[[nodiscard]] constexpr auto operator()(
R && r,
parser_interface<Parser, GlobalState, ErrorHandler> const &
parser,
F && f,
trace trace_mode = trace::off) const
// clang-format on
{
return (*this)(
(R &&) r,
(R &&)r,
parser,
parser_interface<eps_parser<detail::phony>>{},
(F &&) f,
parser_interface<
eps_parser<detail::phony, parser_modifiers<>>>{},
(F &&)f,
trace_mode);
}
@@ -764,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(

10
index.html Normal file
View File

@@ -0,0 +1,10 @@
<html>
<head>
<title>Boost.Parser</title>
<meta http-equiv="refresh" content="0; URL=../../doc/html/parser.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/parser.html">../../doc/html/parser.html</a>
</body>
</html>

View File

@@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@@ -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"