Header lexy/callback.hpp

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

Callback

lexy/callback.hpp
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.

Sink

lexy/callback.hpp
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
lexy::callback 

Turn an overload set of function objects into a callback.

lexy::mem_fn 

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.

Primitives
lexy::noop 

Do nothing.

lexy::constant 

Produce a constant value.

lexy::forward 

Forward an existing value unchanged.

lexy::construct  and lexy::new_ 

Construct a new object.

lexy::bit_cast 

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

Rule specific
lexy::as_integer 

Produce a (signed) integer value.

lexy::as_string 

Produce a string.

lexy::as_list  and lexy::as_collection 

Produce a container from all list items.

lexy::as_aggregate 

Produce an aggregate by setting the specified members.