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.hppnamespace 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.hpptemplate <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_classwith 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.hppconstexpr branch-rule operator()(rule auto lexeme_rule) const;- Parsing
Parses the corresponding
lexy::dsl::tnodetoken rule, thenlexeme_ruleon the lexeme of that token node.- Branch parsing
Tries to parse the corresponding
lexy::dsl::tnodetoken rule and backtracks if that backtracks. Then parseslexeme_ruleon the lexeme of that token node.- Errors
lexy::expected_char_classwith 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_ruleon 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_endiflexeme_ruledid 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.hppnamespace 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.hpptemplate <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_classwith the name of the production, at the starting reader position.
Branch rule lexy::dsl::pnode(child_rule)
lexy/dsl/parse_tree_node.hppconstexpr branch-rule operator()(rule auto child_rule) const;- Parsing
Parses the corresponding
lexy::dsl::pnodetoken rule, thenchild_ruleon the children of that production node.- Branch parsing
Tries to parse the corresponding
lexy::dsl::pnodetoken rule and backtracks if that backtracks. Then parseschild_ruleon the children of that production node.- Errors
lexy::expected_char_classwith 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_ruleon 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_endifchild_ruledid 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. |