Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/spirit/doc/closures.html @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 37.1 KB
RevLine 
[29]1<html>
2<head>
3<title>Closures</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<style type="text/css">
7<!--
8.style1 {font-family: "Courier New", Courier, mono}
9-->
10</style>
11</head>
12
13<body>
14<table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2">
15  <tr>
16    <td width="10">
17    </td>
18    <td width="85%">
19      <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Closures</b></font>
20    </td>
21    <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td>
22  </tr>
23</table>
24<br>
25<table border="0">
26  <tr>
27    <td width="10"></td>
28    <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
29    <td width="30"><a href="phoenix.html"><img src="theme/l_arr.gif" border="0"></a></td>
30    <td width="30"><a href="dynamic_parsers.html"><img src="theme/r_arr.gif" border="0"></a></td>
31  </tr>
32</table>
33<h2>Overview</h2>
34<p>Using phoenix, in the previous chapter, we've seen how we can get data from our parsers using <tt>var</tt>:</p>
35<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>int </span><span class=identifier>i</span><span class=special>;
36</span><span class=identifier>    integer </span><span class=special>= </span><span class=identifier>int_p</span><span class=special>[</span><span class="identifier">var</span><span class=special>(</span><span class=identifier>i</span><span class=special>) = </span><span class="identifier">arg1</span><span class=special>];</span></font></code></pre>
37<p>Nifty! Our rule <tt>integer</tt>, if successful, passes the parsed integer
38  to the variable <tt>i</tt>. Everytime we need to parse an integer, we can call
39  our rule <tt>integer</tt> and simply extract the parsed number from the variable
40  <tt>i</tt>. There's something you should be aware of though. In the viewpoint
41  of the grammar, the variable <tt>i</tt> is global. When the grammar gets more
42  complex, it's hard to keep track of the current state of <tt>i</tt>. And, with
43  recursive rules, global variables simply won't be adequate. </p>
44<p>Closures are needed if you need your rules (or grammars) to be reentrant. For example, a rule (or grammar) might be called recursively indirectly or directly by itself. The calculator is a good example. The expression rule recursively calls itself indirectly when it invokes the factor rule. </p>
45<p>Closures provide named (lazy) variables associated with each parse rule invocation. A closure variable is addressed using member syntax:</p>
46<pre><code><font color="#000000"><span class=identifier>    </span>rulename<span class="special">.</span>varname</font></code></pre>
47<p>A closure variable <tt>R.x</tt> may be addressed in the semantic action of any other rule invoked by <tt>R</tt>; it refers to the innermost enclosing invocation of <tt>R</tt>. If no such invocation exists, an assertion occurs at runtime. </p>
48<p>Closures provide an environment, a stack frame, for local variables.
49  Most importantly, the closure variables are accessible from the EBNF grammar
50  specification and can be used to pass parser information upstream or downstream
51  from the topmost rule down to the terminals in a top-down recursive descent.
52  Closures facilitate dynamic scoping in C++.
53  Spirit's closure implementation is based on <em>Todd Veldhuizen</em>'s <strong>Dynamic
54  scoping in C++</strong> technique that he presented in his paper <a href="ftp://ftp.cs.indiana.edu/pub/techreports/TR542.pdf">Techniques
55  for Scientic C++</a>. </p>
56<p>When a rule is given a closure, the closure's local variables are created prior
57    to entering the parse function and destructed after exiting the parse function.
58    These local variables are true local variables that exist on the hardware stack.</p>
59<table width="80%" border="0" align="center">
60  <tr>
61    <td class="note_box"><img src="theme/alert.gif" width="16" height="16"> <strong>Closures</strong>
62      <strong>and Phoenix</strong><br> <br>
63      Spirit v1.8 closure support requires <a href="../phoenix/index.html">Phoenix</a>.
64      In the future, Spirit will fully support <a href="../../../libs/lambda/index.html">BLL</a>.
65      Currently, work is underway to merge the features of both libraries.</td>
66  </tr>
67</table>
68<h2>Example</h2>
69<p>Let's go back to the calculator grammar introduced in the <a href="functional.html">Functional</a> chapter. Here's the full grammar again, plus the closure declarations:</p>
70<pre><span class=special>    </span><span class=keyword>struct </span><span class=identifier>calc_closure </span><span class=special>: </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>spirit</span><span class=special>::</span><span class=identifier>closure</span><span class=special>&lt;</span><span class=identifier>calc_closure</span><span class=special>, </span><span class=keyword>double</span><span class=special>&gt;
71    </span><span class=special>{
72        </span><span class=identifier>member1 </span><span class=identifier>val</span><span class=special>;
73    </span><span class=special>};
74
75    </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>&lt;</span><span class=identifier>calculator</span><span class=special>, </span><span class=identifier>calc_closure</span><span class=special>::</span><span class=identifier>context_t</span><span class=special>&gt;
76    </span><span class=special>{
77        </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>ScannerT</span><span class=special>&gt;
78        </span><span class=keyword>struct </span><span class=identifier>definition
79        </span><span class=special>{
80            </span><span class=identifier>definition</span><span class=special>(</span><span class=identifier>calculator </span><span class=keyword>const</span><span class=special>&amp; </span><span class=identifier>self</span><span class=special>)
81            </span><span class=special>{
82                </span><span class=identifier>top </span><span class=special>= </span><span class=identifier>expression</span><span class=special>[</span><span class=identifier>self</span><span class=special>.</span><span class=identifier>val </span><span class=special>= </span><span class=identifier>arg1</span><span class=special>];
83
84                </span><span class=identifier>expression
85                    </span><span class=special>=   </span><span class=identifier>term</span><span class=special>[</span><span class=identifier>expression</span><span class=special>.</span><span class=identifier>val </span><span class=special>= </span><span class=identifier>arg1</span><span class=special>]
86                        </span><span class=special>&gt;&gt; </span><span class=special>*(   </span><span class=special>(</span><span class=literal>'+' </span><span class=special>&gt;&gt; </span><span class=identifier>term</span><span class=special>[</span><span class=identifier>expression</span><span class=special>.</span><span class=identifier>val </span><span class=special>+= </span><span class=identifier>arg1</span><span class=special>])
87                            </span><span class=special>|   </span><span class=special>(</span><span class=literal>'-' </span><span class=special>&gt;&gt; </span><span class=identifier>term</span><span class=special>[</span><span class=identifier>expression</span><span class=special>.</span><span class=identifier>val </span><span class=special>-= </span><span class=identifier>arg1</span><span class=special>])
88                            </span><span class=special>)
89                    </span><span class=special>;
90
91                </span><span class=identifier>term
92                    </span><span class=special>=   </span><span class=identifier>factor</span><span class=special>[</span><span class=identifier>term</span><span class=special>.</span><span class=identifier>val </span><span class=special>= </span><span class=identifier>arg1</span><span class=special>]
93                        </span><span class=special>&gt;&gt; </span><span class=special>*(   </span><span class=special>(</span><span class=literal>'*' </span><span class=special>&gt;&gt; </span><span class=identifier>factor</span><span class=special>[</span><span class=identifier>term</span><span class=special>.</span><span class=identifier>val </span><span class=special>*= </span><span class=identifier>arg1</span><span class=special>])
94                            </span><span class=special>|   </span><span class=special>(</span><span class=literal>'/' </span><span class=special>&gt;&gt; </span><span class=identifier>factor</span><span class=special>[</span><span class=identifier>term</span><span class=special>.</span><span class=identifier>val </span><span class=special>/= </span><span class=identifier>arg1</span><span class=special>])
95                            </span><span class=special>)
96                    </span><span class=special>;
97
98                </span><span class=identifier>factor
99                    </span><span class=special>=   </span><span class=identifier>ureal_p</span><span class=special>[</span><span class=identifier>factor</span><span class=special>.</span><span class=identifier>val </span><span class=special>= </span><span class=identifier>arg1</span><span class=special>]
100                    </span><span class=special>|   </span><span class=literal>'(' </span><span class=special>&gt;&gt; </span><span class=identifier>expression</span><span class=special>[</span><span class=identifier>factor</span><span class=special>.</span><span class=identifier>val </span><span class=special>= </span><span class=identifier>arg1</span><span class=special>] </span><span class=special>&gt;&gt; </span><span class=literal>')'
101                    </span><span class=special>|   </span><span class=special>(</span><span class=literal>'-' </span><span class=special>&gt;&gt; </span><span class=identifier>factor</span><span class=special>[</span><span class=identifier>factor</span><span class=special>.</span><span class=identifier>val </span><span class=special>= </span><span class=special>-</span><span class=identifier>arg1</span><span class=special>])
102                    </span><span class=special>|   </span><span class=special>(</span><span class=literal>'+' </span><span class=special>&gt;&gt; </span><span class=identifier>factor</span><span class=special>[</span><span class=identifier>factor</span><span class=special>.</span><span class=identifier>val </span><span class=special>= </span><span class=identifier>arg1</span><span class=special>])
103                    </span><span class=special>;
104            </span><span class=special>}
105
106            </span><span class=keyword>typedef </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>, </span><span class=identifier>calc_closure</span><span class=special>::</span><span class=identifier>context_t</span><span class=special>&gt; </span><span class=identifier>rule_t</span><span class=special>;
107            </span><span class=identifier>rule_t </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>;
108            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>&gt; </span><span class=identifier>top</span><span class=special>;
109
110            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>&gt; </span><span class=keyword>const</span><span class=special>&amp;
111            </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>top</span><span class=special>; </span><span class=special>}
112        </span><span class=special>};
113    </span><span class=special>};</span></pre>
114<p> <img height="16" width="15" src="theme/lens.gif"> The full source code can be <a href="../example/fundamental/phoenix_calc.cpp">viewed here</a>. This is part of the Spirit distribution.</p>
115<p>Surely, we've come a long way from the original version of this calculator. With inline <a href="phoenix.html#lambda">lambda expressions</a>, we were able to write self contained grammars complete with semantic actions. </p>
116<p>The first thing to notice is the declaration of <tt>calc_closure</tt>. </p>
117<p> <strong>Declaring closures</strong></p>
118<p> The general closure declaration syntax is:</p>
119<pre><code>    <span class=keyword>struct </span><span class=identifier>name</span><span class=special></span> <span class=special>: </span><span class=identifier>spirit</span><span class=special>::</span><span class=identifier>closure</span><span class=special>&lt;</span><span class=identifier>name</span><span class=special>, </span><span class=keyword>type1, type2, type3,... typeN</span><span class=special>&gt;
120    {
121        </span><span class=identifier>member1 m_name1</span><span class=special>;
122        </span><span class=identifier>member2 m_name2</span><span class=special>;
123        </span><span class=identifier>member3 m_name3</span><span class=special>;
124        ...
125        </span><span class=identifier>memberN m_nameN</span><span class=special>;
126    };</span></code></pre>
127<p> <tt>member1</tt>... <tt>memberN</tt> are indirect links to the actual closure variables. Their indirect types correspond to <code><tt>type1</tt></code>... <code><tt>typeN</tt></code>. In our example, we declared <tt>calc_closure</tt>:</p>
128<pre><span class=number>    </span><span class=keyword>struct </span><span class=identifier>calc_closure </span><span class=special>: </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>spirit</span><span class=special>::</span><span class=identifier>closure</span><span class=special>&lt;</span><span class=identifier>calc_closure</span><span class=special>, </span><span class=keyword>double</span><span class=special>&gt;
129    </span><span class=special>{
130        </span><span class=identifier>member1 </span><span class=identifier>val</span><span class=special>;
131    </span><span class=special>};</span></pre>
132<p><tt>calc_closure</tt> has a single variable <tt>val</tt> of type <span class=keyword>double</span><span class=special></span>.</p>
133<table width="80%" border="0" align="center">
134  <tr>
135    <td class="note_box"><p><img src="theme/alert.gif" width="16" height="16"> <tt>BOOST_SPIRIT_CLOSURE_LIMIT</tt><br>
136        <br>
137      Spirit predefined maximum closure limit. This limit defines the maximum number of elements a closure can hold. This number defaults to 3. The actual maximum is rounded up in multiples of 3. Thus, if this value is 4, the actual limit is 6. The ultimate maximum limit in this implementation is 15. It should <strong>NOT</strong> be greater than <tt>PHOENIX_LIMIT</tt> (see <a href="../phoenix/index.html">phoenix</a>). Example:<br>
138      <br>
139      <span class="comment style1">// Define these before including anything else       <br>
140        </span><span class="preprocessor style1">#define</span><span class="style1"> PHOENIX_LIMIT 10<br>
141      </span><span class="preprocessor">#define</span><span class="style1"> BOOST_SPIRIT_CLOSURE_LIMIT 10</span></p>      </td>
142  </tr>
143</table>
144<p><strong>Attaching closures</strong></p>
145<p>Closures can be applied to rules, subrules and grammars (non-terminals). The closure has a
146  special <a href="indepth_the_parser_context.html">parser context</a> that can be used with these non-terminals. The closure's
147  context is its means to hook into the non-terminal. The  context of the closure <tt>C</tt> is <tt>C::context_t</tt>. </p>
148<p>We can see in the example that we attached <tt>calc_closure</tt> to the <tt>expression</tt>, <tt>term</tt> and <tt>factor</tt> rules in our grammar:</p>
149<pre><span class=special>    </span><span class=keyword>typedef </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>, </span><span class=identifier>calc_closure</span><span class=special>::</span><span class=identifier>context_t</span><span class=special>&gt; </span><span class=identifier>rule_t</span><span class=special>;
150    </span><span class=identifier>rule_t </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>;</span> </pre>
151<p>as well as the grammar itself:</p>
152<pre><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>&lt;</span><span class=identifier>calculator</span><span class=special>, </span><span class=identifier>calc_closure</span><span class=special>::</span><span class=identifier>context_t</span><span class=special>&gt;</span></pre>
153<p><strong>Closure return value</strong></p>
154<p>The closure <tt>member1</tt> is the closure's return value. This return value, like the one returned by <tt>anychar_p</tt>, for example, can be used to propagate data up the parser hierarchy or passed to semantic actions. Thus, <tt>expression</tt>, <tt>term</tt> and <tt>factor</tt>, as well as the <tt>calculator</tt> grammar itself, all return a <tt>double</tt>. </p>
155<p><strong>Accessing closure variables</strong></p>
156<p>Closure variables can be accessed from within semantic actions just like you
157  would struct members: by qualifying the member name with its owner rule, subrule
158  or grammar. In our example above, notice how we referred to the closure member val. Example:</p>
159<pre class="identifier"><code>    expression<span class=special>.</span>val <span class="comment">// refer to expression's closure member val</span></code></pre>
160<p><strong>Initializing closure variables </strong></p>
161<p>We didn't use this feature in the example, yet, for completeness... </p>
162<p>Sometimes, we need to initialize our closure variables upon entering a non-terminal (rule, subrule or grammar). Closure enabled non-terminals, by default, default-construct variables upon entering the parse member function.
163      If this is not desirable, we can pass constructor arguments  to the non-terminal. The syntax mimics a
164  function call. </p>
165<p>For (<em>a contrived</em>) example, if you wish to construct <tt>calc_closure</tt>'s variables
166    to <tt>3.6</tt>, when we invoke the rule <tt>expression</tt>, we write:</p>
167<pre class="identifier"><code>    expression<span class="special">(</span><span class="keyword">3.6</span><span class="special">) </span><span class="comment">// invoke rule expression and set its closure variable to 3.6</span></code></pre>
168<p>The constructor arguments are actually Phoenix lambda expressions, so you can
169  use arbitrarily complex expressions. Here's another <em>contrived example<strong>: </strong></em></p>
170<pre class="identifier"><code>    <span class="comment">// call rule factor and set its closure variable to (expression.x / 8) * factor.y
171</span>    <code>factor</code><span class="special">((</span>expression<span class="special">.</span>x<span class="keyword"> </span><span class="special">/</span><span class="keyword"> 8</span><span class="special">) *</span><span class="keyword"> </span>term<span class="special">.</span>y<span class="special">)</span></code></pre>
172<p><img src="theme/lens.gif" width="15" height="16"> We can pass less arguments than the actual number of variables in the closure.
173  The variables at the right with no corresponding constructor arguments are default
174  constructed. Passing more arguments than there are closure variables is an error.</p>
175<p><img src="theme/lens.gif" width="15" height="16"> See <a href="../example/intermediate/parameters.cpp">parameters.cpp</a> for a compilable example. This is part of the Spirit distribution.</p>
176<h2>Closures and Dynamic parsing</h2>
177<p>Let's write a very simple parser for an XML/HTML like language  with arbitrarily nested tags. The typical approach to this type of nested tag parsing is to delegate the actual tag matching to semantic actions, perhaps using a symbol table. For example, the semantic actions are responsible for ensuring that the tags are nested (e.g. this code: <tt>&lt;p&gt;&lt;table&gt;&lt;/p&gt;&lt;/table&gt;</tt> is erroneous).</p>
178<p>Spirit allows us to dynamically modify the parser at runtime. The ability to guide parser behavior through semantic actions makes it possible to ensure the nesting of tags directly in the parser. We shall see how this is possible. here's the grammar in its simplest form:</p>
179<pre><span class=identifier>    element </span><span class=special>= </span><span class=identifier>start_tag </span><span class=special>&gt;&gt; </span><span class=special>*</span><span class=identifier>element </span><span class=special>&gt;&gt; </span><span class=identifier>end_tag</span><span class=special>;</span>
180</pre>
181<p>An element is a <tt>start_tag</tt> (e.g. <tt>&lt;font&gt;</tt>) folowed by zero or more elements, and ended by an <tt>end_tag</tt> (e.g. <tt>&lt;/font&gt;</tt>). Now, here's a first shot at our <tt>start_tag</tt>:</p>
182<pre><span class=special>    </span><span class=identifier>start_tag </span><span class=special>= </span><span class=literal>'&lt;' </span><span class=special>&gt;&gt; </span><span class=identifier>lexeme_d</span><span class=special>[</span><span class=special>(+</span><span class=identifier>alpha_p</span><span class=special>)</span><span class=special>] </span><span class=special>&gt;&gt; </span><span class=literal>'&gt;'</span><span class=special>;</span></pre>
183<p>Notice that the <tt>end_tag</tt> is just the same as <tt>start_tag</tt> with the addition of a slash:</p>
184<pre><span class=special>    </span><span class=identifier>end_tag </span><span class=special>= </span><span class=literal>&quot;&lt;/&quot; </span><span class=special>&gt;&gt; </span>what_we_got_in_the_start_tag <span class=special></span><span class=special>&gt;&gt; </span><span class=literal>'&gt;'</span><span class=special>;</span>
185</pre>
186<p>What we need to do is to temporarily store what we got in our <tt>start_tag</tt> and use that later to parse our <tt>end_tag</tt>. Nifty, we can use the <a href="parametric_parsers.html">parametric parser</a> primitives to parse our <tt>end_tag</tt>: </p>
187<pre><span class=special>    </span><span class=identifier>end_tag </span><span class=special>= </span><span class=string>&quot;&lt;/&quot; </span><span class=special>&gt;&gt; </span><span class=identifier>f_str_p</span><span class=special>(</span>tag<span class=special>) </span><span class=special>&gt;&gt; </span><span class=literal>'&gt;'</span><span class=special>;</span></pre>
188<p>where we parameterize <tt>f_str_p</tt> with what we stored (tag). </p>
189<p>Be reminded though that our grammar is recursive. The element rule calls itself. Hence, we can't just use a variable and use <tt>phoenix::var</tt> or <tt>boost::ref</tt>. Nested recursion will simply gobble up the variable. Each invocation of element must have a closure variable <tt>tag</tt>. Here now is the complete grammar:</p>
190<pre><span class=number>    </span><span class=keyword>struct </span><span class=identifier>tags_closure </span><span class=special>: </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>spirit</span><span class=special>::</span><span class=identifier>closure</span><span class=special>&lt;</span><span class=identifier>tags_closure</span><span class=special>, </span><span class=identifier>string</span><span class=special>&gt; </span><span class=special>
191    {
192        </span><span class=identifier>member1 </span><span class=identifier>tag</span><span class=special>;
193    </span><span class=special>};
194
195    </span><span class=keyword>struct </span><span class=identifier>tags </span><span class=special>: </span><span class=keyword>public </span><span class=identifier>grammar</span><span class=special>&lt;</span><span class=identifier>tags</span><span class=special>&gt;
196    </span><span class=special>{
197        </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>ScannerT</span><span class=special>&gt;
198        </span><span class=keyword>struct </span><span class=identifier>definition </span><span class=special>{
199
200            </span><span class=identifier>definition</span><span class=special>(</span><span class=identifier>tags </span><span class=keyword>const</span><span class=special>&amp; </span><span class=comment>/*self*/</span><span class=special>)
201            </span><span class=special>{
202                </span><span class=identifier>element </span><span class=special>= </span><span class=identifier>start_tag </span><span class=special>&gt;&gt; </span><span class=special>*</span><span class=identifier>element </span><span class=special>&gt;&gt; </span><span class=identifier>end_tag</span><span class=special>;
203
204                </span><span class=identifier>start_tag </span><span class=special>=
205                        </span><span class=literal>'&lt;'
206                    </span><span class=special>&gt;&gt;  </span><span class=identifier>lexeme_d
207                        </span><span class=special>[
208                            </span><span class=special>(+</span><span class=identifier>alpha_p</span><span class=special>)
209                            </span><span class=special>[
210                                </span><span class=comment>//  construct string from arg1 and arg2 lazily
211                                </span><span class=comment>//  and assign to element.tag
212
213                                </span><span class=identifier>element</span><span class=special>.</span><span class=identifier>tag </span><span class=special>= </span><span class=identifier>construct_</span><span class=special>&lt;</span><span class=identifier>string</span><span class=special>&gt;(</span><span class=identifier>arg1</span><span class=special>, </span><span class=identifier>arg2</span><span class=special>)
214                            </span><span class=special>]
215                        </span><span class=special>]
216                    </span><span class=special>&gt;&gt; </span><span class=literal>'&gt;'</span><span class=special>;
217
218                </span><span class=identifier>end_tag </span><span class=special>= </span><span class=string>&quot;&lt;/&quot; </span><span class=special>&gt;&gt; </span><span class=identifier>f_str_p</span><span class=special>(</span><span class=identifier>element</span><span class=special>.</span><span class=identifier>tag</span><span class=special>) </span><span class=special>&gt;&gt; </span><span class=literal>'&gt;'</span><span class=special>;
219            </span><span class=special>}
220
221            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>, </span><span class=identifier>tags_closure</span><span class=special>::</span><span class=identifier>context_t</span><span class=special>&gt; </span><span class=identifier>element</span><span class=special>;
222            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>&gt; </span><span class=identifier>start_tag</span><span class=special>, </span><span class=identifier>end_tag</span><span class=special>;
223
224            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>, </span><span class=identifier>tags_closure</span><span class=special>::</span><span class=identifier>context_t</span><span class=special>&gt; </span><span class=keyword>const</span><span class=special>&amp;
225            </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>element</span><span class=special>; </span><span class=special>}
226        </span><span class=special>};
227    </span><span class=special>};</span></pre>
228<p>We attached a semantic action to the <tt>(+alpha_p)</tt> part of the start_tag. There, we stored the parsed tag in the <tt>element</tt>'s closure variable <tt>tag</tt>. Later, in the <tt>end_tag</tt>, we simply used the <tt>element</tt>'s closure variable <tt>tag</tt> to parameterize our <tt>f_str_p</tt> parser. Simple and elegant. If some of the details begin to look like greek (e.g. what is <tt>construct_</tt>?), please consult the <a href="phoenix.html">Phoenix</a> chapter. </p>
229<p><img height="16" width="15" src="theme/lens.gif"> The full source code can be <a href="../example/fundamental/matching_tags.cpp">viewed here</a>. This is part of the Spirit distribution.</p>
230<h2><img src="theme/lens.gif" width="15" height="16"> Closures in-depth</h2>
231<p><strong>What are Closures?</strong></p>
232<p>The closure is an object that <span class="quotes">&quot;closes&quot;</span>
233  over the local variables of a function making them visible and accessible outside
234  the function. What is more interesting is that the closure actually packages
235  a local context (stack frame where some variables reside) and makes it available
236  outside the scope in which they actually exist. The information is essentially
237  <span class="quotes">&quot;captured&quot;</span> by the closure allowing it
238  to be referred to anywhere and anytime, even prior to the actual creation of
239  the variables. </p>
240<p>The following diagram depicts the situation where a function <tt>A</tt> (or
241  rule) exposes its closure and another function <tt>B</tt> references <tt>A</tt>'s
242  variables through its closure.</p>
243<table width="40%" border="0" align="center">
244  <tr>
245    <td><img src="theme/closure1.png"></td>
246  </tr>
247  <tr>
248    <td> <div align="center"><b><font face="Geneva, Arial, Helvetica, san-serif" size="+1" color="#003399">The
249        closure as an object that <i>&quot;closes&quot;</i> over the local variables
250        of a function making them visible and accessible outside the function</font></b></div></td>
251  </tr>
252</table>
253<p>Of course, function <tt>A</tt> should be active when <tt>A.x</tt> is referenced.
254  What this means is that function <tt>B</tt> is reliant on function <tt>A</tt>
255  (If <tt>B</tt> is a nested function of <tt>A</tt>, this will always be the case).
256  The free form nature of Spirit rules allows access to a closure variable anytime,
257  anywhere. Accessing <tt>A.x</tt> is equivalent to referring to the topmost stack
258  variable <tt>x</tt> of function <tt>A</tt>. If function <tt>A</tt> is not active
259  when <tt>A.x</tt> is referenced, a runtime exception will be thrown.</p>
260<p><strong>Nested Functions</strong></p>
261<p>To fully understand the importance of closures, it is best to look at a language
262  such as Pascal which allows nested functions. Since we are dealing with C++,
263  lets us assume for the moment that C++ allows nested functions. Consider the
264  following <b><i>pseudo</i></b> C++ code:</p>
265<pre><span class=identifier>    </span><span class=keyword>void </span><span class=identifier>a</span><span class=special>()
266    </span><span class=special>{
267        </span><span class=keyword>int </span><span class=identifier>va</span><span class=special>;
268        </span><span class=keyword>void </span><span class=identifier>b</span><span class=special>()
269        </span><span class=special>{
270            </span><span class=keyword>int </span><span class=identifier>vb</span><span class=special>;
271</span>            <span class=keyword>void </span><span class=identifier>c</span><span class=special>()
272            </span><span class=special>{
273                </span><span class=keyword>int </span><span class=identifier>vc</span><span class=special>;
274            </span><span class=special>}
275
276            </span><span class=identifier>c</span><span class=special>()</span><span class=special>;
277        </span><span class=special>}
278
279        </span><span class=identifier>b</span><span class=special>();
280    </span><span class=special>}</span></pre>
281<p>We have three functions <tt>a</tt>, <tt>b</tt> and <tt>c</tt> where <tt>c</tt>
282  is nested in <tt>b</tt> and <tt>b</tt> is nested in <tt>a</tt>. We also have
283  three variables <tt>va</tt>, <tt>vb</tt> and <tt>vc</tt>. The lifetime of each
284  of these local variables starts when the function where it is declared is entered
285  and ends when the function exits. The scope of a local variable spans all nested
286  functions inside the enclosing function where the variable is declared.</p>
287<p>Going downstream from function <tt>a</tt> to function <tt>c</tt>, when function
288  a is entered, the variable <tt>va</tt> will be created in the stack. When function
289  <tt>b</tt> is entered (called by <tt>a</tt>), <tt>va</tt> is very well in scope
290  and is visble in <tt>b</tt>. At which point a fresh variable, <tt>vb</tt>, is
291  created on the stack. When function <tt>c</tt> is entered, both <tt>va</tt>
292  and <tt>vb</tt> are visibly in scope, and a fresh local variable <tt>vc</tt>
293  is created. </p>
294<p>Going upstream, <tt>vc</tt> is not and cannot be visible outside the function
295  <tt>c</tt>. <tt>vc</tt>'s life has already expired once <tt>c</tt> exits. The
296  same is true with <tt>vb</tt>; vb is accessible in function <tt>c</tt> but not
297  in function <tt>a</tt>. </p>
298<strong>Nested Mutually Recursive Rules</strong>
299<p>Now consider that <tt>a</tt>, <tt>b</tt> and <tt>c</tt> are rules:</p>
300<pre><span class=identifier>    </span><span class=identifier>a </span><span class=special>= </span><span class=identifier>b </span><span class=special>&gt;&gt; </span><span class=special>*((</span><span class=literal>'+' </span><span class=special>&gt;&gt; </span><span class=identifier>b</span><span class=special>) </span><span class=special>| </span><span class=special>(</span><span class=literal>'-' </span><span class=special>&gt;&gt; </span><span class=identifier>b</span><span class=special>));
301    </span><span class=identifier>b </span><span class=special>= </span><span class=identifier>c </span><span class=special>&gt;&gt; </span><span class=special>*((</span><span class=literal>'*' </span><span class=special>&gt;&gt; </span><span class=identifier>c</span><span class=special>) </span><span class=special>| </span><span class=special>(</span><span class=literal>'/' </span><span class=special>&gt;&gt; </span><span class=identifier>c</span><span class=special>));
302    </span><span class=identifier>c </span><span class=special>= </span><span class=identifier>int_p </span><span class=special>| </span><span class=literal>'(' </span><span class=special>&gt;&gt; </span><span class=identifier>a </span><span class=special>&gt;&gt; </span><span class=literal>')' </span><span class=special>| </span><span class=special>(</span><span class=literal>'-' </span><span class=special>&gt;&gt; </span><span class=identifier>c</span><span class=special>) </span><span class=special>| </span><span class=special>(</span><span class=literal>'+' </span><span class=special>&gt;&gt; </span><span class=identifier>c</span><span class=special>);</span></pre>
303<p>We can visualize <tt>a</tt>, <tt>b</tt> and <tt>c</tt> as mutually recursive
304  functions where <tt>a</tt> calls <tt>b</tt>, <tt>b</tt> calls <tt>c</tt> and
305  <tt>c</tt> recursively calls <tt>a</tt>. Now, imagine if <tt>a</tt>, <tt>b</tt>
306  and <tt>c</tt> each has a local variable named <tt>value</tt> that can be referred
307  to in our grammar by explicit qualification:</p>
308<pre><span class=special>    </span><span class=identifier>a</span><span class=special>.</span><span class=identifier>value </span><span class=comment>// refer to a's value local variable
309    </span><span class=identifier>b</span><span class=special>.</span><span class=identifier>value </span><span class=comment>// refer to b's value local variable
310    </span><span class=identifier>c</span><span class=special>.</span><span class=identifier>value </span><span class=comment>// refer to c's value local variable</span>
311</pre>
312<p>Like above, when <tt>a</tt> is entered, a local variable <tt>value</tt> is
313  created on the stack. This variable can be referred to by both <tt>b</tt> and
314  <tt>c</tt>. Again, when <tt>b</tt> is called by <tt>a</tt>, <tt>b</tt> creates
315  a local variable <tt>value</tt>. This variable is accessible by <tt>c</tt> but
316  not by <tt>a</tt>. </p>
317<p>Here now is where the analogy with nested functions end: when <tt>c</tt> is
318  called, a fresh variable <tt>value</tt> is created which, as usual, lasts the
319  whole lifetime of <tt>c</tt>. Pay close attention however that <tt>c</tt> may
320  call <tt>a</tt> recursively. When this happens, <tt>a</tt> may now refer to
321  the local variable of <tt>c</tt><code><span class=special>.</span></code></p>
322<table border="0">
323  <tr>
324    <td width="10"></td>
325    <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
326    <td width="30"><a href="phoenix.html"><img src="theme/l_arr.gif" border="0"></a></td>
327    <td width="30"><a href="dynamic_parsers.html"><img src="theme/r_arr.gif" border="0"></a></td>
328  </tr>
329</table>
330<br>
331<hr size="1">
332<p class="copyright">Copyright &copy; 1998-2003 Joel de Guzman<br>
333  <br>
334<font size="2">Use, modification and distribution is subject to the Boost Software
335    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
336    http://www.boost.org/LICENSE_1_0.txt) </font> </p>
337</body>
338</html>
Note: See TracBrowser for help on using the repository browser.