Header lexy/dsl/parse_tree_node.hpp
Rules for parsing a lexy::parse_tree_input
.
// A simple grammar for a single key-value pair.
namespace grammar
{
struct key
{
static constexpr auto rule = dsl::identifier(dsl::ascii::alnum);
};
struct integer
{
static constexpr auto rule = dsl::digits<>;
};
struct key_value_pair
{
static constexpr auto whitespace = dsl::ascii::space;
static constexpr auto rule = dsl::p<key> + dsl::lit_c<'='> + dsl::p<integer>;
};
} // namespace grammar
namespace tree_grammar
{
struct integer
{
// Match the digits token and extract their integer value.
static constexpr auto rule = dsl::tnode<lexy::digits_token_kind>(dsl::integer<int>);
static constexpr auto value = lexy::as_integer<int>;
};
struct key_value_pair
{
// Skip over literal and whitespace tokens automatically.
static constexpr auto whitespace
= dsl::tnode<lexy::literal_token_kind> | dsl::tnode<lexy::whitespace_token_kind>;
// Skip the key production but parse the children of the integer production.
static constexpr auto rule = [] {
auto key = dsl::pnode<grammar::key>;
auto value = dsl::pnode<grammar::integer>(dsl::p<integer>);
return key + value;
}();
static constexpr auto value = lexy::forward<int>;
};
} // namespace tree_grammar
int main()
{
auto input = lexy_ext::compiler_explorer_input();
// Parse the string into a tree.
lexy::parse_tree_for<lexy::buffer<lexy::utf8_encoding>> tree;
if (!lexy::parse_as_tree<grammar::key_value_pair>(tree, input, lexy_ext::report_error))
return 1;
// Parse the tree to extract the value (we ignore error reporting here since it's a bug for the
// parse tree grammar to fail).
auto result
= lexy::parse<tree_grammar::key_value_pair>(lexy::parse_tree_input(tree), lexy::noop);
if (!result)
return 2;
std::printf("Value: %d\n", result.value());
}
Rule DSL lexy::dsl::tnode
lexy/dsl/parse_tree_node.hpp
namespace lexy
{
struct expected_token_end {};
}
namespace lexy::dsl
{
class tnode-dsl // models token-rule
{
public:
constexpr branch-rule operator()(rule auto lexeme_rule) const;
};
template <auto TokenKind>
constexpr auto tnode = tnode-dsl{};
}
tnode
is a token rule and DSL to match a token node in a lexy::parse_tree_input
.
If used in the form tnode<TokenKind>
, it is a token rule that matches a token node with the given kind.
If used in the form tnode<TokenKind>(lexeme_rule)
, it is a branch rule that also matches the lexeme.
Token rule lexy::dsl::tnode
lexy/dsl/parse_tree_node.hpp
template <auto TokenKind>
constexpr auto tnode = tnode-dsl{};
- Matching
If the current parse tree node in the input is a token node with the specified
TokenKind
, consumes it. Otherwise, fails.- Errors
lexy::expected_char_class
with the name of the token kind, at the starting reader position.- Parse tree
A single token node that contains the node of the input parse tree with the same token kind.
Branch rule lexy::dsl::tnode(lexeme_rule)
lexy/dsl/parse_tree_node.hpp
constexpr branch-rule operator()(rule auto lexeme_rule) const;
- Parsing
Parses the corresponding
lexy::dsl::tnode
token rule, thenlexeme_rule
on the lexeme of that token node.- Branch parsing
Tries to parse the corresponding
lexy::dsl::tnode
token rule and backtracks if that backtracks. Then parseslexeme_rule
on the lexeme of that token node.- Errors
lexy::expected_char_class
with the name of the token kind, at the starting reader position during non-branch parsing when the node did not match. The rule then fails.All errors raised when parsing
lexeme_rule
on the lexeme. The rule then recovers by doing nothing, as the lexeme of the node is not part of the input anyway.lexy::expected_token_end
iflexeme_rule
did not consume the entire lexeme of the node. The rule then recovers by doing nothing.
Note | lexeme_rule matches characters, not other nodes. |
Rule DSL lexy::dsl::pnode
lexy/dsl/parse_tree_node.hpp
namespace lexy
{
struct expected_production_end {};
}
namespace lexy::dsl
{
class pnode-dsl // models token-rule
{
public:
constexpr branch-rule operator()(rule auto child_rule) const;
};
template <production Production>
constexpr auto pnode = pnode-dsl{};
}
pnode
is a token rule and DSL to match a production node in a lexy::parse_tree_input
.
If used in the form pnode<Production>
, it is a token rule that matches a Production
node.
If used in the form pnode<Production>(child_rule)
, it is a branch rule that also matches the children of the node.
Token rule lexy::dsl::pnode
lexy/dsl/parse_tree_node.hpp
template <typename Production>
constexpr auto pnode = pnode-dsl{};
- Matching
If the current parse tree node in the input is a production node for
Production
, consumes it. Otherwise, fails.- Errors
lexy::expected_char_class
with the name of the production, at the starting reader position.
Branch rule lexy::dsl::pnode(child_rule)
lexy/dsl/parse_tree_node.hpp
constexpr branch-rule operator()(rule auto child_rule) const;
- Parsing
Parses the corresponding
lexy::dsl::pnode
token rule, thenchild_rule
on the children of that production node.- Branch parsing
Tries to parse the corresponding
lexy::dsl::pnode
token rule and backtracks if that backtracks. Then parseschild_rule
on the children of that production node.- Errors
lexy::expected_char_class
with the name of the production, at the starting reader position during non-branch parsing when the node did not match. The rule then fails.All errors raised when parsing
child_rule
on the children. The rule then recovers by doing nothing, as the children of the node are not part of the input anyway.lexy::expected_production_end
ifchild_rule
did not consume all children of the node. The rule then recovers by doing nothing.
Note | child_rule is executed on another lexy::parse_tree_input with the matched node as root. |