123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- [/==============================================================================
- 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]
|