mirror of
https://github.com/boostorg/parser.git
synced 2026-02-22 03:32:14 +00:00
Compare commits
16 Commits
boost-1.90
...
introduce_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a200a4074 | ||
|
|
1b984e3546 | ||
|
|
316b4921a9 | ||
|
|
4706f57c8e | ||
|
|
5625f0345e | ||
|
|
a2df985cc5 | ||
|
|
41d939b2bc | ||
|
|
72b8068867 | ||
|
|
f6c5de7e76 | ||
|
|
c54307b95c | ||
|
|
5b3f122aa7 | ||
|
|
6db68bc7f7 | ||
|
|
00fe33d2f3 | ||
|
|
bb183cf5ee | ||
|
|
885595f7bd | ||
|
|
6826f957a1 |
@@ -1,4 +1,4 @@
|
|||||||
name: macos-13 - Clang 14
|
name: macos-15 - Clang
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -14,9 +14,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
cxx_std: [17]
|
cxx_std: [17, 20]
|
||||||
|
|
||||||
runs-on: macos-13
|
runs-on: macos-15
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
13
.github/workflows/ubuntu.yml
vendored
13
.github/workflows/ubuntu.yml
vendored
@@ -18,6 +18,13 @@ jobs:
|
|||||||
compiler_version: [g++-10, g++-11]
|
compiler_version: [g++-10, g++-11]
|
||||||
cxx_std: [17, 20]
|
cxx_std: [17, 20]
|
||||||
os: [ubuntu-22.04]
|
os: [ubuntu-22.04]
|
||||||
|
disable_trace: [false]
|
||||||
|
include:
|
||||||
|
# Test with trace disabled
|
||||||
|
- compiler_version: g++-11
|
||||||
|
cxx_std: 20
|
||||||
|
os: ubuntu-22.04
|
||||||
|
disable_trace: true
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
@@ -30,7 +37,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler_version }} -DCXX_STD=${{ matrix.cxx_std }}
|
if [ "${{ matrix.disable_trace }}" = "true" ]; then
|
||||||
|
cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler_version }} -DCXX_STD=${{ matrix.cxx_std }} -DDISABLE_TRACE=true
|
||||||
|
else
|
||||||
|
cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler_version }} -DCXX_STD=${{ matrix.cxx_std }}
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cd build ; make -j4
|
run: cd build ; make -j4
|
||||||
|
|||||||
18
.github/workflows/windows.yml
vendored
18
.github/workflows/windows.yml
vendored
@@ -17,6 +17,12 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
cxx_std: [17, 20, 23]
|
cxx_std: [17, 20, 23]
|
||||||
os: [windows-2022]
|
os: [windows-2022]
|
||||||
|
disable_trace: [false]
|
||||||
|
include:
|
||||||
|
# Test with trace disabled
|
||||||
|
- cxx_std: 20
|
||||||
|
os: windows-2022
|
||||||
|
disable_trace: true
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
@@ -24,13 +30,19 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
# Configure CMake in a 'build' subdirectory. Visual Studio is a multi-config generator, so we don't use CMAKE_BUILD_TYPE.
|
||||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||||
run: cmake -B build -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DCXX_STD=${{ matrix.cxx_std }}
|
run: |
|
||||||
|
if ("${{ matrix.disable_trace }}" -eq "true") {
|
||||||
|
cmake -B build -DCXX_STD=${{ matrix.cxx_std }} -DDISABLE_TRACE=true
|
||||||
|
} else {
|
||||||
|
cmake -B build -DCXX_STD=${{ matrix.cxx_std }}
|
||||||
|
}
|
||||||
|
shell: pwsh
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: build
|
working-directory: build
|
||||||
run: cmake --build . -- /p:CL_MPcount=4
|
run: cmake --build . --config ${{ env.BUILD_TYPE }} -- /p:CL_MPcount=4
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
working-directory: build/test
|
working-directory: build/test
|
||||||
|
|||||||
@@ -64,6 +64,12 @@ if (BUILD_WITH_HANA)
|
|||||||
add_definitions(-DBOOST_PARSER_USE_HANA_TUPLE)
|
add_definitions(-DBOOST_PARSER_USE_HANA_TUPLE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(DISABLE_TRACE false CACHE BOOL
|
||||||
|
"Disable parser trace functionality (defines BOOST_PARSER_DISABLE_TRACE).")
|
||||||
|
if (DISABLE_TRACE)
|
||||||
|
add_definitions(-DBOOST_PARSER_DISABLE_TRACE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|||||||
@@ -67,6 +67,6 @@ Develop status:
|
|||||||
|
|
||||||
[](https://github.com/tzlaine/parser/actions/workflows/windows.yml)
|
[](https://github.com/tzlaine/parser/actions/workflows/windows.yml)
|
||||||
|
|
||||||
[](https://github.com/tzlaine/parser/actions/workflows/macos-13.yml)
|
[](https://github.com/tzlaine/parser/actions/workflows/macos-15.yml)
|
||||||
|
|
||||||
[](LICENSE_1_0.txt)
|
[](LICENSE_1_0.txt)
|
||||||
|
|||||||
@@ -148,6 +148,7 @@
|
|||||||
[def _RULES_ [macroref BOOST_PARSER_DEFINE_RULES `BOOST_PARSER_DEFINE_RULES`]]
|
[def _RULES_ [macroref BOOST_PARSER_DEFINE_RULES `BOOST_PARSER_DEFINE_RULES`]]
|
||||||
[def _AGGR_SIZE_ [macroref BOOST_PARSER_MAX_AGGREGATE_SIZE `BOOST_PARSER_MAX_AGGREGATE_SIZE`]]
|
[def _AGGR_SIZE_ [macroref BOOST_PARSER_MAX_AGGREGATE_SIZE `BOOST_PARSER_MAX_AGGREGATE_SIZE`]]
|
||||||
[def _SUBRNG_ [macroref BOOST_PARSER_SUBRANGE `BOOST_PARSER_SUBRANGE`]]
|
[def _SUBRNG_ [macroref BOOST_PARSER_SUBRANGE `BOOST_PARSER_SUBRANGE`]]
|
||||||
|
[def _DISABLE_TRACE_ [macroref BOOST_PARSER_DISABLE_TRACE `BOOST_PARSER_DISABLE_TRACE`]]
|
||||||
|
|
||||||
[def __p_ [globalref boost::parser::_p `_p`]]
|
[def __p_ [globalref boost::parser::_p `_p`]]
|
||||||
|
|
||||||
|
|||||||
@@ -3766,6 +3766,22 @@ Some things to be aware of when looking at _Parser_ trace output:
|
|||||||
produces that value. In these cases, you'll see the resolved value of the
|
produces that value. In these cases, you'll see the resolved value of the
|
||||||
parse argument.
|
parse argument.
|
||||||
|
|
||||||
|
[heading Compile-time trace disabling]
|
||||||
|
|
||||||
|
While trace mode is very useful for debugging, it does have some overhead.
|
||||||
|
Most parser templates are instantiated twice: Once with tracing enabled,
|
||||||
|
once with tracing disabled.
|
||||||
|
If you want to completely disable trace functionality at compile time, you can define
|
||||||
|
`BOOST_PARSER_DISABLE_TRACE` before including any Boost.Parser headers:
|
||||||
|
|
||||||
|
[teletype]``
|
||||||
|
#define BOOST_PARSER_DISABLE_TRACE
|
||||||
|
#include <boost/parser/parser.hpp>
|
||||||
|
``
|
||||||
|
|
||||||
|
When this define is set, all trace-related code is compiled out,
|
||||||
|
reducing the compile time.
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[section Memory Allocation]
|
[section Memory Allocation]
|
||||||
@@ -3983,7 +3999,8 @@ This defines a RAII trace object that will produce the verbose trace requested
|
|||||||
by the user if they passed `_trace_::on` to the top-level parse. It only has
|
by the user if they passed `_trace_::on` to the top-level parse. It only has
|
||||||
effect if `detail::enable_trace(flags)` is `true`. If trace is enabled, it
|
effect if `detail::enable_trace(flags)` is `true`. If trace is enabled, it
|
||||||
will show the state of the parse at the point at which it is defined, and then
|
will show the state of the parse at the point at which it is defined, and then
|
||||||
again when it goes out of scope.
|
again when it goes out of scope. By defining `BOOST_PARSER_DISABLE_TRACE`,
|
||||||
|
the trace feature can be disabled globally at compile time.
|
||||||
|
|
||||||
[important For the tracing code to work, you must define an overload of
|
[important For the tracing code to work, you must define an overload of
|
||||||
`detail::print_parser` for your new parser type/template. See
|
`detail::print_parser` for your new parser type/template. See
|
||||||
|
|||||||
@@ -36,6 +36,10 @@
|
|||||||
disable the use of concepts, define this macro. */
|
disable the use of concepts, define this macro. */
|
||||||
# define BOOST_PARSER_DISABLE_CONCEPTS
|
# define BOOST_PARSER_DISABLE_CONCEPTS
|
||||||
|
|
||||||
|
/** Boost.Parser will generate code to trace the execution of each and every
|
||||||
|
parser by default. To disable all trace code, define this macro. */
|
||||||
|
# define BOOST_PARSER_DISABLE_TRACE
|
||||||
|
|
||||||
/** Define this macro to use `boost::hana::tuple` instead of `std::tuple`
|
/** Define this macro to use `boost::hana::tuple` instead of `std::tuple`
|
||||||
throughout Boost.Parser. */
|
throughout Boost.Parser. */
|
||||||
# define BOOST_PARSER_USE_HANA_TUPLE
|
# define BOOST_PARSER_USE_HANA_TUPLE
|
||||||
@@ -92,6 +96,12 @@
|
|||||||
# define BOOST_PARSER_USE_CONCEPTS 0
|
# define BOOST_PARSER_USE_CONCEPTS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOOST_PARSER_DISABLE_TRACE)
|
||||||
|
# define BOOST_PARSER_DO_TRACE 0
|
||||||
|
#else
|
||||||
|
# define BOOST_PARSER_DO_TRACE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__cpp_lib_ranges) && BOOST_PARSER_USE_CONCEPTS
|
#if defined(__cpp_lib_ranges) && BOOST_PARSER_USE_CONCEPTS
|
||||||
# define BOOST_PARSER_SUBRANGE std::ranges::subrange
|
# define BOOST_PARSER_SUBRANGE std::ranges::subrange
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -593,11 +593,14 @@ namespace boost { namespace parser { namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Context, typename T>
|
template<typename Context, typename T>
|
||||||
auto resolve(Context const & context, T const & x);
|
decltype(auto) resolve(Context const & context, T const & x);
|
||||||
|
|
||||||
template<typename Context>
|
template<typename Context>
|
||||||
auto resolve(Context const &, nope n);
|
auto resolve(Context const &, nope n);
|
||||||
|
|
||||||
|
template<typename DependentType, bool DoTraceMacro>
|
||||||
|
constexpr bool trace_disabled = !DoTraceMacro;
|
||||||
|
|
||||||
template<
|
template<
|
||||||
bool DoTrace,
|
bool DoTrace,
|
||||||
typename Iter,
|
typename Iter,
|
||||||
@@ -606,6 +609,8 @@ namespace boost { namespace parser { namespace detail {
|
|||||||
typename Attribute>
|
typename Attribute>
|
||||||
struct scoped_trace_t
|
struct scoped_trace_t
|
||||||
{
|
{
|
||||||
|
static_assert(!trace_disabled<Iter, BOOST_PARSER_DO_TRACE>);
|
||||||
|
|
||||||
scoped_trace_t(
|
scoped_trace_t(
|
||||||
std::ostream & os,
|
std::ostream & os,
|
||||||
Iter & first,
|
Iter & first,
|
||||||
@@ -681,6 +686,9 @@ namespace boost { namespace parser { namespace detail {
|
|||||||
flags f,
|
flags f,
|
||||||
Attribute const & attr)
|
Attribute const & attr)
|
||||||
{
|
{
|
||||||
|
if constexpr (!BOOST_PARSER_DO_TRACE)
|
||||||
|
return;
|
||||||
|
|
||||||
if constexpr (Context::do_trace) {
|
if constexpr (Context::do_trace) {
|
||||||
std::stringstream oss;
|
std::stringstream oss;
|
||||||
detail::print_parser(context, parser, oss);
|
detail::print_parser(context, parser, oss);
|
||||||
@@ -695,6 +703,9 @@ namespace boost { namespace parser { namespace detail {
|
|||||||
template<typename Context, typename Attribute>
|
template<typename Context, typename Attribute>
|
||||||
auto final_trace(Context const & context, flags f, Attribute const & attr)
|
auto final_trace(Context const & context, flags f, Attribute const & attr)
|
||||||
{
|
{
|
||||||
|
if constexpr (!BOOST_PARSER_DO_TRACE)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!detail::do_trace(f))
|
if (!detail::do_trace(f))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ namespace boost { namespace parser {
|
|||||||
os << ":\n";
|
os << ":\n";
|
||||||
|
|
||||||
std::string underlining(std::distance(position.line_start, it), ' ');
|
std::string underlining(std::distance(position.line_start, it), ' ');
|
||||||
|
std::transform(position.line_start, it,
|
||||||
|
underlining.begin(),
|
||||||
|
[](auto c) { return c == '\t' ? '\t' : ' ';});
|
||||||
detail::trace_input(os, position.line_start, it, false, 1u << 31);
|
detail::trace_input(os, position.line_start, it, false, 1u << 31);
|
||||||
if (it == last) {
|
if (it == last) {
|
||||||
os << '\n' << underlining << "^\n";
|
os << '\n' << underlining << "^\n";
|
||||||
|
|||||||
@@ -1020,7 +1020,7 @@ namespace boost { namespace parser {
|
|||||||
bool Callable = is_detected_v<callable, T const &, Context const &>>
|
bool Callable = is_detected_v<callable, T const &, Context const &>>
|
||||||
struct resolve_impl
|
struct resolve_impl
|
||||||
{
|
{
|
||||||
static auto call(Context const &, T const & x) { return x; }
|
static auto& call(Context const &, T const & x) { return x; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename T>
|
template<typename Context, typename T>
|
||||||
@@ -1033,7 +1033,7 @@ namespace boost { namespace parser {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename T>
|
template<typename Context, typename T>
|
||||||
auto resolve(Context const & context, T const & x)
|
decltype(auto) resolve(Context const & context, T const & x)
|
||||||
{
|
{
|
||||||
return resolve_impl<Context, T>::call(context, x);
|
return resolve_impl<Context, T>::call(context, x);
|
||||||
}
|
}
|
||||||
@@ -2168,7 +2168,10 @@ namespace boost { namespace parser {
|
|||||||
{
|
{
|
||||||
if (!gen_attrs || !x)
|
if (!gen_attrs || !x)
|
||||||
return;
|
return;
|
||||||
c.insert(c.end(), x->begin(), x->end());
|
c.insert(c.end(),
|
||||||
|
std::make_move_iterator(x->begin()),
|
||||||
|
std::make_move_iterator(x->end())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container, typename T>
|
template<typename Container, typename T>
|
||||||
@@ -2851,7 +2854,7 @@ namespace boost { namespace parser {
|
|||||||
last,
|
last,
|
||||||
parse_error<I>(first, "end of input")) ==
|
parse_error<I>(first, "end of input")) ==
|
||||||
error_handler_result::rethrow) {
|
error_handler_result::rethrow) {
|
||||||
throw;
|
throw parse_error<I>(first, "end of input");
|
||||||
}
|
}
|
||||||
if constexpr (std::is_same_v<T, bool>)
|
if constexpr (std::is_same_v<T, bool>)
|
||||||
retval = false;
|
retval = false;
|
||||||
@@ -3177,6 +3180,7 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this,
|
*this,
|
||||||
first,
|
first,
|
||||||
@@ -3185,6 +3189,7 @@ namespace boost { namespace parser {
|
|||||||
detail::in_apply_parser(flags) ? detail::disable_trace(flags)
|
detail::in_apply_parser(flags) ? detail::disable_trace(flags)
|
||||||
: flags,
|
: flags,
|
||||||
retval);
|
retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
if constexpr (detail::is_optional_v<Attribute>) {
|
if constexpr (detail::is_optional_v<Attribute>) {
|
||||||
detail::optional_type<Attribute> attr;
|
detail::optional_type<Attribute> attr;
|
||||||
@@ -3341,8 +3346,10 @@ namespace boost { namespace parser {
|
|||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
//[ opt_parser_trace
|
//[ opt_parser_trace
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
//]
|
//]
|
||||||
|
|
||||||
//[ opt_parser_skip
|
//[ opt_parser_skip
|
||||||
@@ -3505,8 +3512,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
use_parser_t<Iter, Sentinel, Context, SkipParser> const use_parser{
|
use_parser_t<Iter, Sentinel, Context, SkipParser> const use_parser{
|
||||||
first, last, context, skip, flags, success};
|
first, last, context, skip, flags, success};
|
||||||
@@ -3529,7 +3538,9 @@ namespace boost { namespace parser {
|
|||||||
else
|
else
|
||||||
use_parser.first_ = prev_first;
|
use_parser.first_ = prev_first;
|
||||||
};
|
};
|
||||||
detail::hl::for_each(parsers_, try_parser); // TODO: -> fold-expr
|
std::apply([&try_parser](auto&&... args) {
|
||||||
|
((try_parser(args)), ...);
|
||||||
|
}, parsers_);
|
||||||
|
|
||||||
if (!done)
|
if (!done)
|
||||||
success = false;
|
success = false;
|
||||||
@@ -3627,8 +3638,10 @@ namespace boost { namespace parser {
|
|||||||
decltype(detail::hl::transform(parsers_, use_parser));
|
decltype(detail::hl::transform(parsers_, use_parser));
|
||||||
result_t retval{};
|
result_t retval{};
|
||||||
|
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first_, last, context, flags, retval);
|
*this, first_, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
call_impl(
|
call_impl(
|
||||||
first,
|
first,
|
||||||
@@ -3663,8 +3676,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first_, last, context, flags, retval);
|
*this, first_, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
Iter first = first_;
|
Iter first = first_;
|
||||||
use_parser_t<Iter, Sentinel, Context, SkipParser> const use_parser{
|
use_parser_t<Iter, Sentinel, Context, SkipParser> const use_parser{
|
||||||
@@ -3711,7 +3726,7 @@ namespace boost { namespace parser {
|
|||||||
if constexpr (detail::is_struct_compatible_v<
|
if constexpr (detail::is_struct_compatible_v<
|
||||||
Attribute,
|
Attribute,
|
||||||
result_t>) {
|
result_t>) {
|
||||||
detail::assign(retval, temp_retval);
|
detail::assign(retval, std::move(temp_retval));
|
||||||
} else {
|
} else {
|
||||||
detail::assign(
|
detail::assign(
|
||||||
retval,
|
retval,
|
||||||
@@ -4290,12 +4305,13 @@ namespace boost { namespace parser {
|
|||||||
{
|
{
|
||||||
Iter first = first_;
|
Iter first = first_;
|
||||||
|
|
||||||
auto temp_result =
|
using temp_result_t =
|
||||||
make_temp_result(first, last, context, skip, flags, success);
|
decltype(make_temp_result(first, last, context, skip, flags, success));
|
||||||
|
|
||||||
std::decay_t<decltype(parser::get(temp_result, llong<0>{}))>
|
std::decay_t<decltype(parser::get(std::declval<temp_result_t>(), llong<0>{}))>
|
||||||
retval{};
|
retval{};
|
||||||
|
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this,
|
*this,
|
||||||
first_,
|
first_,
|
||||||
@@ -4304,10 +4320,11 @@ namespace boost { namespace parser {
|
|||||||
detail::in_apply_parser(flags) ? detail::disable_trace(flags)
|
detail::in_apply_parser(flags) ? detail::disable_trace(flags)
|
||||||
: flags,
|
: flags,
|
||||||
retval);
|
retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
std::decay_t<decltype(parser::get(temp_result, llong<1>{}))>
|
std::decay_t<decltype(parser::get(std::declval<temp_result_t>(), llong<1>{}))>
|
||||||
indices;
|
indices;
|
||||||
std::decay_t<decltype(parser::get(temp_result, llong<2>{}))>
|
std::decay_t<decltype(parser::get(std::declval<temp_result_t>(), llong<2>{}))>
|
||||||
merged;
|
merged;
|
||||||
call_impl(
|
call_impl(
|
||||||
first,
|
first,
|
||||||
@@ -4326,7 +4343,7 @@ namespace boost { namespace parser {
|
|||||||
// A 1-tuple is converted to a scalar.
|
// A 1-tuple is converted to a scalar.
|
||||||
if constexpr (detail::hl::size(retval) == llong<1>{}) {
|
if constexpr (detail::hl::size(retval) == llong<1>{}) {
|
||||||
using namespace literals;
|
using namespace literals;
|
||||||
return parser::get(retval, 0_c);
|
return parser::get(std::move(retval), 0_c);
|
||||||
} else {
|
} else {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -4347,6 +4364,7 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this,
|
*this,
|
||||||
first_,
|
first_,
|
||||||
@@ -4355,16 +4373,17 @@ namespace boost { namespace parser {
|
|||||||
detail::in_apply_parser(flags) ? detail::disable_trace(flags)
|
detail::in_apply_parser(flags) ? detail::disable_trace(flags)
|
||||||
: flags,
|
: flags,
|
||||||
retval);
|
retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
Iter first = first_;
|
Iter first = first_;
|
||||||
|
|
||||||
auto temp_result =
|
using temp_result_t =
|
||||||
make_temp_result(first, last, context, skip, flags, success);
|
decltype(make_temp_result(first, last, context, skip, flags, success));
|
||||||
using temp_result_attr_t =
|
using temp_result_attr_t =
|
||||||
std::decay_t<decltype(parser::get(temp_result, llong<0>{}))>;
|
std::decay_t<decltype(parser::get(std::declval<temp_result_t>(), llong<0>{}))>;
|
||||||
std::decay_t<decltype(parser::get(temp_result, llong<1>{}))>
|
std::decay_t<decltype(parser::get(std::declval<temp_result_t>(), llong<1>{}))>
|
||||||
indices;
|
indices;
|
||||||
std::decay_t<decltype(parser::get(temp_result, llong<2>{}))> merged;
|
std::decay_t<decltype(parser::get(std::declval<temp_result_t>(), llong<2>{}))> merged;
|
||||||
|
|
||||||
auto max_ = [](auto result, auto x) {
|
auto max_ = [](auto result, auto x) {
|
||||||
if constexpr (decltype(result)::value < decltype(x)::value) {
|
if constexpr (decltype(result)::value < decltype(x)::value) {
|
||||||
@@ -4562,7 +4581,7 @@ namespace boost { namespace parser {
|
|||||||
using just_out = detail::remove_cv_ref_t<decltype(out)>;
|
using just_out = detail::remove_cv_ref_t<decltype(out)>;
|
||||||
if constexpr (detail::is_nope_v<attr_t>) {
|
if constexpr (detail::is_nope_v<attr_t>) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
} if constexpr (
|
} else if constexpr (
|
||||||
(!out_container ||
|
(!out_container ||
|
||||||
!std::is_same_v<just_x, just_out>) &&
|
!std::is_same_v<just_x, just_out>) &&
|
||||||
std::is_assignable_v<just_out &, just_x &&> &&
|
std::is_assignable_v<just_out &, just_x &&> &&
|
||||||
@@ -4578,7 +4597,9 @@ namespace boost { namespace parser {
|
|||||||
|
|
||||||
auto const parsers_and_indices =
|
auto const parsers_and_indices =
|
||||||
detail::hl::zip(parsers_, indices, merged, backtracking{});
|
detail::hl::zip(parsers_, indices, merged, backtracking{});
|
||||||
detail::hl::for_each(parsers_and_indices, use_parser);
|
std::apply([&use_parser](auto&&... args) {
|
||||||
|
((use_parser(args)), ...);
|
||||||
|
}, parsers_and_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool AllowBacktracking, typename Parser>
|
template<bool AllowBacktracking, typename Parser>
|
||||||
@@ -4699,8 +4720,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto const initial_first = first;
|
auto const initial_first = first;
|
||||||
auto attr = parser_.call(
|
auto attr = parser_.call(
|
||||||
@@ -4765,8 +4788,10 @@ namespace boost { namespace parser {
|
|||||||
detail::flags flags,
|
detail::flags flags,
|
||||||
bool & success) const
|
bool & success) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, detail::global_nope);
|
*this, first, last, context, flags, detail::global_nope);
|
||||||
|
#endif
|
||||||
auto attr =
|
auto attr =
|
||||||
parser_.call(first, last, context, skip, flags, success);
|
parser_.call(first, last, context, skip, flags, success);
|
||||||
if (success && detail::gen_attrs(flags))
|
if (success && detail::gen_attrs(flags))
|
||||||
@@ -4790,8 +4815,11 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto attr =
|
auto attr =
|
||||||
parser_.call(first, last, context, skip, flags, success);
|
parser_.call(first, last, context, skip, flags, success);
|
||||||
if (success && detail::gen_attrs(flags))
|
if (success && detail::gen_attrs(flags))
|
||||||
@@ -4818,8 +4846,10 @@ namespace boost { namespace parser {
|
|||||||
detail::flags flags,
|
detail::flags flags,
|
||||||
bool & success) const
|
bool & success) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, detail::global_nope);
|
*this, first, last, context, flags, detail::global_nope);
|
||||||
|
#endif
|
||||||
|
|
||||||
parser_.call(
|
parser_.call(
|
||||||
first,
|
first,
|
||||||
@@ -4846,8 +4876,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
parser_.call(
|
parser_.call(
|
||||||
first,
|
first,
|
||||||
@@ -4897,8 +4929,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto const initial_first = first;
|
auto const initial_first = first;
|
||||||
parser_.call(
|
parser_.call(
|
||||||
@@ -4962,8 +4996,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto const initial_first = first;
|
auto const initial_first = first;
|
||||||
parser_.call(
|
parser_.call(
|
||||||
@@ -5038,8 +5074,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
parser_.call(
|
parser_.call(
|
||||||
first,
|
first,
|
||||||
@@ -5098,8 +5136,10 @@ namespace boost { namespace parser {
|
|||||||
auto context = context_;
|
auto context = context_;
|
||||||
++context.no_case_depth_;
|
++context.no_case_depth_;
|
||||||
|
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
parser_.call(first, last, context, skip, flags, success, retval);
|
parser_.call(first, last, context, skip, flags, success, retval);
|
||||||
}
|
}
|
||||||
@@ -5145,8 +5185,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
if constexpr (detail::is_nope_v<SkipParser>) {
|
if constexpr (detail::is_nope_v<SkipParser>) {
|
||||||
parser_.call(
|
parser_.call(
|
||||||
@@ -5209,8 +5251,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto first_copy = first;
|
auto first_copy = first;
|
||||||
parser_.call(
|
parser_.call(
|
||||||
@@ -5376,8 +5420,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto [trie, _0] = detail::get_trie(context, ref());
|
auto [trie, _0] = detail::get_trie(context, ref());
|
||||||
auto const lookup = context.no_case_depth_
|
auto const lookup = context.no_case_depth_
|
||||||
@@ -5451,8 +5497,10 @@ namespace boost { namespace parser {
|
|||||||
tag_type * const tag_ptr = nullptr;
|
tag_type * const tag_ptr = nullptr;
|
||||||
auto const rule_context = detail::make_rule_context(
|
auto const rule_context = detail::make_rule_context(
|
||||||
context, tag_ptr, retval, locals, params);
|
context, tag_ptr, retval, locals, params);
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, rule_context, flags, retval);
|
*this, first, last, rule_context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool dont_assign = false;
|
bool dont_assign = false;
|
||||||
if constexpr (in_recursion) {
|
if constexpr (in_recursion) {
|
||||||
@@ -5481,7 +5529,7 @@ namespace boost { namespace parser {
|
|||||||
dont_assign);
|
dont_assign);
|
||||||
if (success && !dont_assign) {
|
if (success && !dont_assign) {
|
||||||
if constexpr (!detail::is_nope_v<decltype(attr)>)
|
if constexpr (!detail::is_nope_v<decltype(attr)>)
|
||||||
detail::assign(retval, attr);
|
detail::assign(retval, std::move(attr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5545,11 +5593,14 @@ namespace boost { namespace parser {
|
|||||||
locals_type locals = detail::make_locals<locals_type>(context);
|
locals_type locals = detail::make_locals<locals_type>(context);
|
||||||
auto params = detail::resolve_rule_params(context, params_);
|
auto params = detail::resolve_rule_params(context, params_);
|
||||||
tag_type * const tag_ptr = nullptr;
|
tag_type * const tag_ptr = nullptr;
|
||||||
|
attr_type attr{};
|
||||||
auto const rule_context = detail::make_rule_context(
|
auto const rule_context = detail::make_rule_context(
|
||||||
context, tag_ptr, retval, locals, params);
|
context, tag_ptr, attr, locals, params);
|
||||||
|
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, rule_context, flags, retval);
|
*this, first, last, rule_context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool dont_assign = false;
|
bool dont_assign = false;
|
||||||
parse_rule(
|
parse_rule(
|
||||||
@@ -5561,9 +5612,22 @@ namespace boost { namespace parser {
|
|||||||
flags,
|
flags,
|
||||||
success,
|
success,
|
||||||
dont_assign,
|
dont_assign,
|
||||||
retval);
|
attr);
|
||||||
if (!success || dont_assign)
|
|
||||||
retval = Attribute_();
|
if (dont_assign)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
attr = attr_type{};
|
||||||
|
|
||||||
|
if constexpr (detail::is_nope_v<decltype(attr)>) {
|
||||||
|
return;
|
||||||
|
} else if constexpr (
|
||||||
|
container<Attribute_> && container<attr_type>) {
|
||||||
|
detail::move_back(retval, attr, detail::gen_attrs(flags));
|
||||||
|
} else {
|
||||||
|
detail::assign(retval, std::move(attr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6726,8 +6790,10 @@ namespace boost { namespace parser {
|
|||||||
detail::flags flags,
|
detail::flags flags,
|
||||||
bool & success) const noexcept
|
bool & success) const noexcept
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, detail::global_nope);
|
*this, first, last, context, flags, detail::global_nope);
|
||||||
|
#endif
|
||||||
BOOST_PARSER_SUBRANGE const where(first, first);
|
BOOST_PARSER_SUBRANGE const where(first, first);
|
||||||
auto const predicate_context = detail::make_action_context(
|
auto const predicate_context = detail::make_action_context(
|
||||||
context, detail::global_nope, where);
|
context, detail::global_nope, where);
|
||||||
@@ -6754,8 +6820,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
BOOST_PARSER_SUBRANGE const where(first, first);
|
BOOST_PARSER_SUBRANGE const where(first, first);
|
||||||
auto const predicate_context = detail::make_action_context(
|
auto const predicate_context = detail::make_action_context(
|
||||||
context, detail::global_nope, where);
|
context, detail::global_nope, where);
|
||||||
@@ -6805,8 +6873,10 @@ namespace boost { namespace parser {
|
|||||||
detail::flags flags,
|
detail::flags flags,
|
||||||
bool & success) const
|
bool & success) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, detail::global_nope);
|
*this, first, last, context, flags, detail::global_nope);
|
||||||
|
#endif
|
||||||
if (first != last)
|
if (first != last)
|
||||||
success = false;
|
success = false;
|
||||||
return {};
|
return {};
|
||||||
@@ -6827,8 +6897,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
if (first != last)
|
if (first != last)
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@@ -6857,8 +6929,10 @@ namespace boost { namespace parser {
|
|||||||
detail::flags flags,
|
detail::flags flags,
|
||||||
bool &) const
|
bool &) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, detail::global_nope);
|
*this, first, last, context, flags, detail::global_nope);
|
||||||
|
#endif
|
||||||
return detail::resolve(context, attr_);
|
return detail::resolve(context, attr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6877,8 +6951,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute_ & retval) const
|
Attribute_ & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
if (detail::gen_attrs(flags))
|
if (detail::gen_attrs(flags))
|
||||||
detail::assign_copy(retval, detail::resolve(context, attr_));
|
detail::assign_copy(retval, detail::resolve(context, attr_));
|
||||||
}
|
}
|
||||||
@@ -6943,8 +7019,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (first == last) {
|
if (first == last) {
|
||||||
success = false;
|
success = false;
|
||||||
@@ -7108,8 +7186,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (first == last) {
|
if (first == last) {
|
||||||
success = false;
|
success = false;
|
||||||
@@ -7259,8 +7339,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (first == last) {
|
if (first == last) {
|
||||||
success = false;
|
success = false;
|
||||||
@@ -7339,8 +7421,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (first == last) {
|
if (first == last) {
|
||||||
success = false;
|
success = false;
|
||||||
@@ -7461,8 +7545,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (first == last) {
|
if (first == last) {
|
||||||
success = false;
|
success = false;
|
||||||
@@ -7625,8 +7711,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (first == last) {
|
if (first == last) {
|
||||||
success = false;
|
success = false;
|
||||||
@@ -7635,9 +7723,10 @@ namespace boost { namespace parser {
|
|||||||
|
|
||||||
auto const prev_first = first;
|
auto const prev_first = first;
|
||||||
|
|
||||||
auto append = [&retval,
|
std::string temp;
|
||||||
|
auto append = [&temp,
|
||||||
gen_attrs = detail::gen_attrs(flags)](auto & ctx) {
|
gen_attrs = detail::gen_attrs(flags)](auto & ctx) {
|
||||||
detail::move_back(retval, _attr(ctx), gen_attrs);
|
detail::move_back(temp, _attr(ctx), gen_attrs);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto quote_ch = [&]() {
|
auto quote_ch = [&]() {
|
||||||
@@ -7695,7 +7784,10 @@ namespace boost { namespace parser {
|
|||||||
detail::disable_skip(flags),
|
detail::disable_skip(flags),
|
||||||
success);
|
success);
|
||||||
|
|
||||||
if (!success) {
|
if (success) {
|
||||||
|
if (detail::gen_attrs(flags))
|
||||||
|
detail::assign(retval, std::move(temp));
|
||||||
|
} else {
|
||||||
retval = Attribute();
|
retval = Attribute();
|
||||||
first = prev_first;
|
first = prev_first;
|
||||||
}
|
}
|
||||||
@@ -7942,8 +8034,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (first == last) {
|
if (first == last) {
|
||||||
success = false;
|
success = false;
|
||||||
@@ -8109,8 +8203,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto compare =
|
auto compare =
|
||||||
[no_case = context.no_case_depth_](char32_t a, char32_t b) {
|
[no_case = context.no_case_depth_](char32_t a, char32_t b) {
|
||||||
@@ -8198,8 +8294,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
T attr = 0;
|
T attr = 0;
|
||||||
auto const initial = first;
|
auto const initial = first;
|
||||||
success =
|
success =
|
||||||
@@ -8339,8 +8437,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
T attr = 0;
|
T attr = 0;
|
||||||
auto const initial = first;
|
auto const initial = first;
|
||||||
success =
|
success =
|
||||||
@@ -8454,8 +8554,10 @@ namespace boost { namespace parser {
|
|||||||
bool & success,
|
bool & success,
|
||||||
Attribute & retval) const
|
Attribute & retval) const
|
||||||
{
|
{
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
T attr = 0;
|
T attr = 0;
|
||||||
auto const initial = first;
|
auto const initial = first;
|
||||||
success = detail::numeric::parse_real(first, last, attr);
|
success = detail::numeric::parse_real(first, last, attr);
|
||||||
@@ -8521,9 +8623,9 @@ namespace boost { namespace parser {
|
|||||||
template<typename SwitchValue, typename OrParser>
|
template<typename SwitchValue, typename OrParser>
|
||||||
struct switch_parser
|
struct switch_parser
|
||||||
{
|
{
|
||||||
switch_parser() {}
|
constexpr switch_parser() {}
|
||||||
switch_parser(SwitchValue switch_value) : switch_value_(switch_value) {}
|
constexpr switch_parser(SwitchValue switch_value) : switch_value_(switch_value) {}
|
||||||
switch_parser(SwitchValue switch_value, OrParser or_parser) :
|
constexpr switch_parser(SwitchValue switch_value, OrParser or_parser) :
|
||||||
switch_value_(switch_value), or_parser_(or_parser)
|
switch_value_(switch_value), or_parser_(or_parser)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -8548,8 +8650,10 @@ namespace boost { namespace parser {
|
|||||||
using attr_t = decltype(or_parser_.call(
|
using attr_t = decltype(or_parser_.call(
|
||||||
first, last, context, skip, flags, success));
|
first, last, context, skip, flags, success));
|
||||||
attr_t attr{};
|
attr_t attr{};
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ =
|
[[maybe_unused]] auto _ =
|
||||||
detail::scoped_trace(*this, first, last, context, flags, attr);
|
detail::scoped_trace(*this, first, last, context, flags, attr);
|
||||||
|
#endif
|
||||||
attr = or_parser_.call(first, last, context, skip, flags, success);
|
attr = or_parser_.call(first, last, context, skip, flags, success);
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
@@ -8574,8 +8678,10 @@ namespace boost { namespace parser {
|
|||||||
"It looks like you tried to write switch_(val). You need at "
|
"It looks like you tried to write switch_(val). You need at "
|
||||||
"least one alternative, like: switch_(val)(value_1, "
|
"least one alternative, like: switch_(val)(value_1, "
|
||||||
"parser_1)(value_2, parser_2)..."));
|
"parser_1)(value_2, parser_2)..."));
|
||||||
|
#if BOOST_PARSER_DO_TRACE
|
||||||
[[maybe_unused]] auto _ = detail::scoped_trace(
|
[[maybe_unused]] auto _ = detail::scoped_trace(
|
||||||
*this, first, last, context, flags, retval);
|
*this, first, last, context, flags, retval);
|
||||||
|
#endif
|
||||||
or_parser_.call(first, last, context, skip, flags, success, retval);
|
or_parser_.call(first, last, context, skip, flags, success, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9034,8 +9140,13 @@ namespace boost { namespace parser {
|
|||||||
"fill in attr above, using the attribute generated by parser. "
|
"fill in attr above, using the attribute generated by parser. "
|
||||||
"However, parser does not generate an attribute.");
|
"However, parser does not generate an attribute.");
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return reset = detail::parse_impl<true>(
|
return reset =
|
||||||
first, last, parser, parser.error_handler_, attr);
|
detail::parse_impl<(true && BOOST_PARSER_DO_TRACE)>(
|
||||||
|
first,
|
||||||
|
last,
|
||||||
|
parser,
|
||||||
|
parser.error_handler_,
|
||||||
|
attr);
|
||||||
} else {
|
} else {
|
||||||
return reset = detail::parse_impl<false>(
|
return reset = detail::parse_impl<false>(
|
||||||
first, last, parser, parser.error_handler_, attr);
|
first, last, parser, parser.error_handler_, attr);
|
||||||
@@ -9052,8 +9163,9 @@ namespace boost { namespace parser {
|
|||||||
"fill in attr above, using the attribute generated by parser. "
|
"fill in attr above, using the attribute generated by parser. "
|
||||||
"However, parser does not generate an attribute.");
|
"However, parser does not generate an attribute.");
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return reset = detail::parse_impl<true>(
|
return reset =
|
||||||
f, l, parser, parser.error_handler_, attr);
|
detail::parse_impl<(true && BOOST_PARSER_DO_TRACE)>(
|
||||||
|
f, l, parser, parser.error_handler_, attr);
|
||||||
} else {
|
} else {
|
||||||
return reset = detail::parse_impl<false>(
|
return reset = detail::parse_impl<false>(
|
||||||
f, l, parser, parser.error_handler_, attr);
|
f, l, parser, parser.error_handler_, attr);
|
||||||
@@ -9156,7 +9268,7 @@ namespace boost { namespace parser {
|
|||||||
{
|
{
|
||||||
if constexpr (!detail::is_char8_iter_v<I>) {
|
if constexpr (!detail::is_char8_iter_v<I>) {
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return detail::parse_impl<true>(
|
return detail::parse_impl<(true && BOOST_PARSER_DO_TRACE)>(
|
||||||
first, last, parser, parser.error_handler_);
|
first, last, parser, parser.error_handler_);
|
||||||
} else {
|
} else {
|
||||||
return detail::parse_impl<false>(
|
return detail::parse_impl<false>(
|
||||||
@@ -9169,7 +9281,7 @@ namespace boost { namespace parser {
|
|||||||
auto const l = r.end();
|
auto const l = r.end();
|
||||||
auto _ = detail::scoped_base_assign(first, f);
|
auto _ = detail::scoped_base_assign(first, f);
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return detail::parse_impl<true>(
|
return detail::parse_impl<(true && BOOST_PARSER_DO_TRACE)>(
|
||||||
f, l, parser, parser.error_handler_);
|
f, l, parser, parser.error_handler_);
|
||||||
} else {
|
} else {
|
||||||
return detail::parse_impl<false>(
|
return detail::parse_impl<false>(
|
||||||
@@ -9275,7 +9387,8 @@ namespace boost { namespace parser {
|
|||||||
"fill in attr above, using the attribute generated by parser. "
|
"fill in attr above, using the attribute generated by parser. "
|
||||||
"However, parser does not generate an attribute.");
|
"However, parser does not generate an attribute.");
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return reset = detail::skip_parse_impl<true>(
|
return reset = detail::skip_parse_impl<(
|
||||||
|
true && BOOST_PARSER_DO_TRACE)>(
|
||||||
first,
|
first,
|
||||||
last,
|
last,
|
||||||
parser,
|
parser,
|
||||||
@@ -9303,7 +9416,8 @@ namespace boost { namespace parser {
|
|||||||
"fill in attr above, using the attribute generated by parser. "
|
"fill in attr above, using the attribute generated by parser. "
|
||||||
"However, parser does not generate an attribute.");
|
"However, parser does not generate an attribute.");
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return reset = detail::skip_parse_impl<true>(
|
return reset = detail::skip_parse_impl<(
|
||||||
|
true && BOOST_PARSER_DO_TRACE)>(
|
||||||
f, l, parser, skip, parser.error_handler_, attr);
|
f, l, parser, skip, parser.error_handler_, attr);
|
||||||
} else {
|
} else {
|
||||||
return reset = detail::skip_parse_impl<false>(
|
return reset = detail::skip_parse_impl<false>(
|
||||||
@@ -9408,7 +9522,7 @@ namespace boost { namespace parser {
|
|||||||
{
|
{
|
||||||
if constexpr (!detail::is_char8_iter_v<I>) {
|
if constexpr (!detail::is_char8_iter_v<I>) {
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return detail::skip_parse_impl<true>(
|
return detail::skip_parse_impl<(true && BOOST_PARSER_DO_TRACE)>(
|
||||||
first, last, parser, skip, parser.error_handler_);
|
first, last, parser, skip, parser.error_handler_);
|
||||||
} else {
|
} else {
|
||||||
return detail::skip_parse_impl<false>(
|
return detail::skip_parse_impl<false>(
|
||||||
@@ -9421,7 +9535,7 @@ namespace boost { namespace parser {
|
|||||||
auto const l = r.end();
|
auto const l = r.end();
|
||||||
auto _ = detail::scoped_base_assign(first, f);
|
auto _ = detail::scoped_base_assign(first, f);
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return detail::skip_parse_impl<true>(
|
return detail::skip_parse_impl<(true && BOOST_PARSER_DO_TRACE)>(
|
||||||
f, l, parser, skip, parser.error_handler_);
|
f, l, parser, skip, parser.error_handler_);
|
||||||
} else {
|
} else {
|
||||||
return detail::skip_parse_impl<false>(
|
return detail::skip_parse_impl<false>(
|
||||||
@@ -9525,7 +9639,8 @@ namespace boost { namespace parser {
|
|||||||
{
|
{
|
||||||
if constexpr (!detail::is_char8_iter_v<I>) {
|
if constexpr (!detail::is_char8_iter_v<I>) {
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return detail::callback_parse_impl<true>(
|
return detail::callback_parse_impl<(
|
||||||
|
true && BOOST_PARSER_DO_TRACE)>(
|
||||||
first, last, parser, parser.error_handler_, callbacks);
|
first, last, parser, parser.error_handler_, callbacks);
|
||||||
} else {
|
} else {
|
||||||
return detail::callback_parse_impl<false>(
|
return detail::callback_parse_impl<false>(
|
||||||
@@ -9538,7 +9653,8 @@ namespace boost { namespace parser {
|
|||||||
auto const l = r.end();
|
auto const l = r.end();
|
||||||
auto _ = detail::scoped_base_assign(first, f);
|
auto _ = detail::scoped_base_assign(first, f);
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return detail::callback_parse_impl<true>(
|
return detail::callback_parse_impl<(
|
||||||
|
true && BOOST_PARSER_DO_TRACE)>(
|
||||||
f, l, parser, parser.error_handler_, callbacks);
|
f, l, parser, parser.error_handler_, callbacks);
|
||||||
} else {
|
} else {
|
||||||
return detail::callback_parse_impl<false>(
|
return detail::callback_parse_impl<false>(
|
||||||
@@ -9650,7 +9766,8 @@ namespace boost { namespace parser {
|
|||||||
{
|
{
|
||||||
if constexpr (!detail::is_char8_iter_v<I>) {
|
if constexpr (!detail::is_char8_iter_v<I>) {
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return detail::callback_skip_parse_impl<true>(
|
return detail::callback_skip_parse_impl<(
|
||||||
|
true && BOOST_PARSER_DO_TRACE)>(
|
||||||
first,
|
first,
|
||||||
last,
|
last,
|
||||||
parser,
|
parser,
|
||||||
@@ -9673,7 +9790,8 @@ namespace boost { namespace parser {
|
|||||||
auto const l = r.end();
|
auto const l = r.end();
|
||||||
auto _ = detail::scoped_base_assign(first, f);
|
auto _ = detail::scoped_base_assign(first, f);
|
||||||
if (trace_mode == trace::on) {
|
if (trace_mode == trace::on) {
|
||||||
return detail::callback_skip_parse_impl<true>(
|
return detail::callback_skip_parse_impl<(
|
||||||
|
true && BOOST_PARSER_DO_TRACE)>(
|
||||||
f, l, parser, skip, parser.error_handler_, callbacks);
|
f, l, parser, skip, parser.error_handler_, callbacks);
|
||||||
} else {
|
} else {
|
||||||
return detail::callback_skip_parse_impl<false>(
|
return detail::callback_skip_parse_impl<false>(
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ add_test_executable(parser_seq_permutations_1)
|
|||||||
add_test_executable(parser_seq_permutations_2)
|
add_test_executable(parser_seq_permutations_2)
|
||||||
add_test_executable(parser_or_permutations_1)
|
add_test_executable(parser_or_permutations_1)
|
||||||
add_test_executable(parser_or_permutations_2)
|
add_test_executable(parser_or_permutations_2)
|
||||||
|
add_test_executable(disable_trace)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
add_executable(vs_output_tracing tracing.cpp)
|
add_executable(vs_output_tracing tracing.cpp)
|
||||||
|
|||||||
27
test/disable_trace.cpp
Normal file
27
test/disable_trace.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2025
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See
|
||||||
|
* accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BOOST_PARSER_DISABLE_TRACE
|
||||||
|
|
||||||
|
#include <boost/core/lightweight_test.hpp>
|
||||||
|
#include <boost/parser/parser.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
namespace bp = boost::parser;
|
||||||
|
{
|
||||||
|
auto const parser =
|
||||||
|
bp::string("FOO") >> -(bp::string("bar") | bp::string("foo"));
|
||||||
|
|
||||||
|
auto result = bp::parse("FOOfoo", parser);
|
||||||
|
BOOST_TEST(result);
|
||||||
|
BOOST_TEST(bp::get(*result, bp::llong<0>{}) == std::string("FOO"));
|
||||||
|
BOOST_TEST(bp::get(*result, bp::llong<1>{}) == std::string("foo"));
|
||||||
|
}
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
@@ -501,6 +501,282 @@ void github_issue_285()
|
|||||||
BOOST_TEST(result.value().get() != nullptr);
|
BOOST_TEST(result.value().get() != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void github_pr_290()
|
||||||
|
{
|
||||||
|
namespace bp = boost::parser;
|
||||||
|
|
||||||
|
auto const pTest = bp::lit("TEST:") > -bp::quoted_string;
|
||||||
|
|
||||||
|
auto result = bp::parse("TEST: \"foo\"", pTest, bp::blank);
|
||||||
|
BOOST_TEST(result);
|
||||||
|
BOOST_TEST(*result == "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace github_issue_294_ {
|
||||||
|
namespace bp = boost::parser;
|
||||||
|
struct Foo
|
||||||
|
{};
|
||||||
|
constexpr bp::rule<struct foo_parser_tag, std::shared_ptr<Foo>> foo_parser =
|
||||||
|
"foo_parser";
|
||||||
|
constexpr auto foo_parser_action = [](auto & ctx) {
|
||||||
|
std::shared_ptr<Foo> & val = _val(ctx);
|
||||||
|
val = std::shared_ptr<Foo>(new Foo{});
|
||||||
|
};
|
||||||
|
constexpr auto foo_parser_def = bp::eps[foo_parser_action];
|
||||||
|
struct Bar
|
||||||
|
{
|
||||||
|
std::shared_ptr<Foo> foo;
|
||||||
|
};
|
||||||
|
constexpr bp::rule<struct bar_parser_tag, std::shared_ptr<Bar>> bar_parser =
|
||||||
|
"bar_parser";
|
||||||
|
constexpr auto bar_parser_action = [](auto & ctx) {
|
||||||
|
std::shared_ptr<Bar> & val = _val(ctx);
|
||||||
|
val = std::shared_ptr<Bar>(new Bar{});
|
||||||
|
std::optional<std::shared_ptr<Foo>> & attr = _attr(ctx);
|
||||||
|
if (attr) {
|
||||||
|
val->foo = attr.value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
constexpr auto bar_parser_def =
|
||||||
|
(bp::lit("(") > -foo_parser > bp::lit(")"))[bar_parser_action];
|
||||||
|
|
||||||
|
BOOST_PARSER_DEFINE_RULES(bar_parser, foo_parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void github_issue_294()
|
||||||
|
{
|
||||||
|
namespace bp = boost::parser;
|
||||||
|
using namespace github_issue_294_;
|
||||||
|
|
||||||
|
bp::parse("()", bar_parser, bp::blank);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace github_pr_297_ {
|
||||||
|
namespace bp = boost::parser;
|
||||||
|
constexpr auto bar_required_f = [](auto& ctx) -> bool {
|
||||||
|
const bool& argument = bp::_p<0>(ctx);
|
||||||
|
return argument;
|
||||||
|
};
|
||||||
|
constexpr bp::rule<struct foobar_parser_tag> foobar_parser = "foobar_parser";
|
||||||
|
constexpr auto foobar_parser_def =
|
||||||
|
bp::lit("foo")
|
||||||
|
>> bp::switch_(bar_required_f)
|
||||||
|
(true, bp::lit("bar"))
|
||||||
|
(false, -bp::lit("bar"));
|
||||||
|
BOOST_PARSER_DEFINE_RULES(foobar_parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void github_pr_297()
|
||||||
|
{
|
||||||
|
namespace bp = boost::parser;
|
||||||
|
using namespace github_pr_297_;
|
||||||
|
|
||||||
|
{
|
||||||
|
const bool bar_required = true;
|
||||||
|
const bool result =
|
||||||
|
bp::parse("foo bar", foobar_parser.with(bar_required), bp::blank);
|
||||||
|
BOOST_TEST(result);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const bool bar_required = true;
|
||||||
|
const bool result =
|
||||||
|
bp::parse("foo", foobar_parser.with(bar_required), bp::blank);
|
||||||
|
BOOST_TEST(!result);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const bool bar_required = false;
|
||||||
|
const bool result =
|
||||||
|
bp::parse("foo bar", foobar_parser.with(bar_required), bp::blank);
|
||||||
|
BOOST_TEST(result);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const bool bar_required = false;
|
||||||
|
const bool result =
|
||||||
|
bp::parse("foo", foobar_parser.with(bar_required), bp::blank);
|
||||||
|
BOOST_TEST(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace github_issue_312_ {
|
||||||
|
/*
|
||||||
|
* Recursive descent parser for expressions.
|
||||||
|
* Supports addition (+), multiplication (*) and
|
||||||
|
* parethesized expressions, nothing else.
|
||||||
|
*
|
||||||
|
* Creates a tree of "evaluatable" objects which
|
||||||
|
* own their downstream objects in a unique_ptr
|
||||||
|
*/
|
||||||
|
|
||||||
|
// base class for all tree nodes
|
||||||
|
struct evaluatable
|
||||||
|
{
|
||||||
|
virtual double evaluate() = 0;
|
||||||
|
virtual ~evaluatable() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace bp = boost::parser;
|
||||||
|
|
||||||
|
// top level parser
|
||||||
|
constexpr bp::rule<struct expression_tag, std::unique_ptr<evaluatable>> expression_parser = "expression_parser";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LITERAL EXPRESSION
|
||||||
|
*/
|
||||||
|
struct literal_evaluatable : evaluatable
|
||||||
|
{
|
||||||
|
explicit literal_evaluatable(double v) : value_(v) {}
|
||||||
|
double evaluate() override
|
||||||
|
{
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
double value_;
|
||||||
|
};
|
||||||
|
constexpr bp::rule<struct literal_tag, std::unique_ptr<evaluatable>> literal_parser = "literal_parser";
|
||||||
|
constexpr auto literal_parser_action = [](auto& ctx) {
|
||||||
|
std::unique_ptr<evaluatable>& val = _val(ctx);
|
||||||
|
double& parsed_value = _attr(ctx);
|
||||||
|
val = std::make_unique<literal_evaluatable>(parsed_value);
|
||||||
|
};
|
||||||
|
constexpr auto literal_parser_def =
|
||||||
|
bp::double_[literal_parser_action];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PARENTHESIZED EXPRESSION
|
||||||
|
*/
|
||||||
|
struct parenthesized_evaluatable : evaluatable
|
||||||
|
{
|
||||||
|
explicit parenthesized_evaluatable(std::unique_ptr<evaluatable>&& e) : evaluatable_(std::move(e)) {}
|
||||||
|
double evaluate() override
|
||||||
|
{
|
||||||
|
return evaluatable_->evaluate();
|
||||||
|
}
|
||||||
|
std::unique_ptr<evaluatable> evaluatable_;
|
||||||
|
};
|
||||||
|
constexpr bp::rule<struct parenthesized_tag, std::unique_ptr<evaluatable>> parenthesized_parser = "parenthesized_parser";
|
||||||
|
constexpr auto parenthesized_action = [](auto& ctx) {
|
||||||
|
std::unique_ptr<evaluatable>& val = _val(ctx);
|
||||||
|
std::unique_ptr<evaluatable>& attr = _attr(ctx);
|
||||||
|
val = std::make_unique<parenthesized_evaluatable>(std::move(attr));
|
||||||
|
};
|
||||||
|
constexpr auto parenthesized_parser_def =
|
||||||
|
(
|
||||||
|
bp::lit('(') > expression_parser > bp::lit(')')
|
||||||
|
)[parenthesized_action];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ATOM EXPRESSION
|
||||||
|
*/
|
||||||
|
struct atom_evaluatable : evaluatable
|
||||||
|
{
|
||||||
|
explicit atom_evaluatable(std::unique_ptr<evaluatable>&& e) : evaluatable_(std::move(e)) {}
|
||||||
|
double evaluate() override
|
||||||
|
{
|
||||||
|
return evaluatable_->evaluate();
|
||||||
|
}
|
||||||
|
std::unique_ptr<evaluatable> evaluatable_;
|
||||||
|
};
|
||||||
|
constexpr bp::rule<struct atom_tag, std::unique_ptr<evaluatable>> atom_parser = "atom_parser";
|
||||||
|
constexpr auto atom_action = [](auto& ctx) {
|
||||||
|
std::unique_ptr<evaluatable>& val = _val(ctx);
|
||||||
|
std::unique_ptr<evaluatable>& attr = _attr(ctx);
|
||||||
|
val = std::make_unique<atom_evaluatable>(std::move(attr));
|
||||||
|
};
|
||||||
|
constexpr auto atom_parser_def =
|
||||||
|
(
|
||||||
|
parenthesized_parser
|
||||||
|
|
|
||||||
|
literal_parser
|
||||||
|
)[atom_action];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MULTIPLICATION EXPRESSION
|
||||||
|
*/
|
||||||
|
struct multiplication_evaluatable : evaluatable
|
||||||
|
{
|
||||||
|
multiplication_evaluatable(std::vector<std::unique_ptr<evaluatable>>&& e)
|
||||||
|
: evaluatables_(std::move(e))
|
||||||
|
{}
|
||||||
|
double evaluate() override
|
||||||
|
{
|
||||||
|
double result = 1;
|
||||||
|
for (const auto& e : evaluatables_) {
|
||||||
|
result *= e->evaluate();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
std::vector<std::unique_ptr<evaluatable>> evaluatables_;
|
||||||
|
};
|
||||||
|
constexpr bp::rule<struct mult_tag, std::unique_ptr<evaluatable>> mult_parser = "mult_parser";
|
||||||
|
constexpr auto mult_parser_action = [](auto& ctx) {
|
||||||
|
std::unique_ptr<evaluatable>& val = _val(ctx);
|
||||||
|
std::vector<std::unique_ptr<evaluatable>>& operands = _attr(ctx);
|
||||||
|
val = std::make_unique<multiplication_evaluatable>(std::move(operands));
|
||||||
|
};
|
||||||
|
constexpr auto mult_parser_def =
|
||||||
|
(atom_parser % bp::lit('*'))[mult_parser_action];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ADDITION EXPRESSION
|
||||||
|
*/
|
||||||
|
struct addition_evaluatable : evaluatable
|
||||||
|
{
|
||||||
|
addition_evaluatable(std::vector<std::unique_ptr<evaluatable>>&& e)
|
||||||
|
: evaluatables_(std::move(e))
|
||||||
|
{}
|
||||||
|
double evaluate() override
|
||||||
|
{
|
||||||
|
double result = 0;
|
||||||
|
for (const auto& e : evaluatables_) {
|
||||||
|
result += e->evaluate();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
std::vector<std::unique_ptr<evaluatable>> evaluatables_;
|
||||||
|
};
|
||||||
|
constexpr bp::rule<struct add_tag, std::unique_ptr<evaluatable>> add_parser = "add_parser";
|
||||||
|
constexpr auto add_parser_action = [](auto& ctx) {
|
||||||
|
std::unique_ptr<evaluatable>& val = _val(ctx);
|
||||||
|
std::vector<std::unique_ptr<evaluatable>>& operands = _attr(ctx);
|
||||||
|
val = std::make_unique<addition_evaluatable>(std::move(operands));
|
||||||
|
};
|
||||||
|
constexpr auto add_parser_def =
|
||||||
|
(mult_parser % bp::lit('+'))[add_parser_action];
|
||||||
|
|
||||||
|
constexpr auto expression_parser_action = [](auto& ctx) {
|
||||||
|
std::unique_ptr<evaluatable>& val = _val(ctx);
|
||||||
|
std::unique_ptr<evaluatable>& attr = _attr(ctx);
|
||||||
|
val = std::move(attr);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EXPRESSION
|
||||||
|
*/
|
||||||
|
constexpr auto expression_parser_def =
|
||||||
|
add_parser[expression_parser_action];
|
||||||
|
|
||||||
|
BOOST_PARSER_DEFINE_RULES(
|
||||||
|
literal_parser,
|
||||||
|
mult_parser,
|
||||||
|
add_parser,
|
||||||
|
expression_parser,
|
||||||
|
parenthesized_parser,
|
||||||
|
atom_parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void github_issue_312()
|
||||||
|
{
|
||||||
|
namespace bp = boost::parser;
|
||||||
|
using namespace github_issue_312_;
|
||||||
|
|
||||||
|
auto result = bp::parse("(2 + 3) + 3.1415 * 2", expression_parser, bp::blank);
|
||||||
|
BOOST_TEST(result);
|
||||||
|
BOOST_TEST(result.value()->evaluate() == (2 + 3) + 3.1415 * 2);
|
||||||
|
|
||||||
|
result = bp::parse("((2*0.1) + 33.) * (2 + 3) + 3.1415 * 2", expression_parser, bp::blank);
|
||||||
|
BOOST_TEST(result);
|
||||||
|
BOOST_TEST(result.value()->evaluate() == ((2*0.1) + 33.) * (2 + 3) + 3.1415 * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -516,5 +792,9 @@ int main()
|
|||||||
github_issue_268();
|
github_issue_268();
|
||||||
github_issue_279();
|
github_issue_279();
|
||||||
github_issue_285();
|
github_issue_285();
|
||||||
|
github_pr_290();
|
||||||
|
github_issue_294();
|
||||||
|
github_pr_297();
|
||||||
|
github_issue_312();
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user