| [/============================================================================== |
| Copyright (C) 2001-2015 Joel de Guzman |
| Copyright (C) 2001-2011 Hartmut Kaiser |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| ===============================================================================/] |
| |
| [section:semantic_actions 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 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`]] |
| ] |
| |
| [heading 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: [@../../../example/x3/actions.cpp actions.cpp] |
| |
| [endsect] |