2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-22 05:22:32 +00:00
Files
parser/doc/rationale.qbk

192 lines
43 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[/
/ 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)
/]
[section Rationale]
[heading _ch_'s attribute type is polymorphic]
The majority use case for parsing with _Parser_ is Unicode-aware parsing.
Those users should be able simply to use _ch_ and have it "just work". In the
case of Unicode, that "just working" implies that every element of the input
range should be a code point.
Some users will insist that their parsing needs are entirely ASCII. Yet other
users cannot use Unicode, because they use some encoding that is not a subset
of the Unicode encoding, like EBCDIC. For these users, they can just parse
input sequences of `char`, and that will "just work" for them. For them, this
means that every element of the input range that is parsed should be a `char`.
This is exactly what _ch_ does, and why it does it.
[heading _n_ is weird]
Yes, and it's generally not a good programming practice to use a type which is
so loose (anything can be assigned to it, it's implicitly convertible to
anything, etc.). However, it is better than the alternative. Consider this
semantic action:
[](auto & ctx) { _attr(ctx) = 42; }
If attached to an int-parser, this is fine. If attached to an epsilon parser
(which has no attribute), this silently does nothing. However, in debug mode
the assignment in this semantic action will hit a `BOOST_ASSERT(false)`, and
lead the user to a big inline comment about how they got there. This is a far
more understandable failure mode for most programmers than the
arbitrarily-deep template instantiation stack _emdash_ and baffling type of
`ctx` _emdash_ that would result if the expression `_attr(ctx)` were
ill-formed.
The use of _n_ turns an entirely compile-time debugging operation into a
run-time debugging one. Usually, this is the opposite of what we want as C++
users. In light of just how inscrutable error messages are that come from
parser combinator libraries, using your favorite debugger to step through the
stack to diagnose the problem is a *much* faster way to fix problems.
[note The example below is taken from an older version of _Parser_, so some of
the symbol names may be unfamiliar. However, it's a real example, and it
applies just as well to later versions of _Parser_.]
To demonstrate the difference, I added these three lines to the end of the
`object_init` lambda in the _ex_json_:
auto x = _locals(ctx);
if (x)
std::cout << "Oops! What x?";
The parser that `object_init` is attached to has no locals. Here is an
example of how you can investigate this error at run time:
[teletype]``
$ gdb --args example/json ../meta/libraries.json
GNU gdb (Ubuntu 9.1-0ubuntu1) 9.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from example/json...
(gdb) r
Starting program: /home/tzlaine/parser/build/example/json ../meta/libraries.json
json: /home/tzlaine/parser/include/boost/parser/parser.hpp:344: void boost::parser::none::fail() const: Assertion `false' failed.
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) up
#1 0x00007ffff7bdf859 in __GI_abort () at abort.c:79
79 abort.c: No such file or directory.
(gdb)
#2 0x00007ffff7bdf729 in __assert_fail_base (
fmt=0x7ffff7d75588 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n",
assertion=0x5555555f7a2c "false",
file=0x5555555f7dd8 "/home/tzlaine/parser/include/boost/parser/parser.hpp", line=344,
function=<optimized out>) at assert.c:92
92 assert.c: No such file or directory.
(gdb)
#3 0x00007ffff7bf0f36 in __GI___assert_fail (assertion=0x5555555f7a2c "false",
file=0x5555555f7dd8 "/home/tzlaine/parser/include/boost/parser/parser.hpp", line=344,
function=0x5555555f7db0 "void boost::parser::none::fail() const") at assert.c:101
101 in assert.c
(gdb)
#4 0x000055555555f99b in boost::parser::none::fail (this=0x7fffffffc2f0)
at /home/tzlaine/parser/include/boost/parser/parser.hpp:344
344 BOOST_ASSERT(false);
(gdb)
#5 0x000055555559d380 in boost::parser::none::operator bool<bool>() const (this=0x7fffffffc2f0)
at /home/tzlaine/parser/include/boost/parser/parser.hpp:83
83 fail();
(gdb)
#6 0x0000555555590a6b in _ZNK4json11object_initMUlRT_E_clIKN5boost4hana6detail8map_implINS6_10hash_tableIJNS6_6bucketINS4_6parser6detail9begin_tagEJLm0EEEENS9_INSB_7end_tagEJLm1EEEENS9_INSB_8pass_tagEJLm2EEEENS9_INSB_10locals_tagEJLm3EEEENS9_INSB_15rule_params_tagEJLm4EEEENS9_INSB_11globals_tagEJLm5EEEENS9_INSB_16trace_indent_tagEJLm6EEEENS9_INSB_17error_handler_tagEJLm7EEEENS9_INSB_13callbacks_tagEJLm8EEEENS9_INSB_22symbol_table_tries_tagEJLm9EEEENS9_INSB_7val_tagEJLm10EEEENS9_INSB_8attr_tagEJLm11EEEENS9_INSB_9where_tagEJLm12EEEEEEENS5_11basic_tupleIJNS5_4pairINS5_9type_implISC_E1_ENS4_4text20utf_8_to_32_iteratorIPKcS1B_NS18_25use_replacement_characterEEEEENS14_INS15_ISE_E1_ES1D_EENS14_INS15_ISG_E1_EPbEENS14_INS15_ISI_E1_ENSB_4nopeEEENS14_INS15_ISK_E1_ES1O_EENS14_INS15_ISM_E1_EPNS_12global_stateEEENS14_INS15_ISO_E1_EPiEENS14_INS15_ISQ_E1_EPKNSA_22callback_error_handlerEEENS14_INS15_ISS_E1_ES1O_EENS14_INS15_ISU_E1_EPSt3mapIPvNS4_3anyESt4lessIS2E_ESaISt4pairIKS2E_S2F_EEEEENS14_INS15_ISW_E1_EPNS_5valueEEENS14_INS15_ISY_E1_EPS1O_EENS14_INS15_IS10_E1_EPKNSA_4viewIS1D_S1D_EEEEEEEEEEEDaS1_ (__closure=0x7fffffffc9b1, ctx=...)
at /home/tzlaine/parser/example/json.cpp:103
103 if (x)
(gdb) l
98 auto & globals = _globals(ctx);
99 if (globals.max_recursive_open_count < ++globals.recursive_open_count)
100 throw excessive_nesting(_where(ctx).begin());
101 _val(ctx) = object();
102 auto x = _locals(ctx);
103 if (x)
104 std::cout << "Oops! What x?";
105 };
106
107 // We need object_insert because we can't just insert into the json::value
(gdb)
``
To find the problem, I just had to move up the stack, with GDB's "up" command,
until I saw that I was in my own code. Then I listed the code surrounding the
offending line, as you see above. If I were to keep going up the stack, I
would move through the exact chain of template instantiations _emdash_ at the
exact lines of code where they appear _emdash_ in a few seconds.
This is how the same problem looks with `BOOST_PARSER_NO_RUNTIME_ASSERTIONS`
defined, the definition of which makes the code we added ill-formed instead of
a run time error:
[teletype]``
$ make json
Scanning dependencies of target json
[ 50%] Building CXX object example/CMakeFiles/json.dir/json.cpp.o
/home/tzlaine/parser/example/json.cpp: In instantiation of json::<lambda(auto:58&)> [with auto:58 = const boost::hana::detail::map_impl<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::parser::detail::begin_tag, 0>, boost::hana::detail::bucket<boost::parser::detail::end_tag, 1>, boost::hana::detail::bucket<boost::parser::detail::pass_tag, 2>, boost::hana::detail::bucket<boost::parser::detail::locals_tag, 3>, boost::hana::detail::bucket<boost::parser::detail::rule_params_tag, 4>, boost::hana::detail::bucket<boost::parser::detail::globals_tag, 5>, boost::hana::detail::bucket<boost::parser::detail::trace_indent_tag, 6>, boost::hana::detail::bucket<boost::parser::detail::error_handler_tag, 7>, boost::hana::detail::bucket<boost::parser::detail::callbacks_tag, 8>, boost::hana::detail::bucket<boost::parser::detail::symbol_table_tries_tag, 9>, boost::hana::detail::bucket<boost::parser::detail::val_tag, 10>, boost::hana::detail::bucket<boost::parser::detail::attr_tag, 11>, boost::hana::detail::bucket<boost::parser::detail::where_tag, 12> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::type_impl<boost::parser::detail::begin_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::end_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::pass_tag>::_, bool*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::locals_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::rule_params_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::globals_tag>::_, json::global_state*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::trace_indent_tag>::_, int*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::error_handler_tag>::_, const boost::parser::callback_error_handler*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::callbacks_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::symbol_table_tries_tag>::_, std::map<void*, boost::any, std::less<void*>, std::allocator<std::pair<void* const, boost::any> > >*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::val_tag>::_, json::value*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::attr_tag>::_, boost::parser::detail::nope*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::where_tag>::_, const boost::parser::view<boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >*> > >]:
/home/tzlaine/parser/include/boost/parser/parser.hpp:3216:24: required from void boost::parser::action_parser<Parser, Action>::call(boost::hana::bool_<UseCallbacks>, Iter&, Sentinel, const Context&, const SkipParser&, boost::parser::detail::flags, bool&, Attribute&) const [with bool UseCallbacks = false; Iter = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Sentinel = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Context = boost::hana::detail::map_impl<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::parser::detail::begin_tag, 0>, boost::hana::detail::bucket<boost::parser::detail::end_tag, 1>, boost::hana::detail::bucket<boost::parser::detail::pass_tag, 2>, boost::hana::detail::bucket<boost::parser::detail::attr_tag, 3>, boost::hana::detail::bucket<boost::parser::detail::locals_tag, 4>, boost::hana::detail::bucket<boost::parser::detail::rule_params_tag, 5>, boost::hana::detail::bucket<boost::parser::detail::globals_tag, 6>, boost::hana::detail::bucket<boost::parser::detail::trace_indent_tag, 7>, boost::hana::detail::bucket<boost::parser::detail::error_handler_tag, 8>, boost::hana::detail::bucket<boost::parser::detail::callbacks_tag, 9>, boost::hana::detail::bucket<boost::parser::detail::symbol_table_tries_tag, 10>, boost::hana::detail::bucket<boost::parser::detail::val_tag, 11> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::type_impl<boost::parser::detail::begin_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::end_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::pass_tag>::_, bool*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::attr_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::locals_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::rule_params_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::globals_tag>::_, json::global_state*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::trace_indent_tag>::_, int*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::error_handler_tag>::_, const boost::parser::callback_error_handler*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::callbacks_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::symbol_table_tries_tag>::_, std::map<void*, boost::any, std::less<void*>, std::allocator<std::pair<void* const, boost::any> > >*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::val_tag>::_, json::value*> > >; SkipParser = boost::parser::rule<json::ws>; Attribute = boost::parser::detail::nope; Parser = boost::parser::omit_parser<boost::parser::char_parser<char, void> >; Action = json::<lambda(auto:58&)>; boost::hana::bool_<UseCallbacks> = boost::hana::integral_constant<bool, false>]
/home/tzlaine/parser/include/boost/parser/parser.hpp:3175:17: required from boost::parser::detail::nope boost::parser::action_parser<Parser, Action>::call(boost::hana::bool_<UseCallbacks>, Iter&, Sentinel, const Context&, const SkipParser&, boost::parser::detail::flags, bool&) const [with bool UseCallbacks = false; Iter = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Sentinel = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Context = boost::hana::detail::map_impl<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::parser::detail::begin_tag, 0>, boost::hana::detail::bucket<boost::parser::detail::end_tag, 1>, boost::hana::detail::bucket<boost::parser::detail::pass_tag, 2>, boost::hana::detail::bucket<boost::parser::detail::attr_tag, 3>, boost::hana::detail::bucket<boost::parser::detail::locals_tag, 4>, boost::hana::detail::bucket<boost::parser::detail::rule_params_tag, 5>, boost::hana::detail::bucket<boost::parser::detail::globals_tag, 6>, boost::hana::detail::bucket<boost::parser::detail::trace_indent_tag, 7>, boost::hana::detail::bucket<boost::parser::detail::error_handler_tag, 8>, boost::hana::detail::bucket<boost::parser::detail::callbacks_tag, 9>, boost::hana::detail::bucket<boost::parser::detail::symbol_table_tries_tag, 10>, boost::hana::detail::bucket<boost::parser::detail::val_tag, 11> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::type_impl<boost::parser::detail::begin_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::end_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::pass_tag>::_, bool*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::attr_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::locals_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::rule_params_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::globals_tag>::_, json::global_state*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::trace_indent_tag>::_, int*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::error_handler_tag>::_, const boost::parser::callback_error_handler*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::callbacks_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::symbol_table_tries_tag>::_, std::map<void*, boost::any, std::less<void*>, std::allocator<std::pair<void* const, boost::any> > >*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::val_tag>::_, json::value*> > >; SkipParser = boost::parser::rule<json::ws>; Parser = boost::parser::omit_parser<boost::parser::char_parser<char, void> >; Action = json::<lambda(auto:58&)>; boost::hana::bool_<UseCallbacks> = boost::hana::integral_constant<bool, false>]
/home/tzlaine/parser/include/boost/parser/parser.hpp:2745:35: required from auto boost::parser::seq_parser<ParserTuple, BacktrackingTuple>::dummy_use_parser_t<UseCallbacks, Iter, Sentinel, Context, SkipParser>::operator()(const Parser&) const [with Parser = boost::parser::action_parser<boost::parser::omit_parser<boost::parser::char_parser<char, void> >, json::<lambda(auto:58&)> >; bool UseCallbacks = false; Iter = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Sentinel = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Context = boost::hana::detail::map_impl<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::parser::detail::begin_tag, 0>, boost::hana::detail::bucket<boost::parser::detail::end_tag, 1>, boost::hana::detail::bucket<boost::parser::detail::pass_tag, 2>, boost::hana::detail::bucket<boost::parser::detail::attr_tag, 3>, boost::hana::detail::bucket<boost::parser::detail::locals_tag, 4>, boost::hana::detail::bucket<boost::parser::detail::rule_params_tag, 5>, boost::hana::detail::bucket<boost::parser::detail::globals_tag, 6>, boost::hana::detail::bucket<boost::parser::detail::trace_indent_tag, 7>, boost::hana::detail::bucket<boost::parser::detail::error_handler_tag, 8>, boost::hana::detail::bucket<boost::parser::detail::callbacks_tag, 9>, boost::hana::detail::bucket<boost::parser::detail::symbol_table_tries_tag, 10>, boost::hana::detail::bucket<boost::parser::detail::val_tag, 11> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::type_impl<boost::parser::detail::begin_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::end_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::pass_tag>::_, bool*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::attr_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::locals_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::rule_params_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::globals_tag>::_, json::global_state*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::trace_indent_tag>::_, int*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::error_handler_tag>::_, const boost::parser::callback_error_handler*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::callbacks_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::symbol_table_tries_tag>::_, std::map<void*, boost::any, std::less<void*>, std::allocator<std::pair<void* const, boost::any> > >*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::val_tag>::_, json::value*> > >; SkipParser = boost::parser::rule<json::ws>; ParserTuple = boost::hana::tuple<boost::parser::action_parser<boost::parser::omit_parser<boost::parser::char_parser<char, void> >, json::<lambda(auto:58&)> >, boost::parser::opt_parser<boost::parser::delimited_seq_parser<boost::parser::action_parser<boost::parser::rule_parser<false, json::object_element, boost::hana::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, json::value>, boost::parser::detail::nope, boost::parser::detail::nope>, json::<lambda(auto:59&)> >, boost::parser::omit_parser<boost::parser::char_parser<char, void> > > >, boost::parser::omit_parser<boost::parser::char_parser<char, void> > >; BacktrackingTuple = boost::hana::tuple<boost::hana::integral_constant<bool, true>, boost::hana::integral_constant<bool, true>, boost::hana::integral_constant<bool, false> >]
/home/tzlaine/boost_1_71_0/boost/hana/transform.hpp:62:42: required from constexpr auto boost::hana::transform_impl<S, boost::hana::when<boost::hana::Sequence<S>::value> >::transformer<F>::operator()(Xs&& ...) const [with Xs = {const boost::parser::action_parser<boost::parser::omit_parser<boost::parser::char_parser<char, void> >, json::<lambda(auto:58&)> >&, const boost::parser::opt_parser<boost::parser::delimited_seq_parser<boost::parser::action_parser<boost::parser::rule_parser<false, json::object_element, boost::hana::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, json::value>, boost::parser::detail::nope, boost::parser::detail::nope>, json::<lambda(auto:59&)> >, boost::parser::omit_parser<boost::parser::char_parser<char, void> > > >&, const boost::parser::omit_parser<boost::parser::char_parser<char, void> >&}; F = const boost::parser::seq_parser<boost::hana::tuple<boost::parser::action_parser<boost::parser::omit_parser<boost::parser::char_parser<char, void> >, json::<lambda(auto:58&)> >, boost::parser::opt_parser<boost::parser::delimited_seq_parser<boost::parser::action_parser<boost::parser::rule_parser<false, json::object_element, boost::hana::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, json::value>, boost::parser::detail::nope, boost::parser::detail::nope>, json::<lambda(auto:59&)> >, boost::parser::omit_parser<boost::parser::char_parser<char, void> > > >, boost::parser::omit_parser<boost::parser::char_parser<char, void> > >, boost::hana::tuple<boost::hana::integral_constant<bool, true>, boost::hana::integral_constant<bool, true>, boost::hana::integral_constant<bool, false> > >::dummy_use_parser_t<false, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>, boost::hana::detail::map_impl<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::parser::detail::begin_tag, 0>, boost::hana::detail::bucket<boost::parser::detail::end_tag, 1>, boost::hana::detail::bucket<boost::parser::detail::pass_tag, 2>, boost::hana::detail::bucket<boost::parser::detail::attr_tag, 3>, boost::hana::detail::bucket<boost::parser::detail::locals_tag, 4>, boost::hana::detail::bucket<boost::parser::detail::rule_params_tag, 5>, boost::hana::detail::bucket<boost::parser::detail::globals_tag, 6>, boost::hana::detail::bucket<boost::parser::detail::trace_indent_tag, 7>, boost::hana::detail::bucket<boost::parser::detail::error_handler_tag, 8>, boost::hana::detail::bucket<boost::parser::detail::callbacks_tag, 9>, boost::hana::detail::bucket<boost::parser::detail::symbol_table_tries_tag, 10>, boost::hana::detail::bucket<boost::parser::detail::val_tag, 11> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::type_impl<boost::parser::detail::begin_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::end_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::pass_tag>::_, bool*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::attr_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::locals_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::rule_params_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::globals_tag>::_, json::global_state*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::trace_indent_tag>::_, int*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::error_handler_tag>::_, const boost::parser::callback_error_handler*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::callbacks_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::symbol_table_tries_tag>::_, std::map<void*, boost::any, std::less<void*>, std::allocator<std::pair<void* const, boost::any> > >*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::val_tag>::_, json::value*> > >, boost::parser::rule<json::ws> >*; S = boost::hana::tuple_tag]
/home/tzlaine/boost_1_71_0/boost/hana/basic_tuple.hpp:115:39: required from static constexpr decltype(auto) boost::hana::unpack_impl<boost::hana::basic_tuple_tag>::apply(const boost::hana::detail::basic_tuple_impl<std::integer_sequence<long unsigned int, _Idx ...>, Xn ...>&, F&&) [with long unsigned int ...i = {0, 1, 2}; Xn = {boost::parser::action_parser<boost::parser::omit_parser<boost::parser::char_parser<char, void> >, json::<lambda(auto:58&)> >, boost::parser::opt_parser<boost::parser::delimited_seq_parser<boost::parser::action_parser<boost::parser::rule_parser<false, json::object_element, boost::hana::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, json::value>, boost::parser::detail::nope, boost::parser::detail::nope>, json::<lambda(auto:59&)> >, boost::parser::omit_parser<boost::parser::char_parser<char, void> > > >, boost::parser::omit_parser<boost::parser::char_parser<char, void> >}; F = boost::hana::transform_impl<boost::hana::tuple_tag, boost::hana::when<true> >::transformer<const boost::parser::seq_parser<boost::hana::tuple<boost::parser::action_parser<boost::parser::omit_parser<boost::parser::char_parser<char, void> >, json::<lambda(auto:58&)> >, boost::parser::opt_parser<boost::parser::delimited_seq_parser<boost::parser::action_parser<boost::parser::rule_parser<false, json::object_element, boost::hana::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, json::value>, boost::parser::detail::nope, boost::parser::detail::nope>, json::<lambda(auto:59&)> >, boost::parser::omit_parser<boost::parser::char_parser<char, void> > > >, boost::parser::omit_parser<boost::parser::char_parser<char, void> > >, boost::hana::tuple<boost::hana::integral_constant<bool, true>, boost::hana::integral_constant<bool, true>, boost::hana::integral_constant<bool, false> > >::dummy_use_parser_t<false, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>, boost::hana::detail::map_impl<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::parser::detail::begin_tag, 0>, boost::hana::detail::bucket<boost::parser::detail::end_tag, 1>, boost::hana::detail::bucket<boost::parser::detail::pass_tag, 2>, boost::hana::detail::bucket<boost::parser::detail::attr_tag, 3>, boost::hana::detail::bucket<boost::parser::detail::locals_tag, 4>, boost::hana::detail::bucket<boost::parser::detail::rule_params_tag, 5>, boost::hana::detail::bucket<boost::parser::detail::globals_tag, 6>, boost::hana::detail::bucket<boost::parser::detail::trace_indent_tag, 7>, boost::hana::detail::bucket<boost::parser::detail::error_handler_tag, 8>, boost::hana::detail::bucket<boost::parser::detail::callbacks_tag, 9>, boost::hana::detail::bucket<boost::parser::detail::symbol_table_tries_tag, 10>, boost::hana::detail::bucket<boost::parser::detail::val_tag, 11> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::type_impl<boost::parser::detail::begin_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::end_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::pass_tag>::_, bool*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::attr_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::locals_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::rule_params_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::globals_tag>::_, json::global_state*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::trace_indent_tag>::_, int*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::error_handler_tag>::_, const boost::parser::callback_error_handler*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::callbacks_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::symbol_table_tries_tag>::_, std::map<void*, boost::any, std::less<void*>, std::allocator<std::pair<void* const, boost::any> > >*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::val_tag>::_, json::value*> > >, boost::parser::rule<json::ws> >*>]
/home/tzlaine/boost_1_71_0/boost/hana/unpack.hpp:47:29: [ skipping 20 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/home/tzlaine/parser/example/json.cpp:262:5: required from void json::parse_rule(boost::parser::rule_parser<false, json::value_tag, json::value, boost::parser::detail::nope, boost::parser::detail::nope>::tag_type*, boost::hana::bool_<b>, Iter&, Sentinel, const Context&, const SkipParser&, boost::parser::detail::flags, bool&, Attribute&) [with bool UseCallbacks = false; Iter = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Sentinel = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Context = boost::hana::detail::map_impl<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::parser::detail::begin_tag, 0>, boost::hana::detail::bucket<boost::parser::detail::end_tag, 1>, boost::hana::detail::bucket<boost::parser::detail::pass_tag, 2>, boost::hana::detail::bucket<boost::parser::detail::attr_tag, 3>, boost::hana::detail::bucket<boost::parser::detail::locals_tag, 4>, boost::hana::detail::bucket<boost::parser::detail::rule_params_tag, 5>, boost::hana::detail::bucket<boost::parser::detail::globals_tag, 6>, boost::hana::detail::bucket<boost::parser::detail::trace_indent_tag, 7>, boost::hana::detail::bucket<boost::parser::detail::error_handler_tag, 8>, boost::hana::detail::bucket<boost::parser::detail::callbacks_tag, 9>, boost::hana::detail::bucket<boost::parser::detail::symbol_table_tries_tag, 10>, boost::hana::detail::bucket<boost::parser::detail::val_tag, 11> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::type_impl<boost::parser::detail::begin_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::end_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::pass_tag>::_, bool*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::attr_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::locals_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::rule_params_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::globals_tag>::_, json::global_state*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::trace_indent_tag>::_, int*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::error_handler_tag>::_, const boost::parser::callback_error_handler*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::callbacks_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::symbol_table_tries_tag>::_, std::map<void*, boost::any, std::less<void*>, std::allocator<std::pair<void* const, boost::any> > >*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::val_tag>::_, json::value*> > >; SkipParser = boost::parser::rule<json::ws>; Attribute = json::value; boost::parser::rule_parser<false, json::value_tag, json::value, boost::parser::detail::nope, boost::parser::detail::nope>::tag_type = json::value_tag; boost::hana::bool_<b> = boost::hana::integral_constant<bool, false>]
/home/tzlaine/parser/include/boost/parser/parser.hpp:3707:23: required from boost::parser::rule_parser<false, TagType, Attribute, LocalState, ParamsTuple>::attr_type boost::parser::rule_parser<false, TagType, Attribute, LocalState, ParamsTuple>::call(boost::hana::bool_<UseCallbacks>, Iter&, Sentinel, const Context&, const SkipParser&, boost::parser::detail::flags, bool&) const [with bool UseCallbacks = false; Iter = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Sentinel = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Context = boost::hana::detail::map_impl<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::parser::detail::begin_tag, 0>, boost::hana::detail::bucket<boost::parser::detail::end_tag, 1>, boost::hana::detail::bucket<boost::parser::detail::pass_tag, 2>, boost::hana::detail::bucket<boost::parser::detail::val_tag, 3>, boost::hana::detail::bucket<boost::parser::detail::attr_tag, 4>, boost::hana::detail::bucket<boost::parser::detail::locals_tag, 5>, boost::hana::detail::bucket<boost::parser::detail::rule_params_tag, 6>, boost::hana::detail::bucket<boost::parser::detail::globals_tag, 7>, boost::hana::detail::bucket<boost::parser::detail::trace_indent_tag, 8>, boost::hana::detail::bucket<boost::parser::detail::error_handler_tag, 9>, boost::hana::detail::bucket<boost::parser::detail::callbacks_tag, 10>, boost::hana::detail::bucket<boost::parser::detail::symbol_table_tries_tag, 11> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::type_impl<boost::parser::detail::begin_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::end_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::pass_tag>::_, bool*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::val_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::attr_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::locals_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::rule_params_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::globals_tag>::_, json::global_state*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::trace_indent_tag>::_, int*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::error_handler_tag>::_, const boost::parser::callback_error_handler*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::callbacks_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::symbol_table_tries_tag>::_, std::map<void*, boost::any, std::less<void*>, std::allocator<std::pair<void* const, boost::any> > >*> > >; SkipParser = boost::parser::rule<json::ws>; TagType = json::value_tag; Attribute = json::value; LocalState = boost::parser::detail::nope; ParamsTuple = boost::parser::detail::nope; boost::parser::rule_parser<false, TagType, Attribute, LocalState, ParamsTuple>::attr_type = json::value; boost::hana::bool_<UseCallbacks> = boost::hana::integral_constant<bool, false>]
/home/tzlaine/parser/include/boost/parser/parser.hpp:4155:32: required from auto boost::parser::parser_interface<Parser, GlobalState, ErrorHandler>::operator()(boost::hana::bool_<UseCallbacks>, Iter&, Sentinel, const Context&, const SkipParserType&, boost::parser::detail::flags, bool&) const [with bool UseCallbacks = false; Iter = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Sentinel = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Context = boost::hana::detail::map_impl<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::parser::detail::begin_tag, 0>, boost::hana::detail::bucket<boost::parser::detail::end_tag, 1>, boost::hana::detail::bucket<boost::parser::detail::pass_tag, 2>, boost::hana::detail::bucket<boost::parser::detail::val_tag, 3>, boost::hana::detail::bucket<boost::parser::detail::attr_tag, 4>, boost::hana::detail::bucket<boost::parser::detail::locals_tag, 5>, boost::hana::detail::bucket<boost::parser::detail::rule_params_tag, 6>, boost::hana::detail::bucket<boost::parser::detail::globals_tag, 7>, boost::hana::detail::bucket<boost::parser::detail::trace_indent_tag, 8>, boost::hana::detail::bucket<boost::parser::detail::error_handler_tag, 9>, boost::hana::detail::bucket<boost::parser::detail::callbacks_tag, 10>, boost::hana::detail::bucket<boost::parser::detail::symbol_table_tries_tag, 11> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::type_impl<boost::parser::detail::begin_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::end_tag>::_, boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character> >, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::pass_tag>::_, bool*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::val_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::attr_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::locals_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::rule_params_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::globals_tag>::_, json::global_state*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::trace_indent_tag>::_, int*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::error_handler_tag>::_, const boost::parser::callback_error_handler*>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::callbacks_tag>::_, boost::parser::detail::nope>, boost::hana::pair<boost::hana::type_impl<boost::parser::detail::symbol_table_tries_tag>::_, std::map<void*, boost::any, std::less<void*>, std::allocator<std::pair<void* const, boost::any> > >*> > >; SkipParserType = boost::parser::rule<json::ws>; Parser = boost::parser::rule_parser<false, json::value_tag, json::value, boost::parser::detail::nope, boost::parser::detail::nope>; GlobalState = json::global_state&; ErrorHandler = boost::parser::callback_error_handler&; boost::hana::bool_<UseCallbacks> = boost::hana::integral_constant<bool, false>]
/home/tzlaine/parser/include/boost/parser/parser.hpp:1808:43: required from auto boost::parser::detail::skip_parse_impl(Iter&, Sentinel, const Parser&, const SkipParser&, const ErrorHandler&) [with bool Debug = true; Iter = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Sentinel = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Parser = boost::parser::parser_interface<boost::parser::rule_parser<false, json::value_tag, json::value, boost::parser::detail::nope, boost::parser::detail::nope>, json::global_state&, boost::parser::callback_error_handler&>; SkipParser = boost::parser::rule<json::ws>; ErrorHandler = boost::parser::callback_error_handler]
/home/tzlaine/parser/include/boost/parser/parser.hpp:6369:53: required from auto boost::parser::parse(I&, S, const boost::parser::parser_interface<Parser, GlobalState, ErrorHandler>&, const boost::parser::rule<TagType, Attribute, LocalState, ParamsTuple>&, boost::parser::trace) [with I = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; S = boost::text::utf_8_to_32_iterator<const char*, const char*, boost::text::use_replacement_character>; Parser = boost::parser::rule_parser<false, json::value_tag, json::value, boost::parser::detail::nope, boost::parser::detail::nope>; GlobalState = json::global_state&; ErrorHandler = boost::parser::callback_error_handler&; TagType = json::ws; Attribute = boost::parser::detail::nope; LocalState = boost::parser::detail::nope; ParamsTuple = boost::parser::detail::nope]
/home/tzlaine/parser/example/json.cpp:313:53: required from here
/home/tzlaine/parser/example/json.cpp:103:13: error: could not convert x from boost::parser::none to bool
103 | if (x)
| ^
| |
| boost::parser::none
make[3]: *** [example/CMakeFiles/json.dir/build.make:63: example/CMakeFiles/json.dir/json.cpp.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:1668: example/CMakeFiles/json.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:1675: example/CMakeFiles/json.dir/rule] Error 2
make: *** [Makefile:827: json] Error 2
``
Some very familiar problems should be noted here:
* Most of the template instantiation stack is missing (20 instantiation
contexts, as you can see indicated in the middle). If the problem occurred
there, it's that much harder to find.
* That's a lot of text to try and read and understand (try scrolling
horizontally, there's a lot more).
* Worst of all, `object_init` may be used with multiple rules, some of which
have locals, and some of which do not. While it's nice that the last line
of the error diagnostic points us to the ill-formed use of a _n_, we don't
know which *parser plus semantic action* is the problem. With a stack trace
in a debugger, we would know that in a few seconds. In this case, we'd have
a long slog trying to figure out exactly where the problem lies.
[heading Attribute types are flexible]
This is how we get genericity in attribute generation. In the STL, we can use
multiple types of container with the algorithms because iterators act as the
glue that connects algorithms to containers. With attribute generation, there
are instead arbitrary types being constructed and inserted into containers.
Allowing the insertion to happen on arbitrary types that model the `container`
concept is what allows generic use of different containers.
[endsect]