mirror of
https://github.com/boostorg/parser.git
synced 2026-01-24 06:02:12 +00:00
Compare commits
6 Commits
issue_160
...
issue_160_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e575cbd9f3 | ||
|
|
3c65bcf187 | ||
|
|
c965c512ad | ||
|
|
702c509ea1 | ||
|
|
974154c578 | ||
|
|
35a7bd3c09 |
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user