Header lexy/dsl/error.hpp

Rules that generate errors.

Rule lexy::dsl::error

lexy/dsl/error.hpp
namespace lexy::dsl
{
    template <typename Tag>
    constexpr branch-rule auto error;

    template <typename Tag>
    constexpr branch-rule auto error(rule auto rule);
}

error is a rule that always fails and reports an error.

Parsing

The first overload fails immediately without consuming anything. The second overload first tries to match rule in a new context. The rule then still fails unconditionally without consuming anything.

Branch parsing

In a branch, error fails in the same way, but the branch has been considered taken and no backtracking occurs.

Errors

A generic error with the specified Tag. For the first overload, it is raised at the unchanged reader position. For the second overload, its range covers everything matched by rule. The rule then fails.

Values

None.

Example 1. Generate a custom error for an unknown greeting
struct production
{
    struct unknown_greeting
    {
        static constexpr auto name = "unknown greeting";
    };

    static constexpr auto rule
        // Generate a custom error for an unknown greeting.
        = LEXY_LIT("Hello") | LEXY_LIT("Hi") | dsl::error<unknown_greeting>;
};
Example 2. Generate a custom error for an unknown greeting with range
struct production
{
    struct unknown_greeting
    {
        static constexpr auto name = "unknown greeting";
    };

    static constexpr auto rule
        // Generate a custom error for an unknown greeting.
        = LEXY_LIT("Hello") | LEXY_LIT("Hi")
          | dsl::error<unknown_greeting>(dsl::while_(dsl::ascii::alpha));
};
Tip
Use error in error production: if a certain ill-formed input is common, create a separate rule for it. If it is parsed, a custom error is always raised.
Note
Automatic whitespace  skipping is disabled while parsing rule.
Warning
rule does not have access to any context variables created by the context-sensitive parsing facilities and it can’t use recursion.

Branch rule lexy::dsl::must

lexy/dsl/error.hpp
namespace lexy::dsl
{
    class must-dsl // note: not a rule itself
    {
    public:
        template <typename Tag>
        static constexpr branch-rule auto error;

        template <typename Tag>
        constexpr branch-rule auto error(rule auto capture);
    };

    constexpr must-dsl must(branch-rule auto rule);
}

must is a branch rule that tries to parse another branch rule and raises a specific error if that backtracks.

If must(rule).error<Tag> is used, the associated error rule e is lexy::dsl::error<Tag>. Otherwise, if must(rule).error<Tag>(capture) is used, the associated error rule e is lexy::dsl::error<Tag>(capture).

Requires

rule is a branch rule that is not unconditionally taken (e.g. not lexy::dsl::else_ ).

Parsing

Parses the choice  rule | e, where e is the associated error rule, i.e. it tries to parse rule and raises a specific error if that fails.

Branch parsing

Tries to parse rule and produces the same result.

Errors
  • All errors raised by branch parsing of rule. The rule then fails if rule has failed.

  • A generic error with the specified Tag: if the rule backtracks during non-branch parsing. Its range covers anything consumed by the optional capture rule, just like lexy::dsl::error.

Example 3. Parse a very basic echo command
struct production
{
    struct expected_sep
    {
        static constexpr auto name = "expected separator";
    };

    static constexpr auto rule = [] {
        // A separator is either blank or \ + newline.
        // If a separator is not present, raise the specific error.
        auto blank      = dsl::ascii::blank;
        auto escaped_nl = dsl::backslash >> dsl::newline;
        auto sep        = dsl::must(blank | escaped_nl).error<expected_sep>;

        return LEXY_LIT("echo") + sep
               + dsl::identifier(dsl::ascii::alnum)
               // Allow an optional separator before EOL.
               + dsl::if_(sep) + dsl::eol;
    }();
};
Note
See shell.cpp for a more complete shell parser.
Tip
Use must(rule).error<Tag> if you sometimes need to parse rule unconditionally with a specific error, and sometimes as a branch rule.
Note
The difference between must(rule).error<Tag> and the choice  rule | lexy::dsl::error<Tag> is that the former is still a branch condition. The choice is not a branch condition, as it is unconditionally: it will either parse rule and succeed, or fail, but never backtrack. must on the other hand will behave exactly the same as rule during branch parsing. That way, something like lexy::dsl::if_ (must(rule).error<Tag>) is equivalent to lexy::dsl::if_(rule).
Note
If rule is a token rule, must(rule).error<Tag> is equivalent to rule.error<Tag>.

See also