Header lexy/grammar.hpp

Traits and definitions for the grammar.

Grammar traits

lexy/grammar.hpp
namespace lexy
{
    template <typename T>
    constexpr bool is_production;  (1)

    template <typename T>
    constexpr bool is_rule;        (2)
    template <typename T>
    constexpr bool is_branch_rule; (3)
    template <typename T>
    constexpr bool is_unconditional_branch_rule; (4)
    template <typename T>
    constexpr bool is_token_rule;  (5)

    template <typename T>
    constexpr bool is_literal_rule; (6)
    template <typename T>
    constexpr bool is_literal_set_rule; (7)
    template <typename T>
    constexpr bool is_char_class_rule; (8)

    template <typename T>
    constexpr bool is_separator; (9)
    template <typename T>
    constexpr bool is_operation; (10)
}
  1. Whether or not T is a production, i.e. it has a ::rule member.

  2. Whether or not T is a rule.

  3. Whether or not T is a branch rule.

  4. Whether or not T is an unconditional branch rule (e.g. lexy::dsl::else_ ).

  5. Whether or not T is a token rule.

  6. Whether or not T is a literal rule.

  7. Whether or not T is a lexy::dsl::literal_set  rule.

  8. Whether or not T is a char class rule.

  9. Whether or not T is a separator (lexy::dsl::sep  and lexy::dsl::trailing_sep ).

  10. Whether or not T is an operation (see expression ).

Class lexy::token_production

lexy/grammar.hpp
namespace lexy
{
    struct token_production
    {};

    template <production Production>
    constexpr bool is_token_production = std::is_base_of_v<token_production, Production>;
}

Base class to indicate that a production is conceptually a token. This inhibits whitespace skipping (directly) inside the production.

Class lexy::transparent_production

lexy/grammar.hpp
namespace lexy
{
    struct transparent_production
    {};

    template <production Production>
    constexpr bool is_transparent_production = std::is_base_of_v<transparent_production, Production>;
}

Base class to indicate that this production should not show up in the parse tree or diagnostics.

In the lexy::parse_tree , there will be no separate node for Production. Instead, all child nodes of Production are added to its parent node.

In the lexy::error_context , transparent production will not be listed. Instead, the next non-transparent parent is used.

Function lexy::production_name

lexy/grammar.hpp
namespace lexy
{
    template <production Production>
    consteval const char* production_name();
}

Returns the name of the production.

By default, it is the type name of Production after removing the top-level namespace. This can be overridden by Production::name() or Production::name.

Struct lexy::production_info

lexy/grammar.hpp
namespace lexy
{
    struct production_info
    {
        const void id;             (1)
        const char name;           (2)
        bool        is_token;       (3)
        bool        is_transparent; (4)

        production_info(production auto production);
        production_info(operation auto operation);

        friend bool operator==(production_info lhs, production_info rhs);
        friend bool operator!=(production_info lhs, production_info rhs);
    };
}
  1. A unique id identifying the production.

  2. lexy::production_name 

  3. lexy::is_token_production

  4. lexy::is_transparent_production

A collection of type-erased information about a production (or operation, see expression ).

For an operation, is_token and is_transparent will always be false. It is considered like a production here, because it behaves like one in the lexy::parse_tree .

Trait lexy::production_rule

lexy/grammar.hpp
namespace lexy
{
    template <production Production>
    using production_rule = std::decay_t<decltype(Production::rule)>;
}

Returns the type of the rule of production, i.e. the type of Production::rule.

Trait lexy::production_whitespace

lexy/grammar.hpp
namespace lexy
{
    template <production Production, production WhitespaceProduction>
    using production_whitespace = see-below;
}

Returns the type of the whitespace  rule of Production given its last parent WhitespaceProduction.

It is determined as follows:

  1. If Production::whitespace is valid, returns the decayed type of that.

  2. If WhitespaceProduction::whitespace is valid, returns the decayed type of that.

  3. Otherwise, returns void.

This is used by lexy::dsl::whitespace  during automatic whitespace skipping.

Callback lexy::production_value_callback

lexy/grammar.hpp
namespace lexy
{
    template <production Production, typename ParseState = void>
    constexpr bool production_has_value_callback;

    template <production Production, typename ParseState = void>
    class production_value_callback
    {
    public:
        constexpr explicit production_value_callback(const ParseState&);

        using return_type = see-below;

        constexpr sink auto sink() const;

        template <typename ... Args>
        constexpr return_type operator()(Args&&... args);
    };
}

A callback and sink for the specified Production.

It wraps an underlying callback/sink, which is determined as follows:

  1. ParseState is non-void and the call state.value_of(Production{}) is well-formed. It will use the result as the underlying callback/sink.

  2. ParseState is non-void but state.value_of(Production{}) is ill-formed. It will use Production::value as the underlying callback/sink, passing the parse state to .sink() and as state parameter to the callback.

  3. ParseState is void. It will use Production::value as the underlying callback/sink.

If state.value_of(Production{}) or Production::value is well-formed, production_has_value_callback<Production, ParseState> is true, false otherwise.

The behavior of the member functions depends on three cases:

  1. If the underlying callback/sink is a callback, return_type is its return type, .sink() is ill-formed and operator() forwards to Production::value.operator().

  2. If the underlying callback/sink is a sink, return_type is its return type, .sink() forwards to Production::value.sink(), and operator() accepts the return type of the sink and forwards it unchanged.

  3. If the underlying callback/sink is both a callback and a sink, return_type is the return type of the callback, .sink() forwards to the sink, and operator() to the callback.

Tip
Use lexy::operator>>  to combine a sink and a callback in one Production::value.

Function lexy::max_recursion_depth

lexy/grammar.hpp
namespace lexy
{
    template <production EntryProduction>
    consteval std::size_t max_recursion_depth();
}

Returns the maximum recursion depth of a grammar given its entry production.

If the entry production has a static std::size_t member named max_recursion_depth (i.e. EntryProduction::max_recursion_depth is well-formed), returns that value. Otherwise returns an implementation-defined "big" value (currently 1024).

If the recursion depth of lexy::dsl::recurse  exceeds this value, an error is raised.

See also