Header lexy/dsl/brackets.hpp

Rules for parsing bracketed or parenthesized expressions.

Rule DSL lexy::dsl::brackets

lexy/dsl/brackets.hpp
namespace lexy::dsl
{
    struct brackets-dsl // note: not a rule itself
    {
        constexpr branch-rule auto open() const;
        constexpr branch-rule auto close() const;

        constexpr terminator-dsl as_terminator() const;

        constexpr brackets-dsl   limit(token-rule auto ... tokens);
        constexpr rule auto      recovery_rule() const;

        //=== rules ===//
        constexpr branch-rule auto operator()(rule auto rule) const;

        constexpr branch-rule auto try_(rule auto rule) const;

        constexpr branch-rule auto opt(rule auto rule) const;

        constexpr branch-rule auto list(rule auto item) const;
        constexpr branch-rule auto list(rule auto item, separator auto sep) const;

        constexpr branch-rule auto opt_list(rule auto item) const;
        constexpr branch-rule auto opt_list(rule auto item, separator auto sep) const;
    };

    constexpr brackets-dsl brackets(branch-rule auto open, branch-rule auto close);
}

brackets is not a rule, but a DSL for specifying rules that all parse something surrounded by brackets.

Many rules require a branch rule as argument, like lexy::dsl::list. However, there isn’t always an easy way to check for a branch condition and sometimes the rule in question is always surrounded by brackets. Then you can use brackets: it specifies branch rules for open and closing brackets and provides ways of building rules where any branch condition is just "the closing bracket hasn’t been matched yet". As such, you don’t need to provide a branch condition anymore.

Common brackets, like parentheses, are predefined (see below).

Note
See lexy::dsl::terminator if you want to parse something that is just terminated by something and doesn’t have an "opening bracket".

Branch rules .open() and .close()

lexy/dsl/brackets.hpp
constexpr branch-rule auto open() const;  (1)
constexpr branch-rule auto close() const; (2)
  1. Returns the opening bracket rule passed as first argument to brackets().

  2. Returns the opening bracket rule passed as second argument to brackets().

.as_terminator(), .limit(), and .recovery_rule()

lexy/dsl/brackets.hpp
constexpr terminator-dsl as_terminator() const;             (1)

constexpr brackets-dsl   limit(token-rule auto ... tokens); (2)
constexpr rule auto      recovery_rule() const;             (3)
  1. Returns the corresponding terminator.

  2. Sets the limit for error recovery.

  3. Returns as_terminator().recovery_rule().

brackets itself is just a thin wrapper over lexy::dsl::terminator; as_terminator() returns that terminator: lexy::dsl::brackets(open, close).as_terminator() is equivalent to lexy::dsl::terminator(close); lexy::dsl::brackets(open, close).limit(tokens…​).as_terminator() is equivalent to lexy::dsl::terminator(close).limit(tokens…​).as_terminator().

Bracketed rules

lexy/dsl/brackets.hpp
constexpr branch-rule auto operator()(rule auto rule) const
{
    return open() >> as_terminator()(rule);
}

constexpr branch-rule auto try_(rule auto rule) const
{
    return open() >> as_terminator().try_(rule);
}

constexpr branch-rule auto opt(rule auto rule) const
{
    return open() >> as_terminator().opt(rule);
}

constexpr branch-rule auto list(rule auto item) const
{
    return open() >> as_terminator().list(item);
}
constexpr branch-rule auto list(rule auto item, separator auto sep) const
{
    return open() >> as_terminator().list(item, sep);
}

constexpr branch-rule auto opt_list(rule auto item) const
{
    return open() >> as_terminator().opt_list(item);
}
constexpr branch-rule auto opt_list(rule auto item, separator auto sep) const
{
    return open() >> as_terminator().opt_list(item, sep);
}

Parse something surrounded by brackets.

They are all entirely equivalent to the expression indicated above: the result is a branch whose condition is open(), and then it parses as_terminator().foo(…​), where the terminator is close().

Predefined brackets

lexy/dsl/brackets.hpp
namespace lexy::dsl
{
    constexpr brackets-dsl auto round_bracketed  = brackets(lit_c<'('>, lit_c<')'>);
    constexpr brackets-dsl auto square_bracketed = brackets(lit_c<'['>, lit_c<']'>);
    constexpr brackets-dsl auto curly_bracketed  = brackets(lit_c<'{'>, lit_c<'}'>);
    constexpr brackets-dsl auto angle_bracketed  = brackets(lit_c<'<'>, lit_c<'>'>);

    constexpr brackets-dsl auto parenthesized = round_bracketed;
}

ASCII brackets are pre-defined.

Example 1. Parse a parenthesized list of things
struct production
{
    static constexpr auto rule = [] {
        auto item = LEXY_LIT("abc") | LEXY_LIT("123");

        return dsl::parenthesized.list(item, dsl::sep(dsl::comma));
    }();
};

See also