2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-19 04:22:13 +00:00

Explain more fully in More about Rules that you need to write a semantic

action sometimes for a rule, and under what cirumstances you do.

Fixes #93.
This commit is contained in:
Zach Laine
2024-02-11 16:46:47 -06:00
parent f326cd9d23
commit b6b77bac3c
2 changed files with 68 additions and 0 deletions

View File

@@ -2640,6 +2640,44 @@ attribute flexibility we want across our code:
Now we have one of each, and we did not have to copy any parsing logic that
would have to be maintained in two places.
Sometimes, you need to create a rule to enforce a certain attribute type, but
the rule's attribute is not constructible from its parser's attribute. When
that happens, you'll need to write a semantic action.
struct type_t
{
type_t() = default;
explicit type_t(double x) : x_(x) {}
// etc.
double x_;
};
namespace bp = boost::parser;
auto doubles_to_type = [](auto & ctx) {
using namespace bp::literals;
_val(ctx) = type_t(_attr(ctx)[0_c] * _attr(ctx)[1_c]);
};
bp::rule<struct type_tag, type_t> type = "type";
auto const type_def = (bp::double_ >> bp::double_)[doubles_to_type];
BOOST_PARSER_DEFINE_RULES(type);
For a rule `R` and its parser `P`, we do not need to write such a semantic
action if:
- `_ATTR_np_(R)` is an aggregate, and `_ATTR_np_(P)` is a compatible tuple;
- `_ATTR_np_(R)` is a tuple, and `_ATTR_np_(P)` is a compatible aggregate;
- `_ATTR_np_(R)` is a non-aggregate class type `C`, and `_ATTR_np_(P)` is a
tuple whose elements can be used to construct `C`; or
- `_ATTR_np_(R)` and `_ATTR_np_(P)` are compatible types.
The notion of "compatible" is defined in _p_api_.
[heading Creating a parser for better diagnostics]
Each _r_ has associated diagnostic text that _Parser_ can use for failures of

View File

@@ -2818,3 +2818,33 @@ TEST(parser, variant_compat_example)
bp::parse("42 13.0", bp::int_ >> bp::double_, kv_or_d); // Error: ill-formed!
#endif
}
namespace rule_construction_example {
struct type_t
{
type_t() = default;
explicit type_t(double x) : x_(x) {}
// etc.
double x_;
};
namespace bp = boost::parser;
auto doubles_to_type = [](auto & ctx) {
using namespace bp::literals;
_val(ctx) = type_t(_attr(ctx)[0_c] * _attr(ctx)[1_c]);
};
bp::rule<struct type_tag, type_t> type = "type";
auto const type_def = (bp::double_ >> bp::double_)[doubles_to_type];
BOOST_PARSER_DEFINE_RULES(type);
}
TEST(parser, rule_example)
{
namespace bp = boost::parser;
using namespace rule_construction_example;
EXPECT_TRUE(bp::parse("3 4", type, bp::ws));
}