Header lexy/error.hpp

Classes to store information about parse errors.

Class lexy::error

lexy/error.hpp
namespace lexy
{
    template <reader Reader, typename Tag>
    class error;

    template <reader Reader>
    class error<Reader, void>;

    struct expected_literal {};
    template <reader Reader>
    class error<Reader, expected_literal>;

    struct expected_keyword {};
    template <reader Reader>
    class error<Reader, expected_keyword>;

    struct expected_char_class {};
    template <reader Reader>
    class error<Reader, expected_char_class>;

    template <input Input, typename Tag>
    using error_for = error<input_reader<Input>, Tag>;
}

Represents a parse error.

Different kinds of errors are identified by the Tag, which is an empty tag type. The error type is specialized for three tags.

An error<R1, T> is implicitly convertible to an error<R2, T> as long as the R1::iterator and R2::iterator are the same type.

Generic error (primary template, void)

lexy/error.hpp
template <reader Reader, typename Tag>
class error : public error<Reader, void>
{
    using iterator = typename Reader::iterator;

public:
    constexpr explicit error(iterator begin, iterator end) noexcept;
    constexpr explicit error(iterator pos) noexcept;
};

template <reader Reader>
class error<void>
{
    using iterator = typename Reader::iterator;

public:
    constexpr explicit error(iterator begin, iterator end, const char msg) noexcept;
    constexpr explicit error(iterator pos, const char msg) noexcept
    : error(pos, pos)
    {}

    constexpr iterator position() const noexcept
    {
        return begin();
    }

    constexpr iterator begin() const noexcept;
    constexpr iterator end() const noexcept;

    constexpr const char* message() const noexcept;

    template <typename Tag>
    constexpr bool is(Tag) const noexcept;
};

A generic error without additional data.

position() is the position where the error occurred, while begin() and end() return the entire range. For some errors, this range is empty.

message() is determined by Tag (if typed) or the constructor argument (if type-erased). By default, it is the type name of Tag after removing the top-level namespace. This can be overridden by Tag::name() or Tag::name.

Example 1. Choice raises generic error at a single position
struct production
{
    static constexpr auto rule = LEXY_LIT("Hello") | LEXY_LIT("Hi");
};
Example 2. Identifier rules raise a generic error spanning a sub-range
struct production
{
    static constexpr auto rule = [] {
        // Define the general identifier syntax.
        auto head = dsl::ascii::alpha_underscore;
        auto tail = dsl::ascii::alpha_digit_underscore;
        auto id   = dsl::identifier(head, tail);

        // Define some keywords.
        auto kw_int    = LEXY_KEYWORD("int", id);
        auto kw_struct = LEXY_KEYWORD("struct", id);
        // ...

        // Parse an identifier
        return id
            // ... that is not a keyword,
            .reserve(kw_int, kw_struct)
            // ... doesn't start with an underscore,
            .reserve_prefix(dsl::lit_c<'_'>)
            // ... or contains a double underscore.
            .reserve_containing(LEXY_LIT("__"));
    }();
};

lexy::expected_literal error

lexy/error.hpp
struct expected_literal {};

template <reader Reader>
class error<Reader, expected_literal>
{
    using iterator  = typename Reader::iterator;
    using char_type = typename Reader::encoding::char_type;

public:
    constexpr explicit error(iterator pos,
                             const char_type string,
                             std::size_t index, std::size_t length) noexcept;

    constexpr iterator position() const noexcept;

    constexpr const char_type string() const noexcept;
    constexpr std::size_t index() const noexcept;
    constexpr std::size_t length() const noexcept;

    constexpr char_type character() const noexcept
    {
        return string()[index()];
    }
};

An error where a given literal string was expected.

The error can be raised while trying to parse string() with length() beginning at position(); the code unit at std::next(position(), index()) did not match character(). If the remaining input contained fewer code units than string(), index() indicates the first code unit that was missing.

It is raised by lexy::dsl::lit  and related rules.

Example 3. LEXY_LIT() raises an expected literal error
struct production
{
    static constexpr auto rule = LEXY_LIT("Hello World!");
};

lexy::expected_keyword error

lexy/error.hpp
struct expected_keyword {};

template <reader Reader>
class error<Reader, expected_keyword>
{
    using iterator  = typename Reader::iterator;
    using char_type = typename Reader::encoding::char_type;

public:
    constexpr explicit error(iterator begin, iterator end,
                             const char_type string, std::size_t length) noexcept;

    constexpr iterator position() const noexcept;

    constexpr iterator begin() const noexcept;
    constexpr iterator end() const noexcept;

    constexpr const char_type string() const noexcept;
    constexpr std::size_t length() const noexcept;
};

An error where a given keyword was expected.

The error can be raised while trying to parse the keyword string() with length() against the identifier [begin(), end()), but it was a different identifier. The position() is also begin().

It is raised by lexy::dsl::keyword .

Example 4. LEXY_KEYWORD() raises an expected keyword error
struct production
{
    static constexpr auto rule = [] {
        // Define the general identifier syntax.
        auto head = dsl::ascii::alpha_underscore;
        auto tail = dsl::ascii::alpha_digit_underscore;
        auto id   = dsl::identifier(head, tail);

        // Parse a keyword.
        return LEXY_KEYWORD("int", id);
    }();
};

lexy::expected_char_class error

lexy/error.hpp
struct expected_char_class {};

template <reader Reader>
class error<Reader, expected_keyword>
{
    using iterator  = typename Reader::iterator;

public:
    constexpr explicit error(iterator pos, const char name) noexcept;

    constexpr iterator position() const noexcept;

    constexpr const char name() const noexcept;
};

An error where one character from a character class was expected.

The error can be raised while trying to parse the character class with the human-readable name character_class() at position(). This happens in rules like lexy::dsl::ascii  or lexy::dsl::digit .

Example 5. dsl::digit raises an expected char class error
struct production
{
    static constexpr auto rule = dsl::digit<dsl::octal>;
};

Class lexy::error_context

lexy/error.hpp
namespace lexy
{
    template <input Input>
    class error_context
    {
        using iterator  = typename input_reader<Reader>::iterator;

    public:
        constexpr explicit error_context(production_info production,
                                         const Input& input,
                                         iterator pos) noexcept;

        const char* production() const noexcept;

        constexpr const Input& input() const noexcept;

        constexpr iterator position() const noexcept;
    };
}

Contains additional information about an error.

input()

The entire input where the error occurred; all positions are iterators into that input. If the input is lexy::lexeme_input , returns the parent input instead. This allows correct computation of the lexy::input_location .

production()

The name of the production where the error occurred, i.e. lexy::production_name . This is the first non-lexy::transparent_production  parent of the current production.

position()

The position where it started to parse the production.

See also