Skip to content

Commit

Permalink
Merge branch 'master' into gh-pages
Browse files Browse the repository at this point in the history
  • Loading branch information
tzlaine committed Dec 31, 2023
2 parents 144ac9c + 19f3989 commit 14e17fa
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 51 deletions.
6 changes: 1 addition & 5 deletions doc/intro.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,7 @@ tutorial and examples.

The presence of Boost headers is detected using `__has_include()`. When it is
present, all the typical Boost conventions are used (e.g. `BOOST_ASSERT()`
instead of `assert()`); otherwise, non-Boost alternatives are used. The macro
`BOOST_PARSER_DEFINE_RULES()`, which defines multiple rules in one go, is only
defined when Boost.Preprocessor is present. Without this macro, you have to
write `BOOST_PARSER_DEFINE_RULE()` (note the singular form) once for each
rule.
instead of `assert()`); otherwise, non-Boost alternatives are used.

[endsect]

Expand Down
33 changes: 21 additions & 12 deletions doc/tutorial.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,28 @@ before or after the list of `double`s.
Let's modify the trivial parser we just saw to ignore any spaces it might find
among the `double`s and commas. To skip whitespace wherever we find it, we
can pass a /skip parser/ to our call to _p_ (we don't need to touch the parser
passed to _p_). Here, we use `ascii::space`, which matches any ASCII
character `c` for which `std::isspace(c)` is true.
passed to _p_). Here, we use `ws`, which matches any Unicode whitespace
character.

[trivial_skipper_example]

[tip Even though there is another parser `ascii::space` that we could have
used here, and even though we know we're in a non-Unicode parsing context here
from the `std::string` input, I did not use `ascii::space`. The `ascii::`
namespace parsers exist mostly to aid porting from Boost.Spirit. They are
inherently dangerous in a Unicode environment, since they use the `std::is*()`
functions (like `std::isspace()`). `ws` is correct, plus it is written in
such a way that it matches the ASCII subset of values first, meaning it is no
less efficient to use for parsing ASCII than `ascii::space`.]

The skip parser, or /skipper/, is run between the subparsers within the
parser passed to _p_. In this case, the skipper is run before the first
`double` is parsed, before any subsequent comma or `double` is parsed, and at
the end. So, the strings `"3.6,5.9"` and `" 3.6 , \t 5.9 "` are parsed the
same by this program.

Skipping is an important concept in _Parser_. You can skip anything, not just
ASCII whitespace; there are lots of other things you might want to skip. The
whitespace; there are lots of other things you might want to skip. The
skipper you pass to _p_ can be an arbitrary parser. For example, if you write
a parser for a scripting language, you can write a skipper to skip whitespace,
inline comments, and end-of-line comments.
Expand Down Expand Up @@ -495,8 +504,7 @@ like we might any other parser:
[rule_intro_parse_call]

[note We used _RULE_ in this example. There is also another macro that allows
you to define multiple rules in one macro expansion, _RULES_. _RULES_ is only
available if the necessary Boost.Preprocessor headers are available.]
you to define multiple rules in one macro expansion, _RULES_.]

The full program:

Expand Down Expand Up @@ -2710,13 +2718,14 @@ code manageable.

These are broken for many use cases, because they use the implementations from
the C library (e.g. `isalnum()`). Those implementations do not work for
non-ASCII values. A general implementation of each of these is also difficult
even in Unicode parsing, because the meaning of many of them is contextual.
For example, whether a code point is lower case or not can depend on where it
is within the text you're parsing, and can depend on the language you're
parsing. You're better off naming the specific code points or ranges of code
points you want to match. The `boost::parser::ascii` parsers are included for
ASCII-only users, and for those porting parsers from Spirit.
non-ASCII values, *even though they take `int` parameters*. A general
implementation of each of these is also difficult even in Unicode parsing,
because the meaning of many of them is contextual. For example, whether a
code point is lower case or not can depend on where it is within the text
you're parsing, and can depend on the language you're parsing. You're better
off naming the specific code points or ranges of code points you want to
match. The `boost::parser::ascii` parsers are included for ASCII-only users,
and for those porting parsers from Spirit.

[heading If your parser takes end-user input, give rules names that you would want an end-user to see]

Expand Down
4 changes: 2 additions & 2 deletions example/trivial_skipper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ int main()
std::string input;
std::getline(std::cin, input);

auto const result = bp::parse(
input, bp::double_ >> *(',' >> bp::double_), bp::ascii::space);
auto const result =
bp::parse(input, bp::double_ >> *(',' >> bp::double_), bp::ws);

if (result) {
std::cout << "Great! It looks like you entered:\n";
Expand Down
123 changes: 123 additions & 0 deletions include/boost/parser/detail/pp_for_each.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#ifndef BOOST_PARSER_DETAIL_PP_FOR_EACH_HPP_INCLUDED
#define BOOST_PARSER_DETAIL_PP_FOR_EACH_HPP_INCLUDED

// Copyright 2020 Peter Dimov
// Copyright 2023 T. Zachary Laine
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/parser/detail/pp_utilities.hpp>

#define BOOST_PARSER_PP_FOR_EACH_0(F, a)
#define BOOST_PARSER_PP_FOR_EACH_1(F, a, x) BOOST_PARSER_PP_CALL(F, a, x)
#define BOOST_PARSER_PP_FOR_EACH_2(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_1(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_3(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_2(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_4(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_3(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_5(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_4(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_6(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_5(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_7(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_6(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_8(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_7(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_9(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_8(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_10(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_9(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_11(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_10(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_12(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_11(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_13(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_12(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_14(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_13(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_15(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_14(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_16(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_15(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_17(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_16(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_18(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_17(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_19(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_18(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_20(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_19(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_21(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_20(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_22(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_21(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_23(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_22(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_24(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_23(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_25(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_24(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_26(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_25(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_27(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_26(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_28(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_27(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_29(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_28(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_30(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_29(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_31(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_30(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_32(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_31(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_33(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_32(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_34(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_33(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_35(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_34(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_36(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_35(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_37(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_36(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_38(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_37(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_39(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_38(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_40(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_39(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_41(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_40(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_42(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_41(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_43(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_42(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_44(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_43(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_45(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_44(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_46(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_45(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_47(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_46(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_48(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_47(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_49(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_48(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_50(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_49(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_51(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_50(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_52(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_51(F, a, __VA_ARGS__))

#define BOOST_PARSER_PP_FE_EXTRACT(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, V, ...) V

#define BOOST_PARSER_PP_FOR_EACH(F, ...) \
BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_FE_EXTRACT(__VA_ARGS__, \
BOOST_PARSER_PP_FOR_EACH_52, \
BOOST_PARSER_PP_FOR_EACH_51, \
BOOST_PARSER_PP_FOR_EACH_50, \
BOOST_PARSER_PP_FOR_EACH_49, \
BOOST_PARSER_PP_FOR_EACH_48, \
BOOST_PARSER_PP_FOR_EACH_47, \
BOOST_PARSER_PP_FOR_EACH_46, \
BOOST_PARSER_PP_FOR_EACH_45, \
BOOST_PARSER_PP_FOR_EACH_44, \
BOOST_PARSER_PP_FOR_EACH_43, \
BOOST_PARSER_PP_FOR_EACH_42, \
BOOST_PARSER_PP_FOR_EACH_41, \
BOOST_PARSER_PP_FOR_EACH_40, \
BOOST_PARSER_PP_FOR_EACH_39, \
BOOST_PARSER_PP_FOR_EACH_38, \
BOOST_PARSER_PP_FOR_EACH_37, \
BOOST_PARSER_PP_FOR_EACH_36, \
BOOST_PARSER_PP_FOR_EACH_35, \
BOOST_PARSER_PP_FOR_EACH_34, \
BOOST_PARSER_PP_FOR_EACH_33, \
BOOST_PARSER_PP_FOR_EACH_32, \
BOOST_PARSER_PP_FOR_EACH_31, \
BOOST_PARSER_PP_FOR_EACH_30, \
BOOST_PARSER_PP_FOR_EACH_29, \
BOOST_PARSER_PP_FOR_EACH_28, \
BOOST_PARSER_PP_FOR_EACH_27, \
BOOST_PARSER_PP_FOR_EACH_26, \
BOOST_PARSER_PP_FOR_EACH_25, \
BOOST_PARSER_PP_FOR_EACH_24, \
BOOST_PARSER_PP_FOR_EACH_23, \
BOOST_PARSER_PP_FOR_EACH_22, \
BOOST_PARSER_PP_FOR_EACH_21, \
BOOST_PARSER_PP_FOR_EACH_20, \
BOOST_PARSER_PP_FOR_EACH_19, \
BOOST_PARSER_PP_FOR_EACH_18, \
BOOST_PARSER_PP_FOR_EACH_17, \
BOOST_PARSER_PP_FOR_EACH_16, \
BOOST_PARSER_PP_FOR_EACH_15, \
BOOST_PARSER_PP_FOR_EACH_14, \
BOOST_PARSER_PP_FOR_EACH_13, \
BOOST_PARSER_PP_FOR_EACH_12, \
BOOST_PARSER_PP_FOR_EACH_11, \
BOOST_PARSER_PP_FOR_EACH_10, \
BOOST_PARSER_PP_FOR_EACH_9, \
BOOST_PARSER_PP_FOR_EACH_8, \
BOOST_PARSER_PP_FOR_EACH_7, \
BOOST_PARSER_PP_FOR_EACH_6, \
BOOST_PARSER_PP_FOR_EACH_5, \
BOOST_PARSER_PP_FOR_EACH_4, \
BOOST_PARSER_PP_FOR_EACH_3, \
BOOST_PARSER_PP_FOR_EACH_2, \
BOOST_PARSER_PP_FOR_EACH_1, \
BOOST_PARSER_PP_FOR_EACH_0))(F, __VA_ARGS__))

#endif // #ifndef BOOST_PARSER_DETAIL_PP_FOR_EACH_HPP_INCLUDED
93 changes: 93 additions & 0 deletions include/boost/parser/detail/pp_utilities.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#ifndef BOOST_PARSER_DETAIL_PP_UTILITIES_HPP_INCLUDED
#define BOOST_PARSER_DETAIL_PP_UTILITIES_HPP_INCLUDED

// Copyright 2021 Peter Dimov
// Copyright 2023 T. Zachary Laine
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#define BOOST_PARSER_PP_EXPAND(x) x

#define BOOST_PARSER_PP_CAT(x, y) BOOST_PARSER_PP_CAT_I(x, y)
#define BOOST_PARSER_PP_CAT_I(x, ...) x ## __VA_ARGS__

#if defined(_MSC_VER) && !defined(__clang__)

#define BOOST_PARSER_PP_FIRST(x) BOOST_PARSER_PP_FIRST_I((x))
#define BOOST_PARSER_PP_FIRST_I(x) BOOST_PARSER_PP_FIRST_II x
#define BOOST_PARSER_PP_FIRST_II(x, ...) x

#else

#define BOOST_PARSER_PP_FIRST(x) BOOST_PARSER_PP_FIRST_I(x)
#define BOOST_PARSER_PP_FIRST_I(x, ...) x

#endif

#define BOOST_PARSER_PP_IS_PAREN_I(x) BOOST_PARSER_PP_CAT(BOOST_PARSER_PP_IS_PAREN_I_, BOOST_PARSER_PP_IS_PAREN_II x)
#define BOOST_PARSER_PP_IS_PAREN_II(...) 0
#define BOOST_PARSER_PP_IS_PAREN_I_0 1,
#define BOOST_PARSER_PP_IS_PAREN_I_BOOST_PARSER_PP_IS_PAREN_II 0,

#define BOOST_PARSER_PP_IS_PAREN(x) BOOST_PARSER_PP_FIRST(BOOST_PARSER_PP_IS_PAREN_I(x))

#define BOOST_PARSER_PP_EMPTY

#define BOOST_PARSER_PP_IS_EMPTY(x) BOOST_PARSER_PP_IS_EMPTY_I(BOOST_PARSER_PP_IS_PAREN(x), BOOST_PARSER_PP_IS_PAREN(x BOOST_PARSER_PP_EMPTY ()))
#define BOOST_PARSER_PP_IS_EMPTY_I(x, y) BOOST_PARSER_PP_IS_EMPTY_II(x, y)
#define BOOST_PARSER_PP_IS_EMPTY_II(x, y) BOOST_PARSER_PP_IS_EMPTY_III(x, y)
#define BOOST_PARSER_PP_IS_EMPTY_III(x, y) BOOST_PARSER_PP_IS_EMPTY_III_ ## x ## y
#define BOOST_PARSER_PP_IS_EMPTY_III_00 0
#define BOOST_PARSER_PP_IS_EMPTY_III_01 1
#define BOOST_PARSER_PP_IS_EMPTY_III_10 0
#define BOOST_PARSER_PP_IS_EMPTY_III_11 0

#define BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_CAT(BOOST_PARSER_PP_CALL_I_, BOOST_PARSER_PP_IS_EMPTY(x))(F, a, x)
#define BOOST_PARSER_PP_CALL_I_0(F, a, x) F(a, x)
#define BOOST_PARSER_PP_CALL_I_1(F, a, x)

#define BOOST_PARSER_PP_PARSE(x) BOOST_PARSER_PP_CAT(BOOST_PARSER_PP_PARSE_I_, BOOST_PARSER_PP_PARSE_II x)
#define BOOST_PARSER_PP_PARSE_II(...) 0, (__VA_ARGS__),
#define BOOST_PARSER_PP_PARSE_I_BOOST_PARSER_PP_PARSE_II 0, ~,
#define BOOST_PARSER_PP_PARSE_I_0 1

#if defined(_MSC_VER) && !defined(__clang__)

#define BOOST_PARSER_PP_NAME(x) BOOST_PARSER_PP_NAME_I(BOOST_PARSER_PP_PARSE(x))
#define BOOST_PARSER_PP_NAME_I(x) BOOST_PARSER_PP_NAME_II((x))
#define BOOST_PARSER_PP_NAME_II(x) BOOST_PARSER_PP_NAME_III x
#define BOOST_PARSER_PP_NAME_III(x, y, z) #z

#else

#define BOOST_PARSER_PP_NAME(x) BOOST_PARSER_PP_NAME_I(BOOST_PARSER_PP_PARSE(x))
#define BOOST_PARSER_PP_NAME_I(x) BOOST_PARSER_PP_NAME_II(x)
#define BOOST_PARSER_PP_NAME_II(x, y, z) #z

#endif

// template<class C, class F> constexpr auto mfn( F C::* p ) { return p; }
// template<class C, class F> constexpr auto mfn( F * p ) { return p; }

#define BOOST_PARSER_PP_POINTER(C, x) BOOST_PARSER_PP_POINTER_I(C, BOOST_PARSER_PP_PARSE(x))

#define BOOST_PARSER_PP_EXPAND_V(...) __VA_ARGS__

#if defined(_MSC_VER) && !defined(__clang__)

#define BOOST_PARSER_PP_POINTER_I(C, x) BOOST_PARSER_PP_POINTER_II((C, x))
#define BOOST_PARSER_PP_POINTER_II(x) BOOST_PARSER_PP_POINTER_III x
#define BOOST_PARSER_PP_POINTER_III(C, x, y, z) BOOST_PARSER_PP_POINTER_III_##x(C, y, z)
#define BOOST_PARSER_PP_POINTER_III_0(C, y, z) &C::z
#define BOOST_PARSER_PP_POINTER_III_1(C, y, z) ::boost::describe::detail::mfn<C, BOOST_PARSER_PP_EXPAND_V y>(&C::z)

#else

#define BOOST_PARSER_PP_POINTER_I(C, x) BOOST_PARSER_PP_POINTER_II(C, x)
#define BOOST_PARSER_PP_POINTER_II(C, x, y, z) BOOST_PARSER_PP_POINTER_III_##x(C, y, z)
#define BOOST_PARSER_PP_POINTER_III_0(C, y, z) &C::z
#define BOOST_PARSER_PP_POINTER_III_1(C, y, z) ::boost::describe::detail::mfn<C, BOOST_PARSER_PP_EXPAND_V y>(&C::z)

#endif

#endif // #ifndef BOOST_PARSER_DETAIL_PP_UTILITIES_HPP_INCLUDED
Loading

0 comments on commit 14e17fa

Please sign in to comment.