Sophie

Sophie

distrib > Mandriva > 9.1 > i586 > by-pkgid > b9ba69a436161613d8fb030c8c726a8e > files > 443

spirit-1.5.1-2mdk.noarch.rpm

<html>
<head>
<title>Semantic Actions</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="theme/style.css" type="text/css">
</head>

<body>
<table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2">
  <tr>
    <td width="10">
    </td>
    <td width="85%">
      <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Semantic Actions</b></font>
    </td>
    <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td>
  </tr>
</table>
<br>
<table border="0">
  <tr>
    <td width="10"></td>
    <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
    <td width="30"><a href="subrules.html"><img src="theme/l_arr.gif" border="0"></a></td>
    <td width="20"><a href="indepth_the_parser.html"><img src="theme/r_arr.gif" border="0"></a></td>
   </tr>
</table>
<p>Semantic actions have the form: <b>expression[action]</b></p>
<p>Ultimately, after having defined our grammar and having generated a corresponding
  parser, we'll need to produce some output and do some work besides syntax analysis.
  Unless of course what we want is merely to check for the conformance of an input
  with our grammar, which is very seldom the case.</p>
<p>What we need is a mechanism that will instruct the parser on what work should
  be done as it traverses the grammar while in the process of parsing an input
  stream. This mechanism is put in place through semantic actions.</p>
<p>Semantic actions may be attached to any expression at any level within the
  parser hierarchy. An action is a C/C++ function or function object that will
  be called if a match is found in the particular context where it is attached.
  The action function may be serve as a hook into the parser and may be used to,
  for example:</p>
<blockquote>
  <p><img src="theme/bullet.gif" width="13" height="13"> Generate output from 
    the parser (ASTs, for example)<br>
    <img src="theme/bullet.gif" width="13" height="13"> Report warnings or errors<br>
    <img src="theme/bullet.gif" width="13" height="13"> Manage symbol tables</p>
</blockquote>
<h2>Generic Semantic Actions</h2>
<p>A generic semantic action can be any free function or function object that
  is compatible with the interface:</p>
<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>
<p>where <tt>IteratorT</tt> is the type of iterator used, <tt>first</tt> points
  to the current input and <tt>last</tt> points to one after the end of the input
  (identical to STL iterator ranges). A functor should have a member <tt>operator()</tt>
  with the same signature as above:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>struct </span><span class=identifier>my_functor
    </span><span class=special>{
        </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>;
    </span><span class=special>};</span></font></code></pre>
<p>Iterators pointing to the matching portion of the input are passed into the
  function/functor.</p>
<h3>Example:</h3>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>void
    </span><span class=identifier>my_action</span><span class=special>(</span><span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>first</span><span class=special>, </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>last</span><span class=special>)
    </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>first</span><span class=special>, </span><span class=identifier>last</span><span class=special>);
        </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=identifier>string </span><span class=special>&lt;&lt; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;
    </span><span class=special>}

    </span><span class=identifier>rule</span><span class=special>&lt;&gt; </span><span class=identifier>myrule </span><span class=special>= </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=special>*(</span><span class=identifier>c </span><span class=special>&gt;&gt; </span><span class=identifier>d</span><span class=special>))[&</span><span class=identifier>my_action</span><span class=special>];</span></font></code></pre>
<p>The function <tt>my_action</tt> will be called whenever the expression <tt>(a
  | b | *(c &gt;&gt; d)</tt> matches a portion of the input stream while parsing.
  Two iterators <tt>first</tt> and <tt>last</tt>, are passed into the function.
  These iterators point to the start and end, respectively, of the portion of
  input stream where the match is found.</p>
<h3>Const-ness:</h3>
<p>With functors, take note that the <tt>operator()</tt> should be <tt>const</tt>.
  This implies that functors are immutable. One may wish to have some member variables
  that are modified when the action gets called. This is not a good idea. First
  of all, functors are preferably lighweight. Functors are passed around a lot
  and it would incur a lot of overhead if the functors are heavily laden. Second,
  functors are passed by value. Thus, the actual functor object that finally attaches
  to the parser, will surely not be the original instance supplied by the client.
  What this means is that changes to a functor's state will not affect the original
  functor that the client passed in since they are distinct copies. If a functor
  needs to update some state variables, which is often the case, it is better
  to use references to external data. The following example shows how this can
  be done:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>struct </span><span class=identifier>my_functor
    </span><span class=special>{
        </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>)
        </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>{}

        </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>{
            </span><span class=identifier>str</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=identifier>first</span><span class=special>, </span><span class=identifier>last</span><span class=special>);
        </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>;
    </span><span class=special>};</span></font></code></pre>
<h3>Full Example:</h3>
<p>Here now is our calculator enhanced with semantic actions:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>namespace
    </span><span class=special>{
        </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>)
        </span><span class=special>{
            </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>);
            </span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=string>"PUSH(" </span><span class=special>&lt;&lt; </span><span class=identifier>s </span><span class=special>&lt;&lt; </span><span class=literal>')' </span><span class=special>&lt;&lt; </span><span class=identifier>endl</span><span class=special>;
        </span><span class=special>}

        </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>&lt;&lt; </span><span class=string>"ADD\n"</span><span class=special>; </span><span class=special>}
        </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>&lt;&lt; </span><span class=string>"SUBTRACT\n"</span><span class=special>; </span><span class=special>}
        </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>&lt;&lt; </span><span class=string>"MULTIPLY\n"</span><span class=special>; </span><span class=special>}
        </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>&lt;&lt; </span><span class=string>"DIVIDE\n"</span><span class=special>; </span><span class=special>}
        </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>&lt;&lt; </span><span class=string>"NEGATE\n"</span><span class=special>; </span><span class=special>}
    </span><span class=special>}</span></font></code></pre>
<p>We augment our grammar with semantic actions:</p>
<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>&lt;</span><span class=identifier>calculator</span><span class=special>&gt;
    </span><span class=special>{
        </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;
        </span><span class=keyword>struct </span><span class=identifier>definition
        </span><span class=special>{
            </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>)
            </span><span class=special>{
                </span><span class=identifier>expression
                    </span><span class=special>=   </span><span class=identifier>term
                        </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>do_add</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>term</span><span class=special>)[&</span><span class=identifier>do_subt</span><span class=special>]
                            </span><span class=special>)
                    </span><span class=special>;

                </span><span class=identifier>term </span><span class=special>=
                    </span><span class=identifier>factor
                        </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>do_mult</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>factor</span><span class=special>)[&</span><span class=identifier>do_div</span><span class=special>]
                            </span><span class=special>)
                        </span><span class=special>;

                </span><span class=identifier>factor
                    </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>]]
                    </span><span class=special>|   </span><span class=literal>'(' </span><span class=special>&gt;&gt; </span><span class=identifier>expression </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>factor</span><span class=special>)[&</span><span class=identifier>do_neg</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>factor</span><span class=special>)
                    </span><span class=special>;
            </span><span class=special>}

            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>&gt; </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><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>&
            </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>}
        </span><span class=special>};
    </span><span class=special>};</span></font></code></pre>
<p>Feeding in the expression <tt>(-1 + 2) * (3 + -4)</tt>, for example, to the
  rule <tt>expression</tt> will produce the expected output:</p>
<pre><code><span class=special>-</span><span class=number>1
</span><span class=number>2
</span><span class=identifier>ADD
</span><span class=number>3
</span><span class=special>-</span><span class=number>4
</span><span class=identifier>ADD
</span><span class=identifier>MULT</span></code></pre>
<p>which, by the way, is the Reverse Polish Notation (RPN) of the given expression, 
  reminiscent of some primitive calculators and the language Forth.</p>
<p><img src="theme/lens.gif" width="15" height="16"> <a href="calc_plain.cpp.html">View 
  the complete source code here</a>. This is part of the Spirit distribution. 
  <br>
  [ See libs/spirit/example/fundamental/calc/calc_plain.cpp ]</p>
<h2><a name="specialized_actions"></a>Specialized Actions</h2>
<p>In general, semantic actions accept the first-last iterator pair. The action
  functions or functors receive the unprocessed data representing the matching
  production directly from the input. There are situations though where we might
  want to pass data in its processed form. A concrete example is the numeric parser.
  It is unwise to pass unprocessed data to a semantic action attached to a numeric
  parser and just throw away what has been done by the parser. Here, we want to
  pass the actual parsed number.</p>
<p>The function and functor signature of a semantic action varies depending on
  the parser where it is attached. The following table lists the parsers that
  accept unique signatures. Unless explicitly stated in the documentation of a
  specific parser type, parsers not included in the list by default expect the
  generic signature as explained above.</p>
<h3>Numeric Actions</h3>
<p><b>Applies to:</b></p>
<blockquote>
  <p><img src="theme/bullet.gif" width="13" height="13"> uint_p<br>
    <img src="theme/bullet.gif" width="13" height="13"> int_p<br>
    <img src="theme/bullet.gif" width="13" height="13"> ureal_p<br>
    <img src="theme/bullet.gif" width="13" height="13"> real_p</p>
</blockquote>
<p><b>Signature for functions:</b></p>
<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>
<p><br>
  <b>Signature for functors:</b><b><br>
  </b> </p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>struct </span><span class=identifier>ftor
    </span><span class=special>{
        </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>;
    </span><span class=special>};</span></font></code></pre>
<p>Where <tt>NumT</tt> is any primitive numeric type such as <tt>int</tt>, <tt>long</tt>,
  <tt>float</tt>, <tt>double</tt>, etc., or a user defined numeric type such as
  big_int. <tt>NumT</tt> is the same type used as template parameter to <tt>uint_p</tt>,
  <tt>int_p</tt>, <tt>ureal_p</tt> or <tt>real_p</tt>. The parsed number is passed
  into the function/functor.</p>
<h3>Character Actions</h3>
<p><b>Applies to:</b></p>
<blockquote>
  <p><img src="theme/bullet.gif" width="13" height="13"> chlit, ch_p<br>
    <img src="theme/bullet.gif" width="13" height="13"> range, range_p<br>
    <img src="theme/bullet.gif" width="13" height="13"> anychar<br>
    <img src="theme/bullet.gif" width="13" height="13"> alnum, alpha<br>
    <img src="theme/bullet.gif" width="13" height="13"> cntrl, digit<br>
    <img src="theme/bullet.gif" width="13" height="13"> graph, lower<br>
    <img src="theme/bullet.gif" width="13" height="13"> print, punct<br>
    <img src="theme/bullet.gif" width="13" height="13"> space, upper<br>
    <img src="theme/bullet.gif" width="13" height="13"> xdigit</p>
</blockquote>
<p><b>Signature for functions:</b></p>
<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>
<p><b>Signature for functors:</b><br>
</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>struct </span><span class=identifier>ftor
    </span><span class=special>{
        </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>;
    </span><span class=special>};</span></font></code></pre>
<p>Where <tt>CharT</tt> is the value_type of the iterator used in parsing. A <tt>char
  const*</tt> iterator for example has a <tt>value_type</tt> of <tt>char</tt>.
  The matching character is passed into the function/functor.</p>
<h2>Cascading Actions</h2>
<p>Actions can be cascaded. Cascaded actions also inherit the function/functor
  interface of the original. For example:</p>
<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>
<p>Here, the functors <tt>fa</tt>, <tt>fb</tt> and <tt>fc</tt> all expect the
  signature <tt>void operator()(unsigned n) const</tt>.</p>
<h2>Directives and Actions</h2>
<p>Directives inherit the the function/functor interface of the subject it is
  enclosing. Example:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=identifier>nocase_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>
<p>Here, the functor <tt>f</tt> expects the signature <tt>void operator()(char
  ch) const</tt>, assuming that the iterator used is a <tt>char const*</tt>.</p>
<h2>Templatized Functors</h2>
<p>For the sake of genericity, it is often better to make the functor's member
  <tt>operator()</tt> a template. That way, we do not have to concern ourselves
  with the type of the argument to expect as long as the behavior is appropriate.
  For instance, rather than hard-coding <tt>char const*</tt> as the argument of
  a generic semantic action, it is better to make it a template member function.
  That way, it can accept any type of iterator:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>struct </span><span class=identifier>my_functor
    </span><span class=special>{
        </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>IteratorT</span><span class=special>&gt;
        </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>;
    </span><span class=special>};</span></font></code></pre>
<p>Take note that this is only possible with functors, however. Which clearly
  shows that functors are superior to plain function.</p>
<h2>Predefined Actions</h2>
<p>The framework has two predefined semantic action functors. Experience shows
  that these functors are so often used that they were included as part of the
  core framework to spare the user from having to reinvent the same functionality
  over and over again.</p>
<h3>assign(v)</h3>
<p>Assign the value passed by the parser to the variable <tt>v</tt>.</p>
<p>Example usage:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>int </span><span class=identifier>i</span><span class=special>;
    </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>s</span><span class=special>;
    </span><span class=identifier>r </span><span class=special>= </span><span class=identifier>int_p</span><span class=special>[</span><span class=identifier>assign</span><span class=special>(</span><span class=identifier>i</span><span class=special>)] </span><span class=special>&gt;&gt; </span><span class=special>(+</span><span class=identifier>alpha_p</span><span class=special>)[</span><span class=identifier>assign</span><span class=special>(</span><span class=identifier>s</span><span class=special>)];</span></font></code></pre>
<p>Given an input <tt>123456 &quot;Hello&quot;</tt>, <tt>assign(i)</tt> will extract
  the number <tt>123456</tt> and assign it to <tt>i</tt>, then, <tt>assign(s)</tt>
  will extract the string <tt>&quot;Hello&quot;</tt> and assign it to <tt>s</tt>.
  Technically, the expression <tt>assign(v)</tt> is a template function that generates
  a semantic action. The semantic action generated is polymorphic and should work
  with any type as long as it is compatible with the arguments received from the
  parser. It might not be obvious, but a string can accept the iterator <tt>first</tt>
  and <tt>last</tt> arguments that are passed into a generic semantic action (see
  above). In fact, any STL container that has an <tt>assign(first, last)</tt>
  member function can be used.</p>
<p>For reference and to aid users in writing their own semantic action functors,
  here's the implementation of the <tt>assign(v)</tt> action. We include it here since
  it is short and simple enough to understand.</p>
<p><b>The assign_actor class</b></p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T</span><span class=special>&gt;
    </span><span class=keyword>class </span><span class=identifier>assign_actor
    </span><span class=special>{
    </span><span class=keyword>public</span><span class=special>:

        </span><span class=keyword>explicit
        </span><span class=identifier>assign_actor</span><span class=special>(</span><span class=identifier>T</span><span class=special>& </span><span class=identifier>ref_</span><span class=special>)
        </span><span class=special>: </span><span class=identifier>ref</span><span class=special>(</span><span class=identifier>ref_</span><span class=special>) </span><span class=special>{}

        </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T2</span><span class=special>&gt;
        </span><span class=keyword>void </span><span class=keyword>operator</span><span class=special>()(</span><span class=identifier>T2 </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>val</span><span class=special>) </span><span class=keyword>const
        </span><span class=special>{ </span><span class=identifier>ref </span><span class=special>= </span><span class=identifier>val</span><span class=special>; </span><span class=special>}

        </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>IteratorT</span><span class=special>&gt;
        </span><span class=keyword>void
        </span><span class=keyword>operator</span><span class=special>()(</span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>first</span><span class=special>, </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>last</span><span class=special>) </span><span class=keyword>const
        </span><span class=special>{ </span><span class=identifier>ref</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=identifier>first</span><span class=special>, </span><span class=identifier>last</span><span class=special>); </span><span class=special>}

    </span><span class=keyword>private</span><span class=special>:

        </span><span class=identifier>T</span><span class=special>& </span><span class=identifier>ref</span><span class=special>;
    </span><span class=special>};</span></font></code></pre>
<p><b>The assign function</b></p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T</span><span class=special>&gt;
    </span><span class=keyword>inline </span><span class=identifier>assign_actor</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt; </span><span class=keyword>const
    </span><span class=identifier>assign</span><span class=special>(</span><span class=identifier>T</span><span class=special>& </span><span class=identifier>t</span><span class=special>)
    </span><span class=special>{
        </span><span class=keyword>return </span><span class=identifier>assign_actor</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;(</span><span class=identifier>t</span><span class=special>);
    </span><span class=special>}</span></font></code></pre>
<h3>append(c)</h3>
<p>Append the value passed by the parser to the container <tt>c</tt>.</p>
<p>Example usage:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt; </span><span class=identifier>v</span><span class=special>;
    </span><span class=identifier>r </span><span class=special>= </span><span class=identifier>int_p</span><span class=special>[</span><span class=identifier>append</span><span class=special>(</span><span class=identifier>v</span><span class=special>)] </span><span class=special>&gt;&gt; </span><span class=special>*(</span><span class=literal>',' </span><span class=special>&gt;&gt; </span><span class=identifier>int_p</span><span class=special>[</span><span class=identifier>append</span><span class=special>(</span><span class=identifier>v</span><span class=special>)]);</span></font></code></pre>
<p>The code above can parse a comma separated list of integers and stuff the numbers 
  in the vector <tt>v</tt>. If it isn't obvious already, <tt>append(c)</tt> appends 
  the parsed value (the argument passed into the semantic action by the parser) 
  into the container <tt>c</tt>, which must have member functions <tt>insert(where, 
  value)</tt> and <tt>end()</tt>. To cut the story short, STL containers are perfect 
  candidates for <tt>append(c)</tt> to work on. Like <tt>assign(v)</tt>, <tt>append(c)</tt> 
  may also take in the iterator pairs. In which case, the container must have 
  two member functions: <tt>insert(where, first, last)</tt> and <tt>end()</tt>; 
  e.g. <tt>std::vector&lt;std::string&gt;</tt>.</p>
<table border="0">
  <tr>
    <td width="10"></td>
    <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
    <td width="30"><a href="subrules.html"><img src="theme/l_arr.gif" border="0"></a></td>
    <td width="20"><a href="indepth_the_parser.html"><img src="theme/r_arr.gif" border="0"></a></td>
  </tr>
</table>
<br>
<hr size="1">
<p class="copyright">Copyright &copy; 1998-2002 Joel de Guzman<br>
  <br>
  <font size="2">Permission to copy, use, modify, sell and distribute this document 
  is granted provided this copyright notice appears in all copies. This document 
  is provided &quot;as is&quot; without express or implied warranty, and with 
  no claim as to its suitability for any purpose.</font></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>
</html>