| Home | Libraries | People | FAQ | More

### Parser Semantic Actions

The example in the previous section was very simplistic. It only recognized data, but did nothing with it. It answered the question: "Did the input match?". Now, we want to extract information from what was parsed. For example, we would want to store the parsed number after a successful match. To do this, you will need semantic actions.

Semantic actions may be attached to any point in the grammar specification. These actions are polymorphic function objects that are called whenever a part of the parser successfully recognizes a portion of the input. Say you have a parser `p`, and a polymorphic C++ function object `f`. You can make the parser call `f` whenever it matches an input by attaching `f`:

    p[f]

The expression above links `f` to the parser, `p`. `f` is expected to be a polymorphic function object with the signature:

    template <typename Context>
    void operator()(Context const& ctx) const;

We can also use C++14 generic lambdas of the form:

    [](auto& ctx) { /*...*/ }

From the context, we can extract relevant information:

Table 2. Parse Context Access Functions

Function | Description | Example
--- | --- | ---
`_val` | A reference to the attribute of the innermost rule that directly or indirectly invokes the parser `p` | `_val(ctx) = "Gotya!"`
`_where` | Iterator range to the input stream | `_where(ctx).begin()`
`_attr` | A reference to the attribute of the parser `p` | `_val(ctx) += _attr(ctx)`
`_pass` | A reference to a `bool` flag that can be used to force the `p` to fail | `_pass(ctx) = false`

##### Examples of Semantic Actions

Given:

    struct print_action
    {
        template <typename Context>
        void operator()(Context const& ctx) const
        {
            std::cout << _attr(ctx) << std::endl;
        }
    };

Take note that with function objects, we need to have an `operator()` with the Context argument. If we don't care about the context, we can use `unused_type`. We'll see more of `unused_type` elsewhere. `unused_type` is a Spirit supplied support class.

All examples parse inputs of the form:

    "{NNN}"

Where NNN is an integer inside the curly braces (e.g. {44}).

The first example shows how to attach a function object:

    parse(first, last, '{' >> int_[print_action()] >> '}');

What's new? Well `int_` is the sibling of `double_`. I'm sure you can guess what this parser does.

The next example shows how use C++14 lambda:

    auto f = [](auto& ctx){ std::cout << _attr(ctx) << std::endl; };
    parse(first, last, '{' >> int_[f] >> '}');

Attaching semantic actions is the first hurdle one has to tackle when getting started with parsing with Spirit. Familiarize yourself with this task.

The examples above can be found here: actions.cpp