Header lexy/dsl/production.hpp
The inline_
, p
, and recurse
rules.
Rule lexy::dsl::inline_
lexy/dsl/production.hpp
namespace lexy::dsl
{
template <production P>
constexpr rule auto inline_;
template <production P>
requires token-rule<production_rule<P>>
constexpr token-rule auto inline_;
template <production P>
requires branch-rule<production_rule<P>>
constexpr branch-rule auto inline_;
}
inline_
is a rule that parses the rule of production P
as part of the current production.
- Requires
P
is a complete type, i.e.p
cannot be used for recursion.- Matching
Matches
P::rule
.- (Branch) Parsing
Parses
P::rule
.- Errors
All errors raised by
P::rule
. The rule then fails ifP::rule
has failed.- Values
All values produced by
P::rule
.
struct name
{
static constexpr auto rule
// One or more alpha numeric characters, underscores or hyphens.
= dsl::identifier(dsl::unicode::alnum / dsl::lit_c<'_'> / dsl::lit_c<'-'>);
};
struct production
{
// Allow arbitrary spaces between individual tokens.
// Note that this includes the individual characters of the name.
static constexpr auto whitespace = dsl::ascii::space;
static constexpr auto rule = [] {
auto greeting = LEXY_LIT("Hello");
return greeting + dsl::inline_<name> + dsl::exclamation_mark + dsl::eof;
}();
};
Tip | Use inline_ when you need to parse a production as part of the whitespace rule. |
Rule lexy::dsl::p
lexy/dsl/production.hpp
namespace lexy::dsl
{
template <production P>
constexpr rule auto p;
template <production P>
requires branch-rule<production_rule<P>> && !defines-whitespace<P>`
constexpr branch-rule auto p;
}
p
is a rule that parses the production P
.
- Requires
P
is a complete type, i.e.p
cannot be used for recursion.- (Branch) Parsing
Parses
P::rule
in a new context forP
, potentially after skipping initialwhitespace
ifP::whitespace
has been defined.- Errors
All errors raised by parsing
P::rule
, but forwarded to the new context forP
. The rule fails ifP::rule
has failed.- Values
All values produced by
P::rule
are forwarded to the new context, e.g. toP::value
. The final value of the context is produced as the single value forp
.- Parse tree
If
P
inherits fromlexy::transparent_production
, the nodes generated byP::rule
are added to the parse tree as if they were added byp
itself.Otherwise, it creates a single production node for
P
. Its children are all the nodes generated byP::rule
.
struct name
{
static constexpr auto rule
// One or more alpha numeric characters, underscores or hyphens.
= dsl::identifier(dsl::unicode::alnum / dsl::lit_c<'_'> / dsl::lit_c<'-'>);
};
struct production
{
// Allow arbitrary spaces between individual tokens.
static constexpr auto whitespace = dsl::ascii::space;
static constexpr auto rule = [] {
auto greeting = LEXY_LIT("Hello");
return greeting + dsl::p<name> + dsl::exclamation_mark + dsl::eof;
}();
};
constexpr auto id = dsl::identifier(dsl::ascii::alpha);
constexpr auto kw_function = LEXY_KEYWORD("function", id);
constexpr auto kw_type = LEXY_KEYWORD("type", id);
struct function_decl
{
static constexpr auto rule = [] {
auto arguments = dsl::parenthesized(LEXY_LIT("..."));
auto body = dsl::curly_bracketed(LEXY_LIT("..."));
return kw_function >> id + arguments + body;
}();
};
struct type_decl
{
static constexpr auto rule //
= kw_type >> id + dsl::lit_c<'='> + id + dsl::semicolon;
};
struct production
{
static constexpr auto whitespace = dsl::ascii::space;
static constexpr auto rule = dsl::p<function_decl> | dsl::p<type_decl>;
};
Note | The p rule cannot handle direct or indirect recursion, as P must be a complete type. |
Caution | While parsing P::rule , the current whitespace rule can be different.
If whitespace parsing has been disabled using lexy::dsl::no_whitespace ,
it is temporarily re-enabled while parsing P::rule .
If whitespace parsing has been disabled because the current production inherits from lexy::token_production ,
it is still disabled, unless the current production explicitly defines a new whitespace rule. |
Rule lexy::dsl::recurse
lexy/dsl/production.hpp
namespace lexy
{
struct max_recursion_depth_exceeded {};
}
namespace lexy::dsl
{
struct recurse // models rule or branch-rule
{
template <typename Tag>
static constexpr recurse max_depth_error;
};
template <production P>
constexpr recurse auto recurse; // rule
template <production P>
constexpr recurse auto recurse_branch; // branch-rule
}
recurse
is a rule that parses the production P
but supports recursion.
It behaves similar to the p
rule, but P
does not need to a be a complete type, which allows recursion.
For the same reason, recurse<P>
is never a branch rule: it can’t know whether P
is a branch.
Use recurse_branch<P>
if you know that P
is a branch; it will cause a delayed static_assert
if it isn’t.
- Parsing
Checks whether the current depth of recursive production call exceeds the maximum parse depth, which is determined by
lexy::max_recursion_depth
. Fails, if that is the case. Otherwise, parsesp<P>
, i.e. the productionP
.- Branch parsing
Branch parses
p<P>
, i.e. the productionP
. The recursive depth check is done after the branch condition has matched. It will not backtrack if the condition matches but the depth is exceeded.- Errors
A generic error with the specified
Tag
orlexy::max_recursion_depth_exceeded
if the recursive depth is exceeded, at the position where it would have started to match the production. It then fails without recovering.All errors raised by parsing
p<P>
.
struct production
{
// We define a (tiny) maximum recursion depth.
// This prevents unbounded recursion which can cause a stack overflow.
static constexpr auto max_recursion_depth = 3;
static constexpr auto rule
// Either we parse ourselves surrounded by expressions, or an atom.
= dsl::parenthesized(dsl::recurse<production>) | LEXY_LIT("atom");
};
Warning | Left recursion will create a max recursion error.
Use lexy::dsl::loop or lexy::dsl::list instead. |
Note | The recursion depth only counts productions parsed by recurse ; intermediate productions parsed using p are ignored.
In particular, the nesting level of p rules, which is statically determined by the grammar and not by the input, is allowed to exceed the maximum recursion depth. |