Header lexy/dsl/minus.hpp

Token rule lexy::dsl::operator-

lexy/dsl/minus.hpp
namespace lexy
{
    struct minus_failure {};
}

namespace lexy::dsl
{
    constexpr token-rule auto operator-(token-rule auto token,
                                        token-rule auto except);
}

operator- (minus) is a token rule matches token unless except matches as well.

Matching

Matches and consumes token. Then tries to match except on a partial input that consists of everything just consumed by token (ignoring the trailing whitespace). Succeeds only if that fails to match the entire partial input.

Errors
  • lexy::minus_failure: if except matches the entire partial input. Its range covers the partial input. The rule then fails.

  • All errors raised by matching token. The rule then fails.

Parse tree

Only a token node for token whose kind is determined by the minus rule; nothing for except.

Example 1. Match a string literal that doesn't contain control characters
struct production
{
    static constexpr auto rule = [] {
        // Arbitrary code points that aren't control characters.
        auto c = dsl::code_point - dsl::ascii::control;

        return dsl::quoted(c);
    }();
};
Caution
When using .error<Tag> to override the generic lexy::minus_failure tag, keep in mind that this also overrides all errors token might raise.
Tip
Use lexy::dsl::prefix or lexy::dsl::contains to prevent the requirement that except must match the entire input.
Note
token - a - b is entirely equivalent to the alternative token - (a / b) and also optimized in the same way.

Token rule lexy::dsl::prefix

lexy/dsl/minus.hpp
namespace lexy::dsl
{
    constexpr token-rule auto prefix(token-rule auto token)
    {
        return dsl::token(token + dsl::any);
    }
}

prefix is a token rule that matches token and then consumes the entire input.

It is meant to be used in combination with minus to remove tokens that start with a given token.

Example 2. Match words that don't start with 'no'
struct production
{
    static constexpr auto rule = [] {
        auto word = dsl::while_one(dsl::ascii::alnum);
        // Without dsl::prefix, only 'no' is forbidden.
        auto forbidden = dsl::prefix(LEXY_LIT("no"));
        return dsl::token(word) - forbidden;
    }();
};

Token rule lexy::dsl::contains

lexy/dsl/minus.hpp
namespace lexy::dsl
{
    constexpr token-rule auto contains(token-rule auto token);
}

contains is a token rule that matches if token is anywhere in the input.

It is meant to be used in combination with minus to remove tokens that contain a given token.

Matching

Tries to match token. If that fails, advances the reader and repeats. Only fails, if EOF is reached before token has been matched.

Errors

All errors raised by matching token at EOF. The rule then fails.

Parse tree

A token node that covers the entire input; its kind is determined by contains().

Example 3. Match words that don't contain 'no'
struct production
{
    static constexpr auto rule = [] {
        auto word = dsl::while_one(dsl::ascii::alnum);
        // Without dsl::contains, only 'no' is forbidden.
        auto forbidden = dsl::contains(LEXY_LIT("no"));
        return dsl::token(word) - forbidden;
    }();
};

See also