1 | <html> |
---|
2 | <head> |
---|
3 | <title>Semantic Actions</title> |
---|
4 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
---|
5 | <link rel="stylesheet" href="theme/style.css" type="text/css"> |
---|
6 | </head> |
---|
7 | |
---|
8 | <body> |
---|
9 | <table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2"> |
---|
10 | <tr> |
---|
11 | <td width="10"> |
---|
12 | </td> |
---|
13 | <td width="85%"> |
---|
14 | <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Semantic Actions</b></font> |
---|
15 | </td> |
---|
16 | <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td> |
---|
17 | </tr> |
---|
18 | </table> |
---|
19 | <br> |
---|
20 | <table border="0"> |
---|
21 | <tr> |
---|
22 | <td width="10"></td> |
---|
23 | <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td> |
---|
24 | <td width="30"><a href="subrules.html"><img src="theme/l_arr.gif" border="0"></a></td> |
---|
25 | <td width="30"><a href="indepth_the_parser.html"><img src="theme/r_arr.gif" border="0"></a></td> |
---|
26 | </tr> |
---|
27 | </table> |
---|
28 | <p>Semantic actions have the form: <b>expression[action]</b></p> |
---|
29 | <p>Ultimately, after having defined our grammar and having generated a corresponding |
---|
30 | parser, we will need to produce some output and do some work besides syntax |
---|
31 | analysis; unless, of course, what we want is merely to check for the conformance |
---|
32 | of an input with our grammar, which is very seldom the case. Semantic actions |
---|
33 | may be attached to any expression at any level within the parser hierarchy. |
---|
34 | An action is a C/C++ function or function object that will be called if a match |
---|
35 | is found in the particular context where it is attached. The action function |
---|
36 | serves as a hook into the parser and may be used to, for example:</p> |
---|
37 | <blockquote> |
---|
38 | <p><img src="theme/bullet.gif" width="13" height="13"> Generate output from |
---|
39 | the parser (ASTs, for example)<br> |
---|
40 | <img src="theme/bullet.gif" width="13" height="13"> Report warnings or errors<br> |
---|
41 | <img src="theme/bullet.gif" width="13" height="13"> Manage symbol tables</p> |
---|
42 | </blockquote> |
---|
43 | <h2>Generic Semantic Actions (Transduction Interface)</h2> |
---|
44 | <p>A generic semantic action can be any free function or function object that |
---|
45 | is compatible with the interface:</p> |
---|
46 | <pre><code><font color="#000000"><span class=identifier></span><span class=keyword> void </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>IteratorT </span><span class=identifier>first</span><span class=special>, </span><span class=identifier>IteratorT </span><span class=identifier>last</span><span class=special>);</span></font></code></pre> |
---|
47 | <p>where <tt>IteratorT</tt> is the type of iterator used, <tt>first</tt> points |
---|
48 | to the current input and <tt>last</tt> points to one after the end of the input |
---|
49 | (identical to STL iterator ranges). A function object (functor) should have |
---|
50 | a member <tt>operator()</tt> with the same signature as above:</p> |
---|
51 | <pre><code><font color="#000000"><span class=special> </span><span class=keyword>struct </span><span class=identifier>my_functor |
---|
52 | </span><span class=special>{ |
---|
53 | </span><span class=keyword>void </span><span class=keyword>operator</span><span class=special>()(</span><span class=identifier>IteratorT </span><span class=identifier>first</span><span class=special>, </span><span class=identifier>IteratorT </span><span class=identifier>last</span><span class=special>) </span><span class=keyword>const</span><span class=special>; |
---|
54 | </span><span class=special>};</span></font></code></pre> |
---|
55 | <p>Iterators pointing to the matching portion of the input are passed into the |
---|
56 | function/functor.</p> |
---|
57 | <p>In general, semantic actions accept the first-last iterator pair. This is the |
---|
58 | transduction interface. The action functions or functors receive the unprocessed |
---|
59 | data representing the matching production directly from the input. In many cases, |
---|
60 | this is sufficient. Examples are source to source translation, pre-processing, |
---|
61 | etc. </p> |
---|
62 | <h3>Example:</h3> |
---|
63 | <pre><code><font color="#000000"><span class=special> </span><span class=keyword>void |
---|
64 | </span><span class=identifier>my_action</span><span class=special>(</span><span class=keyword>char const</span><span class=special>* </span><span class=identifier>first</span><span class=special>, </span><span class=keyword>char const</span><span class=special>* </span><span class=identifier>last</span><span class=special>) |
---|
65 | { |
---|
66 | </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special> </span><span class="identifier">str</span><span class=special>(</span><span class=identifier>first</span><span class=special>, </span><span class=identifier>last</span><span class=special>); |
---|
67 | </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special><< </span><span class=identifier>str </span><span class=special><< </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>; |
---|
68 | } |
---|
69 | |
---|
70 | </span><span class=identifier>rule</span><span class=special><> </span><span class=identifier>myrule </span><span class=special>= (</span><span class=identifier>a </span><span class=special>| </span><span class=identifier>b </span><span class=special>| *(</span><span class=identifier>c </span><span class=special>>> </span><span class=identifier>d</span><span class=special>))[&</span><span class=identifier>my_action</span><span class=special>];</span></font></code></pre> |
---|
71 | <p>The function <tt>my_action</tt> will be called whenever the expression <tt>(a |
---|
72 | | b | *(c >> d)</tt> matches a portion of the input stream while parsing. |
---|
73 | Two iterators, <tt>first</tt> and <tt>last</tt>, are passed into the function. |
---|
74 | These iterators point to the start and end, respectively, of the portion of |
---|
75 | input stream where the match is found.</p> |
---|
76 | <h3>Const-ness:</h3> |
---|
77 | <p>With functors, take note that the <tt>operator()</tt> should be <tt>const</tt>. |
---|
78 | This implies that functors are immutable. One may wish to have some member variables |
---|
79 | that are modified when the action gets called. This is not a good idea. First |
---|
80 | of all, functors are preferably lightweight. Functors are passed around a lot |
---|
81 | and it would incur a lot of overhead if the functors are heavily laden. Second, |
---|
82 | functors are passed by value. Thus, the actual functor object that finally attaches |
---|
83 | to the parser, will surely not be the original instance supplied by the client. |
---|
84 | What this means is that changes to a functor's state will not affect the original |
---|
85 | functor that the client passed in since they are distinct copies. If a functor |
---|
86 | needs to update some state variables, which is often the case, it is better |
---|
87 | to use references to external data. The following example shows how this can |
---|
88 | be done:</p> |
---|
89 | <pre><code><font color="#000000"><span class=special> </span><span class=keyword>struct </span><span class=identifier>my_functor |
---|
90 | </span><span class=special>{ |
---|
91 | </span><span class=identifier>my_functor</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>& </span><span class=identifier>str_</span><span class=special>) |
---|
92 | </span><span class=special>: </span><span class=identifier>str</span><span class=special>(</span><span class=identifier>str_</span><span class=special>) </span><span class=special>{} |
---|
93 | |
---|
94 | </span><span class=keyword>void |
---|
95 | </span><span class=keyword>operator</span><span class=special>()(</span><span class=identifier>IteratorT </span><span class=identifier>first</span><span class=special>, </span><span class=identifier>IteratorT </span><span class=identifier>last</span><span class=special>) </span><span class=keyword>const |
---|
96 | </span><span class=special>{ |
---|
97 | </span><span class=identifier>str</span><span class=special>.</span><span class=identifier>assign_a</span><span class=special>(</span><span class=identifier>first</span><span class=special>, </span><span class=identifier>last</span><span class=special>); |
---|
98 | </span><span class=special>} |
---|
99 | |
---|
100 | </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>& </span><span class=identifier>str</span><span class=special>; |
---|
101 | </span><span class=special>};</span></font></code></pre> |
---|
102 | <h3>Full Example:</h3> |
---|
103 | <p>Here now is our calculator enhanced with semantic actions:</p> |
---|
104 | <pre><code><font color="#000000"><span class=special> </span><span class=keyword>namespace |
---|
105 | </span><span class=special>{ |
---|
106 | </span><span class=keyword>void </span><span class=identifier>do_int</span><span class=special>(</span><span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>str</span><span class=special>, </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>end</span><span class=special>) |
---|
107 | </span><span class=special>{ |
---|
108 | </span><span class=identifier>string </span><span class=identifier>s</span><span class=special>(</span><span class=identifier>str</span><span class=special>, </span><span class=identifier>end</span><span class=special>); |
---|
109 | </span><span class=identifier>cout </span><span class=special><< </span><span class=string>"PUSH(" </span><span class=special><< </span><span class=identifier>s </span><span class=special><< </span><span class=literal>')' </span><span class=special><< </span><span class=identifier>endl</span><span class=special>; |
---|
110 | </span><span class=special>} |
---|
111 | |
---|
112 | </span><span class=keyword>void </span><span class=identifier>do_add</span><span class=special>(</span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*, </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*) </span><span class=special>{ </span><span class=identifier>cout </span><span class=special><< </span><span class=string>"ADD\n"</span><span class=special>; </span><span class=special>} |
---|
113 | </span><span class=keyword>void </span><span class=identifier>do_subt</span><span class=special>(</span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*, </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*) </span><span class=special>{ </span><span class=identifier>cout </span><span class=special><< </span><span class=string>"SUBTRACT\n"</span><span class=special>; </span><span class=special>} |
---|
114 | </span><span class=keyword>void </span><span class=identifier>do_mult</span><span class=special>(</span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*, </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*) </span><span class=special>{ </span><span class=identifier>cout </span><span class=special><< </span><span class=string>"MULTIPLY\n"</span><span class=special>; </span><span class=special>} |
---|
115 | </span><span class=keyword>void </span><span class=identifier>do_div</span><span class=special>(</span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*, </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*) </span><span class=special>{ </span><span class=identifier>cout </span><span class=special><< </span><span class=string>"DIVIDE\n"</span><span class=special>; </span><span class=special>} |
---|
116 | </span><span class=keyword>void </span><span class=identifier>do_neg</span><span class=special>(</span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*, </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*) </span><span class=special>{ </span><span class=identifier>cout </span><span class=special><< </span><span class=string>"NEGATE\n"</span><span class=special>; </span><span class=special>} |
---|
117 | </span><span class=special>}</span></font></code></pre> |
---|
118 | <p>We augment our grammar with semantic actions:</p> |
---|
119 | <pre><code><font color="#000000"><span class=special> </span><span class=keyword>struct </span><span class=identifier>calculator </span><span class=special>: </span><span class=keyword>public </span><span class=identifier>grammar</span><span class=special><</span><span class=identifier>calculator</span><span class=special>> |
---|
120 | </span><span class=special>{ |
---|
121 | </span><span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>ScannerT</span><span class=special>> |
---|
122 | </span><span class=keyword>struct </span><span class=identifier>definition |
---|
123 | </span><span class=special>{ |
---|
124 | </span><span class=identifier>definition</span><span class=special>(</span><span class=identifier>calculator </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>self</span><span class=special>) |
---|
125 | </span><span class=special>{ |
---|
126 | </span><span class=identifier>expression |
---|
127 | </span><span class=special>= </span><span class=identifier>term |
---|
128 | </span><span class=special>>> </span><span class=special>*( </span><span class=special>(</span><span class=literal>'+' </span><span class=special>>> </span><span class=identifier>term</span><span class=special>)[&</span><span class=identifier>do_add</span><span class=special>] |
---|
129 | </span><span class=special>| </span><span class=special>(</span><span class=literal>'-' </span><span class=special>>> </span><span class=identifier>term</span><span class=special>)[&</span><span class=identifier>do_subt</span><span class=special>] |
---|
130 | </span><span class=special>) |
---|
131 | </span><span class=special>; |
---|
132 | |
---|
133 | </span><span class=identifier>term </span><span class=special>= |
---|
134 | </span><span class=identifier>factor |
---|
135 | </span><span class=special>>> </span><span class=special>*( </span><span class=special>(</span><span class=literal>'*' </span><span class=special>>> </span><span class=identifier>factor</span><span class=special>)[&</span><span class=identifier>do_mult</span><span class=special>] |
---|
136 | </span><span class=special>| </span><span class=special>(</span><span class=literal>'/' </span><span class=special>>> </span><span class=identifier>factor</span><span class=special>)[&</span><span class=identifier>do_div</span><span class=special>] |
---|
137 | </span><span class=special>) |
---|
138 | </span><span class=special>; |
---|
139 | |
---|
140 | </span><span class=identifier>factor |
---|
141 | </span><span class=special>= </span><span class=identifier>lexeme_d</span><span class=special>[(+</span><span class=identifier>digit_p</span><span class=special>)[&</span><span class=identifier>do_int</span><span class=special>]] |
---|
142 | </span><span class=special>| </span><span class=literal>'(' </span><span class=special>>> </span><span class=identifier>expression </span><span class=special>>> </span><span class=literal>')' |
---|
143 | </span><span class=special>| </span><span class=special>(</span><span class=literal>'-' </span><span class=special>>> </span><span class=identifier>factor</span><span class=special>)[&</span><span class=identifier>do_neg</span><span class=special>] |
---|
144 | </span><span class=special>| </span><span class=special>(</span><span class=literal>'+' </span><span class=special>>> </span><span class=identifier>factor</span><span class=special>) |
---|
145 | </span><span class=special>; |
---|
146 | </span><span class=special>} |
---|
147 | |
---|
148 | </span><span class=identifier>rule</span><span class=special><</span><span class=identifier>ScannerT</span><span class=special>> </span><span class=identifier>expression</span><span class=special>, </span><span class=identifier>term</span><span class=special>, </span><span class=identifier>factor</span><span class=special>; |
---|
149 | |
---|
150 | </span><span class=identifier>rule</span><span class=special><</span><span class=identifier>ScannerT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& |
---|
151 | </span><span class=identifier>start</span><span class=special>() </span><span class=keyword>const </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>expression</span><span class=special>; </span><span class=special>} |
---|
152 | </span><span class=special>}; |
---|
153 | </span><span class=special>};</span></font></code></pre> |
---|
154 | <p>Feeding in the expression <tt>(-1 + 2) * (3 + -4)</tt>, for example, to the |
---|
155 | rule <tt>expression</tt> will produce the expected output:</p> |
---|
156 | <pre><code><span class=special>-</span><span class=number>1 |
---|
157 | </span><span class=number>2 |
---|
158 | </span><span class=identifier>ADD |
---|
159 | </span><span class=number>3 |
---|
160 | </span><span class=special>-</span><span class=number>4 |
---|
161 | </span><span class=identifier>ADD |
---|
162 | </span><span class=identifier>MULT</span></code></pre> |
---|
163 | <p>which, by the way, is the Reverse Polish Notation (RPN) of the given expression, |
---|
164 | reminiscent of some primitive calculators and the language Forth.</p> |
---|
165 | <p><img src="theme/lens.gif" width="15" height="16"> <a href="../example/fundamental/calc_plain.cpp">View |
---|
166 | the complete source code here</a>. This is part of the Spirit distribution. |
---|
167 | </p> |
---|
168 | <h2><a name="specialized_actions"></a>Specialized Actions</h2> |
---|
169 | <p>In general, semantic actions accept the first-last iterator pair. There are |
---|
170 | situations though where we might want to pass data in its processed form. A |
---|
171 | concrete example is the numeric parser. It is unwise to pass unprocessed data |
---|
172 | to a semantic action attached to a numeric parser and just throw away what has |
---|
173 | been parsed by the parser. We want to pass the actual parsed number.</p> |
---|
174 | <p>The function and functor signature of a semantic action varies depending on |
---|
175 | the parser where it is attached to. The following table lists the parsers that |
---|
176 | accept unique signatures.</p> |
---|
177 | <table width="80%" border="0" align="center"> |
---|
178 | <tr> |
---|
179 | <td class="note_box"><img src="theme/note.gif" width="16" height="16"> Unless |
---|
180 | explicitly stated in the documentation of a specific parser type, parsers |
---|
181 | not included in the list by default expect the generic signature as explained |
---|
182 | above.</td> |
---|
183 | </tr> |
---|
184 | </table> |
---|
185 | <h3>Numeric Actions</h3> |
---|
186 | <p><b>Applies to:</b></p> |
---|
187 | <blockquote> |
---|
188 | <p><img src="theme/bullet.gif" width="13" height="13"> uint_p<br> |
---|
189 | <img src="theme/bullet.gif" width="13" height="13"> int_p<br> |
---|
190 | <img src="theme/bullet.gif" width="13" height="13"> ureal_p<br> |
---|
191 | <img src="theme/bullet.gif" width="13" height="13"> real_p</p> |
---|
192 | </blockquote> |
---|
193 | <p><b>Signature for functions:</b></p> |
---|
194 | <pre><code><font color="#000000"><span class=identifier> </span><span class=keyword>void </span><span class=identifier>func</span><span class=special>(</span><span class=identifier>NumT </span><span class=identifier>val</span><span class=special>);</span></font></code></pre> |
---|
195 | <p><b>Signature for functors:</b> </p> |
---|
196 | <pre><code><font color="#000000"><span class=special> </span><span class=keyword>struct </span><span class=identifier>ftor |
---|
197 | </span><span class=special>{ |
---|
198 | </span><span class=keyword>void </span><span class=keyword>operator</span><span class=special>()(</span><span class=identifier>NumT </span><span class=identifier>val</span><span class=special>) </span><span class=keyword>const</span><span class=special>; |
---|
199 | </span><span class=special>};</span></font></code></pre> |
---|
200 | <p>Where <tt>NumT</tt> is any primitive numeric type such as <tt>int</tt>, <tt>long</tt>, |
---|
201 | <tt>float</tt>, <tt>double</tt>, etc., or a user defined numeric type such as |
---|
202 | big_int. <tt>NumT</tt> is the same type used as template parameter to <tt>uint_p</tt>, |
---|
203 | <tt>int_p</tt>, <tt>ureal_p</tt> or <tt>real_p</tt>. The parsed number is passed |
---|
204 | into the function/functor.</p> |
---|
205 | <h3>Character Actions</h3> |
---|
206 | <p><b>Applies to:</b></p> |
---|
207 | <blockquote> |
---|
208 | <p><img src="theme/bullet.gif" width="13" height="13"> chlit, ch_p<br> |
---|
209 | <img src="theme/bullet.gif" width="13" height="13"> range, range_p<br> |
---|
210 | <img src="theme/bullet.gif" width="13" height="13"> anychar<br> |
---|
211 | <img src="theme/bullet.gif" width="13" height="13"> alnum, alpha<br> |
---|
212 | <img src="theme/bullet.gif" width="13" height="13"> cntrl, digit<br> |
---|
213 | <img src="theme/bullet.gif" width="13" height="13"> graph, lower<br> |
---|
214 | <img src="theme/bullet.gif" width="13" height="13"> print, punct<br> |
---|
215 | <img src="theme/bullet.gif" width="13" height="13"> space, upper<br> |
---|
216 | <img src="theme/bullet.gif" width="13" height="13"> xdigit</p> |
---|
217 | </blockquote> |
---|
218 | <p><b>Signature for functions:</b></p> |
---|
219 | <pre><code><font color="#000000"><span class=identifier> </span><span class=keyword>void </span><span class=identifier>func</span><span class=special>(</span><span class=identifier>CharT </span><span class=identifier>ch</span><span class=special>);</span></font></code></pre> |
---|
220 | <p><b>Signature for functors:</b></p> |
---|
221 | <pre><code><font color="#000000"><span class=special> </span><span class=keyword>struct </span><span class=identifier>ftor |
---|
222 | </span><span class=special>{ |
---|
223 | </span><span class=keyword>void </span><span class=keyword>operator</span><span class=special>()(</span><span class=identifier>CharT </span><span class=identifier>ch</span><span class=special>) </span><span class=keyword>const</span><span class=special>; |
---|
224 | </span><span class=special>};</span></font></code></pre> |
---|
225 | <p>Where <tt>CharT</tt> is the value_type of the iterator used in parsing. A <tt>char |
---|
226 | const*</tt> iterator for example has a <tt>value_type</tt> of <tt>char</tt>. |
---|
227 | The matching character is passed into the function/functor.</p> |
---|
228 | <h2>Cascading Actions</h2> |
---|
229 | <p>Actions can be cascaded. Cascaded actions also inherit the function/functor |
---|
230 | interface of the original. For example:</p> |
---|
231 | <pre><code><font color="#000000"><span class=special> </span><span class=identifier>uint_p</span><span class=special>[</span><span class=identifier>fa</span><span class=special>][</span><span class=identifier>fb</span><span class=special>][</span><span class=identifier>fc</span><span class=special>]</span></font></code></pre> |
---|
232 | <p>Here, the functors <tt>fa</tt>, <tt>fb</tt> and <tt>fc</tt> all expect the |
---|
233 | signature <tt>void operator()(unsigned n) const</tt>.</p> |
---|
234 | <h2>Directives and Actions</h2> |
---|
235 | <p>Directives inherit the the function/functor interface of the subject it is |
---|
236 | enclosing. Example:</p> |
---|
237 | <pre><code><font color="#000000"><span class=special> </span><span class=identifier>as_lower_d</span><span class=special>[</span><span class=identifier>ch_p</span><span class=special>(</span><span class=literal>'x'</span><span class=special>)][</span><span class=identifier>f</span><span class=special>]</span></font></code></pre> |
---|
238 | <p>Here, the functor <tt>f</tt> expects the signature <tt>void operator()(char |
---|
239 | ch) const</tt>, assuming that the iterator used is a <tt>char const*</tt>.</p> |
---|
240 | <table border="0"> |
---|
241 | <tr> |
---|
242 | <td width="10"></td> |
---|
243 | <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td> |
---|
244 | <td width="30"><a href="subrules.html"><img src="theme/l_arr.gif" border="0"></a></td> |
---|
245 | <td width="30"><a href="indepth_the_parser.html"><img src="theme/r_arr.gif" border="0"></a></td> |
---|
246 | </tr> |
---|
247 | </table> |
---|
248 | <br> |
---|
249 | <hr size="1"> |
---|
250 | <p class="copyright">Copyright © 1998-2003 Joel de Guzman<br> |
---|
251 | <br> |
---|
252 | <font size="2">Use, modification and distribution is subject to the Boost Software |
---|
253 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
254 | http://www.boost.org/LICENSE_1_0.txt)</font></p> |
---|
255 | <p> </p> |
---|
256 | <p> </p> |
---|
257 | </body> |
---|
258 | </html> |
---|