• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/==============================================================================
2    Copyright (C) 2001-2011 Joel de Guzman
3    Copyright (C) 2001-2011 Hartmut Kaiser
4
5    Distributed under the Boost Software License, Version 1.0. (See accompanying
6    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7===============================================================================/]
8
9[section:semantic_actions Generator Semantic Actions]
10
11In the previous section we mentioned a very important difference between parsers
12and generators. While parsers may be used without 'producing' any data,
13generators always need data to generate the output from. We mentioned one way
14of passing data to the generator by supplying it as a parameter to one of the
15main API functions (for instance `generate()` or `generate_delimited()`).
16But sometimes this is not possible or not desirable.
17
18Very much like for __qi__ we have semantic actions in __karma__ as well.
19Semantic actions may be attached to any point in the grammar specification.
20These actions are C++ functions or function objects that are called whenever a
21part of the generator is about to be invoked. Say you have a generator `G`,
22and a C++ function `F`, you can make the generator call `F` just before it gets
23invoked by attaching `F`:
24
25    G[F]
26
27The expression above links `F` to the generator, `G`.
28
29Semantic actions in __qi__ are invoked after a parser successfully
30matches its input and the matched value is passed into the
31semantic action. In __karma__ the opposite happens. Semantic actions are called
32before its associated generator is invoked. They may provide the data required
33by the generator.
34
35The function/function object signature depends on the type of the generator to
36which it is attached. The generator `double_` expects the number to generate.
37Thus, if we were to attach a function `F` to `double_`, we need `F` to be
38declared as:
39
40    void F(double& n);
41
42where the function is expected to initialize the parameter `n` with the value
43to generate.
44
45[important  Generally, and more formally, the semantic action `F` attached to
46            a generator `G` needs to take a reference to the generator's
47            attribute type as its first parameter. For more information about
48            generator attributes please see the section __karma_attribute__.
49
50            In the example above the function F takes a `double&` as its first
51            parameter as the attribute of the `double_` generator happens to be
52            a `double`.
53]
54
55There are actually 2 more arguments being passed (the generator context and a
56reference to a boolean 'pass' parameter). We don't need these, for now, but
57we'll see more on these other arguments later. __karma__ allows us to bind a
58single argument function, like above. The other arguments are simply ignored.
59
60To sum up, the possible signatures for semantic actions are:
61
62    void f(Attrib&);
63    void f(Attrib&, Context&);
64    void f(Attrib&, Context&, bool&);
65
66[heading Examples of Semantic Actions]
67
68In the following example we present various ways to attach semantic actions:
69
70* Using a plain function pointer
71* Using a simple function object
72* Using __boost_bind__ with a plain function
73* Using __boost_bind__ with a member function
74* Using __boost_lambda__
75
76[import ../../example/karma/actions.cpp]
77
78Let's assume we have:
79
80[karma_tutorial_semantic_action_functions]
81
82Take note that with function objects, we need to have an `operator()` with 3
83arguments. Since we don't care about the other two, we can use `unused_type` for
84these. We'll see more of `unused_type` elsewhere. Get used to it. `unused_type`
85is a Spirit supplied support class. Most of the time it stands for 'I don't
86care, just use the appropriate default'.
87
88All following examples generate outputs of the form:
89
90    "{integer}"
91
92An integer inside the curly braces.
93
94The first example shows how to attach a plain function:
95
96[karma_tutorial_attach_actions1]
97
98What's new? Well `int_` is the sibling of `double_`. I'm sure you can guess
99what this generator does and what type of attribute it expects.
100
101The next example shows how to attach a simple function object:
102
103[karma_tutorial_attach_actions2]
104
105We can use __boost_bind__ to 'bind' member functions:
106
107[karma_tutorial_attach_actions4]
108
109Likewise, we can also use __boost_bind__ to 'bind' plain functions:
110
111[karma_tutorial_attach_actions3]
112
113And last but not least, we can also use __boost_lambda__:
114
115[karma_tutorial_attach_actions5]
116
117There are more ways to bind semantic action functions, but the examples above
118are the most common. Attaching semantic actions is the first hurdle one has
119to tackle when getting started with generating with Spirit. If you didn't do so
120yet, it is probably a good idea to familiarize yourself with the tools behind
121it such as __boost_bind__ and __boost_lambda__.
122
123The examples above can be found here: [@../../example/karma/actions.cpp actions.cpp]
124
125[heading Phoenix]
126
127__phoenix__, a companion library bundled with Spirit, is specifically suited
128for binding semantic actions. It is like __boost_lambda__ on steroids, with
129special custom features that make it easy to integrate semantic actions with
130Spirit. If your requirements go beyond simple to moderate generation, I suggest
131you use this library. Examples presented henceforth shall be using the Phoenix
132library exclusively.
133
134[important There are different ways to write semantic actions for __karma__:
135           using plain functions, __boost_bind__, __boost_lambda__, or
136           __phoenix__. The latter three allow you to use special placeholders
137           to control parameter placement (`_1`, `_2`, etc.). Each of those
138           libraries has it's own implementation of the placeholders, all
139           in different namespaces. You have to make sure not to mix
140           placeholders with a library they don't belong to and not to
141           use different libraries while writing a semantic action.
142
143           Generally, for __boost_bind__, use `::_1`, `::_2`, etc. (yes, these
144           placeholders are defined in the global namespace).
145
146           For __boost_lambda__ use the placeholders defined in the namespace
147           `boost::lambda`.
148
149          For semantic actions written using __phoenix__ use the placeholders
150          defined in the namespace `boost::spirit`. Please note that all
151          existing placeholders for your convenience are also available from
152          the namespace `boost::spirit::karma`.]
153
154[endsect] [/ Semantic Actions]
155
156