c2d982481e
- Minimal example docs
91 lines
3.4 KiB
Plaintext
91 lines
3.4 KiB
Plaintext
[/==============================================================================
|
|
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]
|