2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-24 06:02:12 +00:00

6 Commits

Author SHA1 Message Date
Zach Laine
e575cbd9f3 WIP 2024-12-14 14:32:36 -06:00
Zach Laine
3c65bcf187 WIP 2024-12-14 14:32:36 -06:00
Zach Laine
c965c512ad WIP 2024-12-14 14:32:36 -06:00
Zach Laine
702c509ea1 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-14 14:32:25 -06:00
Zach Laine
974154c578 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-09 02:25:01 -06:00
Zach Laine
35a7bd3c09 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-09 02:24:50 -06:00
7 changed files with 478 additions and 1258 deletions

View File

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

View File

@@ -143,6 +143,13 @@ namespace boost { namespace parser { namespace detail {
std::ostream & os,
int components);
template<typename Context, typename Parser, typename ParserMods>
void print_parser_impl(
Context const & context,
no_case_parser<Parser, ParserMods> const & parser,
std::ostream & os,
int components);
template<
typename Context,
typename Parser,
@@ -157,11 +164,11 @@ namespace boost { namespace parser { namespace detail {
template<
typename Context,
typename Parser,
expect_match_t ExpectMatch,
bool FailOnMatch,
typename ParserMods>
void print_parser_impl(
Context const & context,
expect_parser<Parser, ExpectMatch, ParserMods> const & parser,
expect_parser<Parser, FailOnMatch, ParserMods> const & parser,
std::ostream & os,
int components);
@@ -380,7 +387,7 @@ namespace boost { namespace parser { namespace detail {
std::ostream & os,
int components);
template<bool SuppressOmit = false, typename Context, typename Parser>
template<typename Context, typename Parser>
void print_parser(
Context const & context,
Parser const & parser,

View File

@@ -273,7 +273,7 @@ namespace boost { namespace parser { namespace detail {
os << (backtrack ? " >> " : " > ");
if (group != prev_group && group)
os << (group == -1 ? "separate[" : "merge[");
detail::print_parser(context, parser, os, components);
detail::print_parser_impl(context, parser, os, components);
++components;
++i;
prev_group = (int)group;
@@ -358,6 +358,17 @@ namespace boost { namespace parser { namespace detail {
context, "lexeme", parser.parser_, os, components);
}
template<typename Context, typename Parser, typename ParserMods>
void print_parser_impl(
Context const & context,
no_case_parser<Parser, ParserMods> const & parser,
std::ostream & os,
int components)
{
detail::print_directive(
context, "no_case", parser.parser_, os, components);
}
template<
typename Context,
typename Parser,
@@ -385,18 +396,18 @@ namespace boost { namespace parser { namespace detail {
template<
typename Context,
typename Parser,
expect_match_t ExpectMatch,
bool FailOnMatch,
typename ParserMods>
void print_parser_impl(
Context const & context,
expect_parser<Parser, ExpectMatch, ParserMods> const & parser,
expect_parser<Parser, FailOnMatch, ParserMods> const & parser,
std::ostream & os,
int components)
{
if constexpr (ExpectMatch == expect_match_t::yes)
os << "&";
else
if (FailOnMatch)
os << "!";
else
os << "&";
constexpr bool n_ary_child = n_aray_parser_v<Parser>;
if (n_ary_child)
os << "(";
@@ -587,7 +598,7 @@ namespace boost { namespace parser { namespace detail {
std::ostream & os,
int components)
{
if constexpr (parser.mods_.omit_attr == parser::omit_attr_t::yes) {
if constexpr (parser.mods_.omit_attr) {
if constexpr (is_nope_v<Expected>) {
os << "char_";
} else {
@@ -681,7 +692,7 @@ namespace boost { namespace parser { namespace detail {
std::ostream & os,
int components)
{
if constexpr (parser.mods_.omit_attr == parser::omit_attr_t::no) {
if constexpr (!parser.mods_.omit_attr) {
os << "string(";
}
os << "\"";
@@ -691,7 +702,7 @@ namespace boost { namespace parser { namespace detail {
detail::print_char(os, c);
}
os << "\"";
if constexpr (parser.mods_.omit_attr == parser::omit_attr_t::no) {
if constexpr (!parser.mods_.omit_attr) {
os << ")";
}
}
@@ -935,120 +946,64 @@ namespace boost { namespace parser { namespace detail {
context, parser.or_parser_, os, components);
}
template<typename Context, typename Parser>
template<typename ParserMods>
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)
template<typename Parser>
scoped_print_parser_mods(std::ostream & os, Parser const & parser) :
os_(os), mods_(parser.mods_)
{
if constexpr (parser_mods::omit_attr == parser::omit_attr_t::yes) {
if (!skip_omit_ && !skip_omit(parser_))
if constexpr (ParserMods::omit_attr) {
skip_omit_ = skip_omit(parser);
if (!skip_omit_)
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_))
if constexpr (ParserMods::omit_attr) {
if (!skip_omit_)
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>
template<
typename Expected,
typename AttributeType,
typename ParserMods2>
static bool
skip_omit(char_parser<Expected, AttributeType, ParserMods> const &)
skip_omit(char_parser<Expected, AttributeType, ParserMods2> const &)
{
return !std::is_same_v<Expected, detail::nope>;
}
template<typename StrIter, typename StrSentinel, typename ParserMods>
template<typename StrIter, typename StrSentinel, typename ParserMods2>
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 &)
skip_omit(string_parser<StrIter, StrSentinel, ParserMods2> const &)
{
return true;
}
Context const & context_;
Parser const & parser_;
std::ostream & os_;
int & components_;
bool skip_omit_;
ParserMods const & mods_;
bool skip_omit_ = false;
};
// 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>
// TODO: Document how 'omit[]' will reappear for subparsers sometimes, as
// in omt[*omit[char_]] (see test/tracing.cpp).
template<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);
scoped_print_parser_mods<std::decay_t<decltype(parser.mods_)>> _(
os, parser);
detail::print_parser_impl(context, parser, os, components);
}

File diff suppressed because it is too large Load Diff

View File

@@ -149,33 +149,14 @@ 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>
template<bool OmitAttr = false, typename Action = detail::nope>
struct parser_modifiers
{
using pre_parser_type = PreParser;
using post_parser_type = PostParser;
using action_type = Action;
static constexpr omit_attr_t omit_attr = OmitAttr;
static constexpr ignore_case_t ignore_case = IgnoreCase;
static constexpr bool omit_attr = OmitAttr;
[[no_unique_address]] PreParser pre_parser;
[[no_unique_address]] PostParser post_parser;
[[no_unique_address]] Action action;
};
/** Repeats the application of another parser `p` of type `Parser`,
@@ -296,6 +277,13 @@ namespace boost { namespace 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, typename ParserMods>
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
@@ -307,9 +295,9 @@ namespace boost { namespace parser {
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 equal
to `ExpectMatch == expect_match_t::yes`. */
template<typename Parser, expect_match_t ExpectMatch, typename ParserMods>
and consuming no input. The parse succeeds iff `p`'s success is
unequal to `FailOnMatch`. */
template<typename Parser, bool FailOnMatch, typename ParserMods>
struct expect_parser;
/** Matches one of a set S of possible inputs, each of which is associated

View File

@@ -39,7 +39,7 @@ constexpr auto double_s = u8"sS"; // U+0073 U+0073
// basic)
{
auto char_p = no_case[char_('a') | char_('B')];
constexpr 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<ignore_case_t::yes>(
mixed_sharp_s1,
detail::text::null_sentinel,
mixed_sharp_s2,
detail::text::null_sentinel);
auto const result = detail::no_case_aware_string_mismatch(
mixed_sharp_s1,
detail::text::null_sentinel,
mixed_sharp_s2,
detail::text::null_sentinel,
true);
BOOST_TEST(result.first == detail::text::null_sentinel);
BOOST_TEST(result.second == detail::text::null_sentinel);
}

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; };
@@ -190,15 +190,6 @@ 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"
@@ -229,16 +220,6 @@ 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"
@@ -247,16 +228,6 @@ 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"