Header lexy/callback.hpp

Callbacks that receive the values produced during parsing and process them.


namespace lexy
    template <typename T>
    concept callback = requires { typename T::return_type; }

    template <typename T>
    constexpr bool is_callback = callback<T>;

    template <typename T, typename ... Args>
    concept callback-for = callback<T>
      && requires(const T& cb, Args&&... args) {
          { cb(std::forward<Args>(args)...) }
            -> std::same_as<typename T::return_type>;

    template <typename T, typename ... Args>
    constexpr bool is_callback_for = callback-for<T, Args..>;

    template <typename T, typename State, typename ... Args>
    concept callback-with-state = callback<T>
      && requires(const T& cb, State& state) {
            { cb[state](std::forward<Args>(args)...) }
              -> std::same_as<typename T::return_type>;

    template <typename T, typename State>
    constexpr bool is_callback_state
        = callback-with-state<T, State, some-arguments...>;

A callback is a function object with a return_type typedef that specifies its return type.

The callback can have multiple overloads of operator(), but all of them must return the same type. To be usable in the grammar, a callback must not have any mutable state.

A callback can optionally take a state. This is an additional parameter that is passed via operator[] in addition to all the arguments. During parsing, the callback arguments are the values produced by the rules while the state parameter is the parse state.


namespace lexy
    template <typename T>
    concept sink-callback = requires (T& cb) {
          typename T::return_type;

          // there exist some args... with:
          { cb(args...) } -> std::same_as<void>;

          { std::move(cb).finish() } -> std::same_as<typename T::return_type>;

    template <typename T, typename ... Args>
    concept sink = requires (const T& s, Args&&... args) {
          { s.sink(std::forward<Args>(args)...) } -> sink-callback;

    template <typename T, typename... Args>
    constexpr bool is_sink = sink<T, Args...>;

    template <typename Sink, typename... Args>
    using sink_callback = /* return type of .sink(Args...) /;

    template <typename T, typename ... Args>
    constexpr bool is_sink_callback_for
      = / T is a sink callback that can be invoked with Args... */;

A sink is an object with a sink() member function that returns a sink callback, which is a callback that can be invoked multiples times before producing the final value.

The sink() member function can take arbitrary arguments to construct the sink callback. This is used to e.g. pass allocator parameters to a container’s constructor. During parsing, sink() is passed the parse state, if it accepts it, otherwise it is invoked without arguments.

The sink callback can be invoked with some arguments, and will somehow append them to the result. Calling finish() on the sink callback will return the finished result. Once finish() has been called, the sink callback is never used again. During parsing, the sink callback is repeatedly invoked by values produced during a list rule.

Pre-defined callbacks and sinks

Adapters and composition

Turn an overload set of function objects into a callback.


Turn a member function/data pointer into a callback.

lexy::operator|  and lexy::operator>> 

Combine callbacks and sinks.

lexy::bind  and lexy::bind_sink 

Bind parameters and reorder and transform arguments of a callback or sink.

lexy::fold  and lexy::fold_inplace 

Fold over all arguments of a sink.


Do nothing.


Produce a constant value.


Forward an existing value unchanged.

lexy::construct  and lexy::new_ 

Construct a new object.


Constructs a new object by reinterpreting the bits of an existing one.

Rule specific

Produce a (signed) integer value.


Produce a string.

lexy::as_list  and lexy::as_collection 

Produce a container from all list items.


Produce an aggregate by setting the specified members.