2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-20 16:52:13 +00:00

1 Commits

Author SHA1 Message Date
Zach Laine
390cd1dbe1 parser_config_WIP 2024-03-10 20:09:59 -05:00
4 changed files with 169 additions and 70 deletions

View File

@@ -148,10 +148,10 @@ namespace boost { namespace parser { namespace detail {
std::ostream & os, std::ostream & os,
int components = 0); int components = 0);
template<typename Context, typename Parser, bool FailOnMatch> template<typename Context, typename Parser, typename ParserConfig>
void print_parser( void print_parser(
Context const & context, Context const & context,
expect_parser<Parser, FailOnMatch> const & parser, expect_parser_t<Parser, ParserConfig> const & parser,
std::ostream & os, std::ostream & os,
int components = 0); int components = 0);

View File

@@ -378,14 +378,14 @@ namespace boost { namespace parser { namespace detail {
} }
} }
template<typename Context, typename Parser, bool FailOnMatch> template<typename Context, typename Parser, typename ParserConfig>
void print_parser( void print_parser(
Context const & context, Context const & context,
expect_parser<Parser, FailOnMatch> const & parser, expect_parser_t<Parser, ParserConfig> const & parser,
std::ostream & os, std::ostream & os,
int components) int components)
{ {
if (FailOnMatch) if (ParserConfig::fail_on_match)
os << "!"; os << "!";
else else
os << "&"; os << "&";

View File

@@ -2685,6 +2685,89 @@ namespace boost { namespace parser {
private: private:
T * x_; T * x_;
}; };
template<typename I, typename ParserConfig>
struct scoped_consume_input
{
scoped_consume_input(I & first, ParserConfig const &) :
first_copy_(first), first_(first)
{}
~scoped_consume_input()
{
if (ParserConfig::dont_consume_input)
first_ = first_copy_;
}
private:
I first_copy_;
I & first_;
};
template<typename ParserConfig>
struct scoped_fail_on_match
{
scoped_fail_on_match(bool & success, ParserConfig const &) :
success_(success)
{}
~scoped_fail_on_match()
{
if (ParserConfig::fail_on_match)
success_ = !success_;
}
private:
bool & success_;
};
// TODO: Tests for these.
template<
template<class, class>
typename ParserTmpl,
typename Parser,
typename OldConfig,
typename NewConfig>
constexpr auto with_config(
ParserTmpl<Parser, OldConfig> const & parser, NewConfig && config)
-> decltype(ParserTmpl<Parser, NewConfig>{
parser.parser_, (NewConfig &&) config})
{
return ParserTmpl<Parser, NewConfig>{
parser.parser_, (NewConfig &&) config};
}
template<
template<class, class>
typename ParserTmpl,
typename Parsers,
typename OldConfig,
typename NewConfig>
constexpr auto with_config(
ParserTmpl<Parser, OldConfig> const & parser, NewConfig && config)
-> decltype(ParserTmpl<Parser, NewConfig>{
parser.parsers_, (NewConfig &&) config})
{
return ParserTmpl<Parsers, NewConfig>{
parser.parsers_, (NewConfig &&) config};
}
template<
typename Parser,
typename DelimiterParser,
typename MinType,
typename MaxType,
typename OldConfig,
typename NewConfig>
constexpr auto with_config(
repeat_parser<Parser, OldConfig> const & parser,
NewConfig && config)
{
return repeat_parser<
Parser,
DelimiterParser,
MinType,
MaxType,
NewConfig>{parser.parser_, (NewConfig &&) config};
}
} }
#ifndef BOOST_PARSER_DOXYGEN #ifndef BOOST_PARSER_DOXYGEN
@@ -4855,8 +4938,8 @@ namespace boost { namespace parser {
SkipParser skip_parser_; SkipParser skip_parser_;
}; };
template<typename Parser, bool FailOnMatch> template<typename Parser, typename ParserConfig>
struct expect_parser struct expect_parser_t
{ {
template< template<
typename Iter, typename Iter,
@@ -4887,26 +4970,20 @@ namespace boost { namespace parser {
Sentinel last, Sentinel last,
Context const & context, Context const & context,
SkipParser const & skip, SkipParser const & skip,
detail::flags flags, detail::flags flags_,
bool & success, bool & success,
Attribute & retval) const Attribute & retval) const
{ {
[[maybe_unused]] auto _ = detail::scoped_trace( [[maybe_unused]] auto _ = detail::scoped_trace(
*this, first, last, context, flags, retval); *this, first, last, context, flags_, retval);
auto sci = detail::scoped_consume_input(first, config_);
auto first_copy = first; auto sfm = detail::scoped_fail_on_match(success, config_);
parser_.call( auto flags = ParserConfig::flags(flags_);
first_copy, parser_.call(first, last, context, skip, flags, success);
last,
context,
skip,
detail::disable_attrs(flags),
success);
if (FailOnMatch)
success = !success;
} }
Parser parser_; Parser parser_;
[[maybe_unused]] ParserConfig config_;
}; };
template<typename T> template<typename T>
@@ -5195,8 +5272,12 @@ namespace boost { namespace parser {
true`. */ true`. */
constexpr auto operator!() const noexcept constexpr auto operator!() const noexcept
{ {
return parser::parser_interface{ expect_parser_t<
expect_parser<parser_type, true>{parser_}}; parser_type,
detail::parser_config<true, true, false>>
ex_parser{parser_, {}};
return parser::parser_interface{detail::with_config(
ex_parser, detail::parser_config<true, true, true>{})};
} }
/** Returns a `parser_interface` containing a parser equivalent to an /** Returns a `parser_interface` containing a parser equivalent to an
@@ -5204,8 +5285,12 @@ namespace boost { namespace parser {
false`. */ false`. */
constexpr auto operator&() const noexcept constexpr auto operator&() const noexcept
{ {
return parser::parser_interface{ expect_parser_t<
expect_parser<parser_type, false>{parser_}}; parser_type,
detail::parser_config<true, true, true>>
ex_parser{parser_, {}};
return parser::parser_interface{detail::with_config(
ex_parser, detail::parser_config<true, true, false>{})};
} }
/** Returns a `parser_interface` containing a parser equivalent to a /** Returns a `parser_interface` containing a parser equivalent to a

View File

@@ -70,6 +70,7 @@ namespace boost { namespace parser {
trace = 1 << 2, trace = 1 << 2,
in_apply_parser = 1 << 3 in_apply_parser = 1 << 3
}; };
constexpr inline flags disable_attrs(flags f);
using symbol_table_tries_t = using symbol_table_tries_t =
std::map<void *, std::pair<std::any, bool>, std::less<void *>>; std::map<void *, std::pair<std::any, bool>, std::less<void *>>;
@@ -116,6 +117,25 @@ namespace boost { namespace parser {
{}; {};
struct upper_case_chars struct upper_case_chars
{}; {};
template<
bool OmitAttr = false,
bool DontConsumeInput = false,
bool FailOnMatch = false,
typename Action = nope>
struct parser_config
{
static constexpr bool omit = OmitAttr;
static constexpr bool dont_consume_input = DontConsumeInput;
static constexpr bool fail_on_match = FailOnMatch;
static constexpr detail::flags flags(detail::flags f)
{
return omit ? detail::disable_attrs(f) : f;
}
[[maybe_unused]] Action action_;
};
} }
/** Repeats the application of another parser `p` of type `Parser`, /** Repeats the application of another parser `p` of type `Parser`,
@@ -128,36 +148,15 @@ namespace boost { namespace parser {
typename Parser, typename Parser,
typename DelimiterParser = detail::nope, typename DelimiterParser = detail::nope,
typename MinType = int64_t, typename MinType = int64_t,
typename MaxType = int64_t> typename MaxType = int64_t,
typename ParserConfig = parser_config<>>
struct repeat_parser; 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>
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>
struct one_plus_parser;
/** Repeats the application of another parser `p` of type `Parser`, `[1,
Inf)` times, applying a parser `d` of type `DelimiterParser` in
between each pair of applications of `p`. The parse succeeds iff `p`
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>
struct delimited_seq_parser;
/** Repeats the application of another parser of type `Parser`, `[0, 1]` /** Repeats the application of another parser of type `Parser`, `[0, 1]`
times. The parse always succeeds. The attribute produced is a times. The parse always succeeds. The attribute produced is a
`std::optional<T>`, where `T` is the type of attribute produced by `std::optional<T>`, where `T` is the type of attribute produced by
`Parser`. */ `Parser`. */
template<typename Parser> template<typename Parser, typename ParserConfig = parser_config<>>
struct opt_parser; struct opt_parser;
/** Applies each parser in `ParserTuple`, in order, stopping after the /** Applies each parser in `ParserTuple`, in order, stopping after the
@@ -165,7 +164,7 @@ namespace boost { namespace parser {
one of the sub-parsers succeeds. The attribute produced is a one of the sub-parsers succeeds. The attribute produced is a
`std::variant` over the types of attribute produced by the parsers in `std::variant` over the types of attribute produced by the parsers in
`ParserTuple`. */ `ParserTuple`. */
template<typename ParserTuple> template<typename ParserTuple, typename ParserConfig = parser_config<>>
struct or_parser; struct or_parser;
/** Applies each parsers in `ParserTuple`, an any order, stopping after /** Applies each parsers in `ParserTuple`, an any order, stopping after
@@ -176,7 +175,7 @@ namespace boost { namespace parser {
`ParserTuple`, not the order of the parsers' matches. It is an error `ParserTuple`, not the order of the parsers' matches. It is an error
to specialize `perm_parser` with a `ParserTuple` template parameter to specialize `perm_parser` with a `ParserTuple` template parameter
that includes an `eps_parser`. */ that includes an `eps_parser`. */
template<typename ParserTuple> template<typename ParserTuple, typename ParserConfig = parser_config<>>
struct perm_parser; struct perm_parser;
/** Applies each parser in `ParserTuple`, in order. The parse succeeds /** Applies each parser in `ParserTuple`, in order. The parse succeeds
@@ -189,14 +188,18 @@ namespace boost { namespace parser {
template< template<
typename ParserTuple, typename ParserTuple,
typename BacktrackingTuple, typename BacktrackingTuple,
typename CombiningGroups> typename CombiningGroups,
typename ParserConfig = parser_config<>>
struct seq_parser; struct seq_parser;
/** Applies the given parser `p` of type `Parser` and an invocable `a` of /** Applies the given parser `p` of type `Parser` and an invocable `a` of
type `Action`. `Action` shall model `semantic_action`, and `a` will type `Action`. `Action` shall model `semantic_action`, and `a` will
only be invoked if `p` succeeds. The parse succeeds iff `p` succeeds. only be invoked if `p` succeeds. The parse succeeds iff `p` succeeds.
Produces no attribute. */ Produces no attribute. */
template<typename Parser, typename Action> template<
typename Parser,
typename Action,
typename ParserConfig = parser_config<>>
struct action_parser; struct action_parser;
/** Applies the given parser `p` of type `Parser`. The attribute produced /** Applies the given parser `p` of type `Parser`. The attribute produced
@@ -204,21 +207,24 @@ namespace boost { namespace parser {
only be invoked if `p` succeeds and sttributes are currently being only be invoked if `p` succeeds and sttributes are currently being
generated. The parse succeeds iff `p` succeeds. The attribute generated. The parse succeeds iff `p` succeeds. The attribute
produced is the the result of the call to `f`. */ produced is the the result of the call to `f`. */
template<typename Parser, typename F> template<
typename Parser,
typename F,
typename ParserConfig = parser_config<>>
struct transform_parser; struct transform_parser;
/** Applies the given parser `p` of type `Parser`. This parser produces /** Applies the given parser `p` of type `Parser`. This parser produces
no attribute, and suppresses the production of any attributes that no attribute, and suppresses the production of any attributes that
would otherwise be produced by `p`. The parse succeeds iff `p` would otherwise be produced by `p`. The parse succeeds iff `p`
succeeds. */ succeeds. */
template<typename Parser> template<typename Parser, typename ParserConfig = parser_config<>>
struct omit_parser; struct omit_parser;
/** Applies the given parser `p` of type `Parser`; regardless of the /** Applies the given parser `p` of type `Parser`; regardless of the
attribute produced by `Parser`, this parser's attribute is equivalent attribute produced by `Parser`, this parser's attribute is equivalent
to `_where(ctx)` within a semantic action on `p`. The parse succeeds to `_where(ctx)` within a semantic action on `p`. The parse succeeds
iff `p` succeeds. */ iff `p` succeeds. */
template<typename Parser> template<typename Parser, typename ParserConfig = parser_config<>>
struct raw_parser; struct raw_parser;
#if defined(BOOST_PARSER_DOXYGEN) || defined(__cpp_lib_concepts) #if defined(BOOST_PARSER_DOXYGEN) || defined(__cpp_lib_concepts)
@@ -231,43 +237,49 @@ namespace boost { namespace parser {
non-contiguous, code using `string_view_parser` is ill-formed. The non-contiguous, code using `string_view_parser` is ill-formed. The
parse succeeds iff `p` succeeds. This parser is only available in parse succeeds iff `p` succeeds. This parser is only available in
C++20 and later. */ C++20 and later. */
template<typename Parser> template<typename Parser, typename ParserConfig = parser_config<>>
struct string_view_parser; struct string_view_parser;
#endif #endif
/** Applies the given parser `p` of type `Parser`, disabling the current /** Applies the given parser `p` of type `Parser`, disabling the current
skipper in use, if any. The parse succeeds iff `p` succeeds. The skipper in use, if any. The parse succeeds iff `p` succeeds. The
attribute produced is the type of attribute produced by `Parser`. */ attribute produced is the type of attribute produced by `Parser`. */
template<typename Parser> template<typename Parser, typename ParserConfig = parser_config<>>
struct lexeme_parser; struct lexeme_parser;
/** Applies the given parser `p` of type `Parser`, enabling /** Applies the given parser `p` of type `Parser`, enabling
case-insensitive matching, based on Unicode case folding. The parse case-insensitive matching, based on Unicode case folding. The parse
succeeds iff `p` succeeds. The attribute produced is the type of succeeds iff `p` succeeds. The attribute produced is the type of
attribute produced by `Parser`. */ attribute produced by `Parser`. */
template<typename Parser> template<typename Parser, typename ParserConfig = parser_config<>>
struct no_case_parser; struct no_case_parser;
/** Applies the given parser `p` of type `Parser`, using a parser of type /** Applies the given parser `p` of type `Parser`, using a parser of type
`SkipParser` as the skipper. The parse succeeds iff `p` succeeds. `SkipParser` as the skipper. The parse succeeds iff `p` succeeds.
The attribute produced is the type of attribute produced by The attribute produced is the type of attribute produced by
`Parser`. */ `Parser`. */
template<typename Parser, typename SkipParser = detail::nope> template<
typename Parser,
typename SkipParser = detail::nope,
typename ParserConfig = parser_config<>>
struct skip_parser; struct skip_parser;
/** Applies the given parser `p` of type `Parser`, producing no attributes /** Applies the given parser `p` of type `Parser`, producing no attributes
and consuming no input. The parse succeeds iff `p`'s success is and consuming no input. The parse succeeds iff `p`'s success is
unequal to `FailOnMatch`. */ unequal to `FailOnMatch`. */
template<typename Parser, bool FailOnMatch> template<
typename Parser,
typename ParserConfig,
typename ParserConfig = parser_config<>>
struct expect_parser; struct expect_parser;
/** Matches one of a set S of possible inputs, each of which is associated /** Matches one of a set S of possible inputs, each of which is
with an attribute value of type `T`, forming a symbol table. New associated with an attribute value of type `T`, forming a symbol
elements and their associated attributes may be added to or removed table. New elements and their associated attributes may be added to
from S dynamically, during parsing; any such changes are reverted at or removed from S dynamically, during parsing; any such changes are
the end of parsing. The parse succeeds iff an element of S is reverted at the end of parsing. The parse succeeds iff an element of
matched. \see `symbols` */ S is matched. \see `symbols` */
template<typename T> template<typename T, typename ParserConfig = parser_config<>>
struct symbol_parser; struct symbol_parser;
/** Applies another parser `p`, associated with this parser via `TagType`. /** Applies another parser `p`, associated with this parser via `TagType`.
@@ -286,22 +298,24 @@ namespace boost { namespace parser {
typename TagType, typename TagType,
typename Attribute, typename Attribute,
typename LocalState, typename LocalState,
typename ParamsTuple> typename ParamsTuple,
typename ParserConfig = parser_config<>>
struct rule_parser; struct rule_parser;
/** Matches anything, and consumes no input. If `Predicate` is anything /** Matches anything, and consumes no input. If `Predicate` is anything
other than `detail::nope` (which it is by default), and `pred_(ctx)` other than `detail::nope` (which it is by default), and `pred_(ctx)`
evaluates to false, where `ctx` is the parser context, the parse evaluates to false, where `ctx` is the parser context, the parse
fails. */ fails. */
template<typename Predicate> template<typename Predicate, typename ParserConfig = parser_config<>>
struct eps_parser; struct eps_parser;
/** Matches only the end of input. Produces no attribute. */ /** Matches only the end of input. Produces no attribute. */
template<typename ParserConfig = parser_config<>>
struct eoi_parser; struct eoi_parser;
/** Matches anything, consumes no input, and produces an attribute of type /** Matches anything, consumes no input, and produces an attribute of type
`RESOLVE(Attribute)`. */ `RESOLVE(Attribute)`. */
template<typename Attribute> template<typename Attribute, typename ParserConfig = parser_config<>>
struct attr_parser; struct attr_parser;
/** A tag type that can be passed as the first parameter to `char_()` when /** A tag type that can be passed as the first parameter to `char_()` when