123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>Trees</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">
- <tbody><tr>
- <td width="10">
- <br>
- </td>
- <td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Trees</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>
- </tbody></table>
- <br>
- <table border="0">
- <tbody><tr>
- <td width="10"><br>
- </td>
- <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
- <td width="30"><a href="symbols.html"><img src="theme/l_arr.gif" border="0"></a></td>
- <td width="30"><a href="multi_pass.html"><img src="theme/r_arr.gif" border="0"></a></td>
- </tr>
- </tbody></table>
- <h2>Why use parse trees</h2>
- <p> Parse trees are an in-memory representation of the input with a structure
- that conforms to the grammar.</p>
- <p> The advantages of using parse trees instead of semantic actions:</p>
- <ul>
- <li>You can make multiple passes over the data without having to re-parse the
- input.</li>
- <li>You can perform transformations on the tree.</li>
- <li>You can evaluate things in any order you want, whereas with attribute schemes
- you have to process in a begin to end fashion.</li>
- <li>You do not have to worry about backtracking and action side effects that
- may occur with an ambiguous grammar.</li>
- </ul>
- <p> <b>Example</b></p>
- <p> Now that you think you may want to use trees, I'll give an example of how
- to use them and you can see how easy they are to use. So, following with tradition
- (and the rest of the documentation) we'll do a calculator. Here's the grammar:</p>
- <pre> <code><span class="identifier">integer </span><span class="special">
- = </span><span class="identifier"><font color="#ff0000"><b>token_node_d</b></font></span><span class="special">[ (!</span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'-'</span><span class="special">) >> +</span><span class="identifier">digit_p</span><span class="special">) ]<br> ;<br><br> </span><span class="identifier">factor<br> </span><span class="special">= </span><span class="identifier">integer<br> </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">')'<br> </span><span class="special">| (</span><span class="literal">'-' </span><span class="special">>> </span><span class="identifier">factor</span><span class="special">)<br> ;<br><br> </span><span class="identifier">term<br> </span><span class="special">= </span><span class="identifier">factor </span><span class="special">
- >> *( (</span><span class="literal">'*' </span><span class="special">>> </span><span class="identifier">factor</span><span class="special">)<br> | (</span><span class="literal">'/' </span><span class="special">>> </span><span class="identifier">factor</span><span class="special">)<br> )<br> ;<br><br> </span><span class="identifier">expression<br> </span><span class="special">= </span><span class="identifier">term<br> </span><span class="special">>> *( (</span><span class="literal">'+' </span><span class="special">>> </span><span class="identifier">term</span><span class="special">)<br> | (</span><span class="literal">'-' </span><span class="special">>> </span><span class="identifier">term</span><span class="special">)<br> )<br> ;</span></code></pre>
- <p> Now, you'll notice the only thing different in this grammar is the <tt>token_node_d</tt>
- directive. This causes the match of the integer rule to end up in one node.
- Without <tt>token_node_d</tt>, each character would get it's own node.
- Further note that <tt>token_node_d</tt> is an implicit lexeme (that means
- no <tt>lexeme_d</tt> is needed to switch to character level parsing).
- As you'll soon see, it's easier to convert the input into an int when all
- the characters are in one node. Here is how the parse is done to create a tree:</p>
- <pre> <code><span class="identifier">tree_parse_info</span><span class="special"><> </span><span class="identifier">info </span><span class="special">= </span><span class="identifier"><font color="#ff0000"><b>pt_parse</b></font></span><span class="special">(</span><span class="identifier">first</span><span class="special">, </span><span class="identifier">expression</span><span class="special">);</span></code></pre>
- <p> <tt>pt_parse()</tt> is similar to <tt>parse()</tt>. There are four overloads:
- two for pairs of first and last iterators and two for character strings. Two
- of the functions take a skipper parser and the other two do not.</p>
- <p> The <tt>tree_parse_info</tt> struct contains the same information as a <tt>parse_info</tt>
- struct as well as one extra data member called trees. When the parse finishes,
- trees will contain the parse tree.</p>
- <p> Here is how you can use the tree to evaluate the input:</p>
- <pre> <code><span class="keyword">if </span><span class="special">(</span><span class="identifier">info</span><span class="special">.</span><span class="identifier">full</span><span class="special">)<br> {<br> </span><span class="identifier">cout </span><span class="special"><< </span><span class="string">"parsing succeeded\n"</span><span class="special">;<br> </span><span class="identifier">cout </span><span class="special"><< </span><span class="string">"result = " </span><span class="special"><< </span><span class="identifier"><font color="#ff0000"><b>evaluate</b></font></span><span class="special">(</span><span class="identifier">info</span><span class="special">) << </span><span class="string">"\n\n"</span><span class="special">;<br> }</span></code></pre>
- <p> Now you ask, where did <tt>evaluate()</tt> come from? Is it part of spirit?
- Unfortunately, no, <tt>evaluate()</tt> is only a part of the sample. Here it
- is:</p>
- <pre> <code><span class="keyword">long </span><span class="identifier">evaluate</span><span class="special">(</span><span class="keyword">const </span><span class="identifier">tree_parse_info</span><span class="special"><>& </span><span class="identifier">info</span><span class="special">)<br> </span><span class="special">{<br> </span><span class="keyword">return </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">info</span><span class="special">.</span><span class="identifier">trees</span><span class="special">.</span><span class="identifier">begin</span><span class="special">());<br> </span><span class="special">}</span></code></pre>
- <p> So here you see evaluate() simply calls <tt>eval_expression()</tt> passing
- the begin() iterator of info.trees. Now here's the rest of the example:</p>
- <pre> <code><span class="comment">// Here's some typedefs to simplify things<br> </span><span class="keyword">typedef char const</span><span class="special">* </span><span class="identifier">iterator_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">tree_match</span><span class="special"><</span><span class="identifier">iterator_t</span><span class="special">> </span><span class="identifier"> parse_tree_match_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">parse_tree_match_t</span><span class="special">::</span><span class="identifier">const_tree_iterator iter_t</span><span class="special">;<br><br> </span><span class="comment">// Here's the function prototypes that we'll use. One function for each<br> // grammar rule</span><span class="special">.<br> </span><span class="keyword">long </span><span class="identifier">evaluate</span><span class="special">(</span><span class="keyword">const </span><span class="identifier">tree_parse_info</span><span class="special"><>& </span><span class="identifier">info</span><span class="special">);<br> </span><span class="keyword">long </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">iter_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">i</span><span class="special">);<br> </span><span class="keyword">long </span><span class="identifier">eval_term</span><span class="special">(</span><span class="identifier">iter_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">i</span><span class="special">);<br> </span><span class="keyword">long </span><span class="identifier">eval_factor</span><span class="special">(</span><span class="identifier">iter_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">i</span><span class="special">);<br> </span><span class="keyword">long </span><span class="identifier">eval_integer</span><span class="special">(</span><span class="identifier">iter_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">i</span><span class="special">);<br><br> </span><span class="comment">// i should be pointing to a node created by the expression rule<br> </span><span class="keyword">long </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">iter_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">i</span><span class="special">)<br> {<br> </span><span class="comment">// first child points to a term, so call eval_term on it<br> </span><span class="identifier">iter_t chi </span><span class="special">= </span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">();<br> </span><span class="keyword">long </span><span class="identifier">lhs </span><span class="special">= </span><span class="identifier">eval_term</span><span class="special">(</span><span class="identifier">chi</span><span class="special">);<br> </span><span class="keyword">for </span><span class="special">(++</span><span class="identifier">chi</span><span class="special">; </span><span class="identifier">chi </span><span class="special">!= </span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">end</span><span class="special">(); ++</span><span class="identifier">chi</span><span class="special">)<br> {<br> </span><span class="comment">// next node points to the operator. The text of the operator is<br> // stored in value (a vector<char>)<br> </span><span class="keyword">char </span><span class="identifier">op </span><span class="special">= *(</span><span class="identifier">chi</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">begin</span><span class="special">());<br> ++</span><span class="identifier">chi</span><span class="special">;<br> </span><span class="keyword">long </span><span class="identifier">rhs </span><span class="special">= </span><span class="identifier">eval_term</span><span class="special">(</span><span class="identifier">chi</span><span class="special">);<br> </span><span class="keyword">if </span><span class="special">(</span><span class="identifier">op </span><span class="special">== </span><span class="literal">'+'</span><span class="special">)<br> </span><span class="identifier">lhs </span><span class="special">+= </span><span class="identifier">rhs</span><span class="special">;<br> </span><span class="keyword">else if </span><span class="special">(</span><span class="identifier">op </span><span class="special">== </span><span class="literal">'-'</span><span class="special">)<br> </span><span class="identifier">lhs </span><span class="special">-= </span><span class="identifier">rhs</span><span class="special">;<br> </span><span class="keyword">else<br> </span><span class="identifier">assert</span><span class="special">(</span><span class="number">0</span><span class="special">);<br> }<br> </span><span class="keyword">return </span><span class="identifier">lhs</span><span class="special">;<br> }<br><br> </span><span class="keyword">long </span><span class="identifier">eval_term</span><span class="special">(</span><span class="identifier">iter_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">i</span><span class="special">)<br> {<br> </span><span class="comment">// ... see <a href="../example/fundamental/parse_tree_calc1.cpp">parse_tree_calc1.cpp</a> for complete example<br> // (it's rather similar to eval_expression() ) ...<br> </span><span class="special">}<br><br> </span><span class="keyword">long </span><span class="identifier">eval_factor</span><span class="special">(</span><span class="identifier">iter_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">i</span><span class="special">)<br> {<br> </span><span class="comment">// ... again, see <a href="../example/fundamental/parse_tree_calc1.cpp">parse_tree_calc1.cpp</a> if you want all the details ...<br> </span><span class="special">}<br><br> </span><span class="keyword">long </span><span class="identifier">eval_integer</span><span class="special">(</span><span class="identifier">iter_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">i</span><span class="special">)<br> </span><span class="special">{<br> </span><span class="comment">// use the range constructor for a string<br> </span><span class="identifier">string </span><span class="identifier">integer</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(), </span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">end</span><span class="special">());<br> </span><span class="comment">// convert the string to an integer<br> </span><span class="keyword">return </span><span class="identifier">strtol</span><span class="special">(</span><span class="identifier">integer</span><span class="special">.</span><span class="identifier">c_str</span><span class="special">(), </span><span class="number">0</span><span class="special">, </span><span class="number">10</span><span class="special">);<br> </span><span class="special">}<br></span></code></pre>
- <p> <img height="16" width="15" src="theme/lens.gif"> The full source code can be <a href="../example/fundamental/parse_tree_calc1.cpp">viewed here</a>. This is part of the Spirit distribution.</p>
- <p>So, you like what you see, but maybe you think that the parse tree is too
- hard to process? With a few more directives you can generate an abstract syntax
- tree (ast) and cut the amount of evaluation code by at least <b>50%</b>. So
- without any delay, here's the ast calculator grammar:</p>
- <pre> <code><span class="identifier">integer<br> </span><span class="special">= </span><span class="identifier"><font color="#ff0000"><b>leaf_node_d</b></font></span><span class="special">[ </span><span class="special">(!</span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'-'</span><span class="special">) >> +</span><span class="identifier">digit_p</span><span class="special">) ]<br> ;<br><br> </span><span class="identifier">factor<br> </span><span class="special">= </span><span class="identifier">integer<br> </span><span class="special">| </span><span class="identifier"><font color="#ff0000"><b>inner_node_d</b></font></span><span class="special">[</span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'('</span><span class="special">) >> </span><span class="identifier">expression </span><span class="special">>> </span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">')'</span><span class="special">)]<br> | (</span><span class="identifier"><font color="#ff0000"><b>root_node_d</b></font></span><span class="special">[</span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'-'</span><span class="special">)] >> </span><span class="identifier">factor</span><span class="special">)<br> ;<br><br> </span><span class="identifier">term<br> </span><span class="special">= </span><span class="identifier">factor </span><span class="special">
- >> *( (</span><span class="identifier"><font color="#ff0000"><b>root_node_d</b></font></span><span class="special">[</span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'*'</span><span class="special">)] >> </span><span class="identifier">factor</span><span class="special">)<br> | (</span><span class="identifier"><font color="#ff0000"><b>root_node_d</b></font></span><span class="special">[</span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'/'</span><span class="special">)] >> </span><span class="identifier">factor</span><span class="special">)<br> )<br> ;<br><br> </span><span class="identifier">expression<br> </span><span class="special">= </span><span class="identifier">term<br> </span><span class="special">>> *( (</span><span class="identifier"><font color="#ff0000"><b>root_node_d</b></font></span><span class="special">[</span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'+'</span><span class="special">)] >> </span><span class="identifier">term</span><span class="special">)<br> | (</span><span class="identifier"><font color="#ff0000"><b>root_node_d</b></font></span><span class="special">[</span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'-'</span><span class="special">)] >> </span><span class="identifier">term</span><span class="special">)<br> )<br> ;</span></code></pre>
- <p> The differences from the parse tree grammar are hi-lighted in <b><font color="#ff0000">bold-red</font></b>.
- The <tt>inner_node_d</tt> directive causes the first and last nodes generated
- by the enclosed parser to be discarded, since we don't really care about the
- parentheses when evaluating the expression. The <tt>root_node_d</tt> directive
- is the key to ast generation. A node that is generated by the parser inside
- of <tt>root_node_d</tt> is marked as a root node. When a root node is created,
- it becomes a root or parent node of the other nodes generated by the same rule.</p>
- <p> To start the parse and generate the ast, you must use the ast_parse functions,
- which are similar to the pt_parse functions.</p>
- <pre> <code><span class="identifier">tree_parse_info</span><span class="special"><> </span><span class="identifier">info </span><span class="special">= </span><span class="identifier">ast_parse</span><span class="special">(</span><span class="identifier">first</span><span class="special">, </span><span class="identifier">expression</span><span class="special">);</span></code></pre>
- <p> Here is the eval_expression function (note that to process the ast we only
- need one function instead of four):</p>
- <pre> <code><span class="keyword">long </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">iter_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">i</span><span class="special">)<br> </span><span class="special">{<br> </span><span class="keyword">if </span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">id</span><span class="special">() </span><span class="special">== </span><span class="identifier">parser_id</span><span class="special">(&</span><span class="identifier">integer</span><span class="special">))<br> </span><span class="special">{<br> </span><span class="comment">// convert string to integer<br> </span><span class="identifier">string </span><span class="identifier">integer</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(), </span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">end</span><span class="special">());<br> </span><span class="keyword">return </span><span class="identifier">strtol</span><span class="special">(</span><span class="identifier">integer</span><span class="special">.</span><span class="identifier">c_str</span><span class="special">(), </span><span class="number">0</span><span class="special">, </span><span class="number">10</span><span class="special">);<br> </span><span class="special">}<br> </span><span class="keyword">else </span><span class="keyword">if </span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">id</span><span class="special">() </span><span class="special">== </span><span class="identifier">parser_id</span><span class="special">(&</span><span class="identifier">factor</span><span class="special">))<br> </span><span class="special">{<br> </span><span class="comment">// factor can only be unary minus<br> </span><span class="keyword">return </span><span class="special">- </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">());<br> </span><span class="special">}<br> </span><span class="keyword">else </span><span class="keyword">if </span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">id</span><span class="special">() </span><span class="special">== </span><span class="identifier">parser_id</span><span class="special">(&</span><span class="identifier">term</span><span class="special">))<br> </span><span class="special">{<br> </span><span class="keyword">if </span><span class="special">(*</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">begin</span><span class="special">() </span><span class="special">== </span><span class="literal">'*'</span><span class="special">)<br> </span><span class="special">{<br> </span><span class="keyword">return </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()) </span><span class="special">*<br> </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()+</span><span class="number">1</span><span class="special">);<br> </span><span class="special">}<br> </span><span class="keyword">else </span><span class="keyword">if </span><span class="special">(*</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">begin</span><span class="special">() </span><span class="special">== </span><span class="literal">'/'</span><span class="special">)<br> </span><span class="special">{<br> </span><span class="keyword">return </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()) </span><span class="special">/<br> </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()+</span><span class="number">1</span><span class="special">);<br> </span><span class="special">}<br> </span><span class="special">}<br> </span><span class="keyword">else </span><span class="keyword">if </span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">id</span><span class="special">() </span><span class="special">== </span><span class="identifier">parser_id</span><span class="special">(&</span><span class="identifier">expression</span><span class="special">))<br> </span><span class="special">{<br> </span><span class="keyword">if </span><span class="special">(*</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">begin</span><span class="special">() </span><span class="special">== </span><span class="literal">'+'</span><span class="special">)<br> </span><span class="special">{<br> </span><span class="keyword">return </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()) </span><span class="special">+<br> </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()+</span><span class="number">1</span><span class="special">);<br> </span><span class="special">}<br> </span><span class="keyword">else </span><span class="keyword">if </span><span class="special">(*</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">value</span><span class="special">.</span><span class="identifier">begin</span><span class="special">() </span><span class="special">== </span><span class="literal">'-'</span><span class="special">)<br> </span><span class="special">{<br> </span><span class="keyword">return </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()) </span><span class="special">-<br> </span><span class="identifier">eval_expression</span><span class="special">(</span><span class="identifier">i</span><span class="special">-></span><span class="identifier">children</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()+</span><span class="number">1</span><span class="special">);<br> </span><span class="special">}<br> </span><span class="special">}<br><br> </span><span class="keyword">return </span><span class="number">0</span><span class="special">;<br> </span><span class="special">}<br></span></code></pre>
- <p> <img src="theme/lens.gif" width="15" height="16"> An entire working example is <a href="../example/fundamental/ast_calc.cpp">ast_calc.cpp</a>. Hopefully this example has been enough to whet your appetite for
- trees. For more nitty-gritty details, keep on reading the rest of this chapter.</p>
- <a name="usage"></a>
- <h2>Usage</h2>
- <a name="pt_parse"></a>
- <h3>pt_parse</h3>
- <p> To create a parse tree, you can call one of the five free functions:</p>
- <pre> <span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>FactoryT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>IteratorT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>SkipT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>IteratorT</span><span class=special>, </span><span class=identifier>FactoryT</span><span class=special>> <br> </span><span class=identifier>pt_parse</span><span class=special>( <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>first_</span><span class=special>, <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>last_</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>, <br> </span><span class=identifier>SkipT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>skip_</span><span class=special>,
- </span><span class="identifier">FactoryT</span><span class=special> </span><span class="keyword">const</span><span class=special> & </span><span class="identifier">factory_</span><span class=special> = </span><span class="identifier">FactoryT</span><span class=special>()); <br> </span><span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>IteratorT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>SkipT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>IteratorT</span><span class=special>> <br> </span><span class=identifier>pt_parse</span><span class=special>( <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>first_</span><span class=special>, <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>last_</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>, <br> </span><span class=identifier>SkipT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>skip_</span><span class=special>); <br> </span><span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>IteratorT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>IteratorT</span><span class=special>> <br> </span><span class=identifier>pt_parse</span><span class=special>( <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>first_</span><span class=special>, <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>last_</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>); <br> </span><span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>CharT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>SkipT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>CharT </span><span class=keyword>const</span><span class=special>*> <br> </span><span class=identifier>pt_parse</span><span class=special>( <br> </span><span class=identifier>CharT </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>str</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>, <br> </span><span class=identifier>SkipT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>skip</span><span class=special>); <br> </span><span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>CharT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>CharT </span><span class=keyword>const</span><span class=special>*> <br> </span><span class=identifier>pt_parse</span><span class=special>( <br> </span><span class=identifier>CharT </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>str</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>);<br></span></pre>
- <a name="ast_parse"></a>
- <h3>ast_parse</h3>
- <p> To create an abstract syntax tree (ast for short) you call one of the five
- free functions:</p>
- <pre> <span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>FactoryT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>IteratorT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>SkipT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>IteratorT</span><span class=special>, </span><span class=identifier>FactoryT</span><span class=special>> <br> </span><span class=identifier>ast_parse</span><span class=special>( <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>first_</span><span class=special>, <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>last_</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>, <br> </span><span class=identifier>SkipT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>skip_</span><span class=special>,
- </span><span class="identifier"> FactoryT</span><span class=special> </span><span class="keyword">const</span><span class=special> & </span><span class="identifier">factory_</span><span class=special> = </span><span class="identifier">FactoryT</span><span class=special>()</span><span class=special>); <br> </span><span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>IteratorT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>SkipT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>IteratorT</span><span class=special>> <br> </span><span class=identifier>ast_parse</span><span class=special>( <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>first_</span><span class=special>, <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>last_</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>, <br> </span><span class=identifier>SkipT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>skip_</span><span class=special>); <br> </span><span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>IteratorT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>IteratorT</span><span class=special>> <br> </span><span class=identifier>ast_parse</span><span class=special>( <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>first_</span><span class=special>, <br> </span><span class=identifier>IteratorT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>last</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>); <br> </span><span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>CharT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>SkipT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>CharT </span><span class=keyword>const</span><span class=special>*> <br> </span><span class=identifier>ast_parse</span><span class=special>( <br> </span><span class=identifier>CharT </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>str</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>, <br> </span><span class=identifier>SkipT </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>skip</span><span class=special>); <br> </span><span class=keyword>template </span><span class=special><</span><span class=keyword>typename </span><span class=identifier>CharT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>ParserT</span><span class=special>> <br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>CharT </span><span class=keyword>const</span><span class=special>*> <br> </span><span class=identifier>ast_parse</span><span class=special>( <br> </span><span class=identifier>CharT </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>str</span><span class=special>, <br> </span><span class=identifier>parser</span><span class=special><</span><span class=identifier>ParserT</span><span class=special>> </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>parser</span><span class=special>);<br></span></pre>
- <a name="tree_parse_info"></a>
- <h3>tree_parse_info</h3>
- <p> The <tt>tree_parse_info</tt> struct returned from pt_parse and ast_parse contains
- information about the parse:</p>
- <pre> <code><span class="keyword">template </span><span class="special"><</span><span class="keyword">typename </span><span class="identifier">IteratorT </span><span class="special">= </span><span class="keyword">char </span><span class="keyword">const</span><span class="special">*><br> </span><span class="keyword">struct </span><span class="identifier">tree_parse_info<br> </span><span class="special">{<br> </span><span class="identifier">IteratorT </span><span class="identifier">stop</span><span class="special">;<br> </span><span class="keyword">bool </span><span class="identifier">match</span><span class="special">;<br> </span><span class="keyword">bool </span><span class="identifier">full</span><span class="special">;<br> </span><span class="keyword">std::size_t </span><span class="identifier">length</span><span class="special">;<br><br> </span><span class="keyword">typename </span><span class="identifier">tree_match</span><span class="special"><</span><span class="identifier">IteratorT</span><span class="special">>::</span><span class="identifier">container_t </span><span class="identifier">trees</span><span class="special">;<br> </span><span class="special">};<br></span></code></pre>
- <table width="90%" border="0" align="center">
- <tbody><tr>
- <td class="table_title" colspan="10"> tree_parse_info </td>
- </tr>
- <tr>
- </tr><tr>
- <td class="table_cells"><b>stop</b></td>
- <td class="table_cells">points to the final parse position (i.e. parsing processed
- the input up to this point).</td>
- </tr>
- <tr><td class="table_cells"><b>match</b></td>
- <td class="table_cells">true if parsing is successful. This may be full (the
- parser consumed all the input), or partial (the parser consumed only a portion
- of the input.)</td>
- </tr>
- <tr><td class="table_cells"><b>full</b></td>
- <td class="table_cells">true when we have a full match (when the parser consumed
- all the input).</td>
- </tr>
- <tr><td class="table_cells"><b>length</b></td>
- <td class="table_cells">The number of characters consumed by the parser. This
- is valid only if we have a successful match (either partial or full).</td>
- </tr>
- <tr><td class="table_cells"><b>trees</b></td>
- <td class="table_cells">Contains the root node(s) of the tree.</td>
- </tr>
- </tbody></table>
- <a name="tree_match"></a>
- <h3>tree_match</h3>
- <p> When Spirit is generating a tree, the parser's parse() member function will
- return a tree_match object, instead of a match object. tree_match has three
- template parameters. The first is the Iterator type which defaults to <tt>char
- const*</tt>. The second is the node factory, which defaults to <a href="#node_val_data_factory">node_val_data_factory</a>.
- The third is the attribute type stored in the match. A tree_match has a member
- variable which is a container (a <tt>std::vector</tt>) of <a href="#tree_node">tree_node</a>
- objects named trees. For efficiency reasons, when a tree_match is copied, the
- trees are <b>not</b> copied, they are moved to the new object, and the source
- object is left with an empty tree container. tree_match supports the same interface
- as the match class: it has an operator bool() so you can test it for a sucessful
- match: if (matched), and you can query the match length via the length() function.
- The class has this interface:</p>
- <pre> <code><span class="keyword">template </span><span class="special"><</span><span class="keyword">typename </span><span class="identifier">IteratorT </span><span class="special">= </span><span class="keyword">char </span><span class="keyword">const</span><span class="special">*, </span><span class="keyword">typename </span><span class="identifier">NodeFactoryT </span><span class="special">= </span><span class="identifier">node_val_data_factory</span><span class="special"><> </span><span class="special">><br> </span><span class="keyword">struct </span><span class="identifier">tree_match<br> </span><span class="special">{<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">NodeFactoryT</span><span class="special">::</span><span class="keyword">template </span><span class="identifier">factory</span><span class="special"><</span><span class="identifier">IteratorT</span><span class="special">> </span><span class="identifier">node_factory_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">node_factory_t</span><span class="special">::</span><span class="identifier">node_t </span><span class="identifier">parse_node_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">tree_node</span><span class="special"><</span><span class="identifier">parse_node_t</span><span class="special">> </span><span class="identifier">node_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">node_t</span><span class="special">::</span><span class="identifier">children_t </span><span class="identifier">container_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">container_t</span><span class="special">::</span><span class="identifier">iterator </span><span class="identifier">tree_iterator</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">container_t</span><span class="special">::</span><span class="identifier">const_iterator </span><span class="identifier">const_tree_iterator</span><span class="special">;<br><br> </span><span class="identifier">tree_match</span><span class="special">();<br> </span><span class="identifier">tree_match</span><span class="special">(</span><span class="keyword">std::size_t </span><span class="identifier">length</span><span class="special">, </span><span class="identifier">parse_node_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">n</span><span class="special">);<br> </span><span class="identifier">tree_match</span><span class="special">(</span><span class="identifier">tree_match </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">x</span><span class="special">);<br> </span><span class="keyword">explicit </span><span class="identifier">tree_match</span><span class="special">(</span><span class="identifier">match </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">x</span><span class="special">);<br> </span><span class="identifier">tree_match</span><span class="special">& </span><span class="keyword">operator</span><span class="special">=(</span><span class="identifier">tree_match </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">x</span><span class="special">);<br> </span><span class="keyword">void </span><span class="identifier">swap</span><span class="special">(</span><span class="identifier">tree_match</span><span class="special">& </span><span class="identifier">x</span><span class="special">);<br> </span><span class="keyword">operator </span><span class="keyword">bool</span><span class="special">() </span><span class="keyword">const</span><span class="special">;<br> </span><span class="keyword">int </span><span class="identifier">length</span><span class="special">() </span><span class="keyword">const</span><span class="special">;<br><br> </span><span class="identifier">container_t </span><span class="identifier">trees</span><span class="special">;<br> </span><span class="special">};</span></code></pre>
- <p> When a parse has sucessfully completed, the trees data member will contain
- the root node of the tree. </p>
- <table width="80%" border="0" align="center">
- <tbody><tr>
- <td class="note_box"><img src="theme/lens.gif" width="15" height="16"> <b>vector?</b><br>
- <br>
- You may wonder, why is it a vector then? The answer is that it is partly
- for implementation purposes, and also if you do not use any rules in your
- grammar, then trees will contain a sequence of nodes that will not have
- any children.</td>
- </tr>
- </tbody></table>
- <p> Having spirit create a tree is similar to how a normal parse is done:</p>
- <pre> <code><span class="identifier">tree_match</span><span class="special"><> </span><span class="identifier">hit </span><span class="special">= </span><span class="identifier">expression</span><span class="special">.</span><span class="identifier">parse</span><span class="special">(</span><span class="identifier">tree_scanner</span><span class="special">);<br><br> </span><span class="keyword">if </span><span class="special">(</span><span class="identifier">hit</span><span class="special">)<br> </span><span class="identifier">process_tree_root</span><span class="special">(</span><span class="identifier">hit</span><span class="special">.</span><span class="identifier">trees</span><span class="special">[</span><span class="number">0</span><span class="special">]); </span><span class="comment">// do something with the tree</span></code></pre>
- <a name="tree_node"></a>
- <h3>tree_node</h3>
- <p> Once you have created a tree by calling <a href="#pt_parse">pt_parse</a>
- or <a href="#ast_parse">ast_parse</a>, you have a <a href="#tree_parse_info">tree_parse_info</a>
- which contains the root node of the tree, and now you need to do something with
- the tree. The data member trees of <a href="#tree_parse_info">tree_parse_info</a>
- is a std::vector<tree_node>. tree_node provides the tree structure. The
- class has one template parameter named T. tree_node contains an instance of
- type T. It also contains a std::vector<tree_node<T> > which are
- the node's children. The class looks like this:</p>
- <pre> <code><span class="keyword">template </span><span class="special"><</span><span class="keyword">typename </span><span class="identifier">T</span><span class="special">><br> </span><span class="keyword">struct </span><span class="identifier">tree_node<br> </span><span class="special">{<br> </span><span class="keyword">typedef </span><span class="identifier">T </span><span class="identifier">parse_node_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">tree_node</span><span class="special"><</span><span class="identifier">T</span><span class="special">> </span><span class="special">> </span><span class="identifier">children_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">children_t</span><span class="special">::</span><span class="identifier">iterator </span><span class="identifier">tree_iterator</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">children_t</span><span class="special">::</span><span class="identifier">const_iterator </span><span class="identifier">const_tree_iterator</span><span class="special">;<br><br> </span><span class="identifier">T </span><span class="identifier">value</span><span class="special">;<br> </span><span class="identifier">children_t </span><span class="identifier">children</span><span class="special">;<br><br> </span><span class="identifier">tree_node</span><span class="special">();<br> </span><span class="keyword">explicit </span><span class="identifier">tree_node</span><span class="special">(</span><span class="identifier">T </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">v</span><span class="special">);<br> </span><span class="identifier">tree_node</span><span class="special">(</span><span class="identifier">T </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">v</span><span class="special">, </span><span class="identifier">children_t </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">c</span><span class="special">);<br> </span><span class="keyword">void </span><span class="identifier">swap</span><span class="special">(</span><span class="identifier">tree_node</span><span class="special"><</span><span class="identifier">T</span><span class="special">>& </span><span class="identifier">x</span><span class="special">);<br> </span><span class="special">};</span></code></pre>
- <p> This class is simply used to separate the tree framework from the data stored
- in the tree. It is a generic node and any type can be stored inside it and acessed
- via the data member value. The default type for T is <tt>node_val_data</tt>.</p>
- <a name="node_val_data"></a>
- <h3>node_val_data</h3>
- <p> The <tt>node_val_data</tt> class contains the actual information about each
- node. This includes the text or token sequence that was parsed, an <tt>id</tt>
- that indicates which rule created the node, a boolean flag that indicates whether
- the node was marked as a root node, and an optional user-specified value. This
- is the interface:</p>
- <pre> <code><span class="keyword">template </span><span class="special"><</span><span class="keyword">typename </span><span class="identifier">IteratorT </span><span class="special">= </span><span class="keyword">char </span><span class="keyword">const</span><span class="special">*, </span><span class="keyword">typename </span><span class="identifier">ValueT </span><span class="special">= </span><span class="identifier">nil_t</span><span class="special">><br> </span><span class="keyword">struct </span><span class="identifier">node_val_data<br> </span><span class="special">{<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">std</span><span class="special">::</span><span class="identifier">iterator_traits</span><span class="special"><</span><span class="identifier">IteratorT</span><span class="special">>::</span><span class="identifier">value_type </span><span class="identifier">value_type</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">value_type</span><span class="special">> </span><span class="identifier">container_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">container_t</span><span class="special">::</span><span class="identifier">iterator </span><span class="identifier">iterator_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="keyword">typename </span><span class="identifier">container_t</span><span class="special">::</span><span class="identifier">const_iterator </span><span class="identifier">const_iterator_t</span><span class="special">;<br><br> </span><span class="identifier">node_val_data</span><span class="special">();<br> </span><span class="identifier">node_val_data</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">);<br> </span><span class="keyword">template </span><span class="special"><</span><span class="keyword">typename </span><span class="identifier">IteratorT2</span><span class="special">><br> </span><span class="identifier">node_val_data</span><span class="special">(</span><span class="identifier">IteratorT2 </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">_first</span><span class="special">, </span><span class="identifier">IteratorT2 </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">_last</span><span class="special">);<br> </span><span class="keyword">void </span><span class="identifier">swap</span><span class="special">(</span><span class="identifier">node_val_data</span><span class="special">& </span><span class="identifier">x</span><span class="special">);<br><br> </span><span class="identifier">container_t</span><span class="special">::</span><span class="identifier">iterator </span><span class="identifier">begin</span><span class="special">();<br> </span><span class="identifier">container_t</span><span class="special">::</span><span class="identifier">const_iterator </span><span class="identifier">begin</span><span class="special">() </span><span class="keyword">const</span><span class="special">;<br> </span><span class="identifier">container_t</span><span class="special">::</span><span class="identifier">iterator </span><span class="identifier">end</span><span class="special">();<br> </span><span class="identifier">container_t</span><span class="special">::</span><span class="identifier">const_iterator </span><span class="identifier">end</span><span class="special">() </span><span class="keyword">const</span><span class="special">;<br><br> </span><span class="keyword">bool </span><span class="identifier">is_root</span><span class="special">() </span><span class="keyword">const</span><span class="special">;<br> </span><span class="keyword">void </span><span class="identifier">is_root</span><span class="special">(</span><span class="keyword">bool </span><span class="identifier">b</span><span class="special">);<br><br> </span><span class="identifier">parser_id </span><span class="identifier">id</span><span class="special">() </span><span class="keyword">const</span><span class="special">;<br> </span><span class="keyword">void </span><span class="identifier">id</span><span class="special">(</span><span class="identifier">parser_id </span><span class="identifier">r</span><span class="special">);<br><br> </span><span class="identifier">ValueT </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">value</span><span class="special">() </span><span class="keyword">const</span><span class="special">;<br> </span><span class="keyword">void </span><span class="identifier">value</span><span class="special">(</span><span class="identifier">ValueT </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">v</span><span class="special">);<br> </span><span class="special">};<br></span></code></pre>
- <a name="parser_id__checking_and_setting"></a>
- <h3>parser_id, checking and setting</h3>
- <p> If a node is generated by a rule, it will have an <tt>id</tt> set. Each rule
- has an id that it sets of all nodes generated by that rule. The id is of type
- <tt><a href="rule.html#tag">parser_id</a></tt>. The default id of each rule
- is set to the address of that rule (converted to an integer). This is not always
- the most convenient, since the code that processes the tree may not have access
- to the rules, and may not be able to compare addresses. So, you can override
- the default id used by each rule by <a href="rule.html#tag">giving it a specific
- ID</a>. Then, when processing the tree you can call <tt>node_val_data::id()</tt>
- to see which rule created that node.</p>
- <a name="structure_layout_of_a_parse_tree"></a>
- <h2>structure/layout of a parse tree</h2>
- <a name="parse_tree_layout"></a>
- <h3>parse tree layout</h3>
- <p> The tree is organized by the rules. Each rule creates a new level in the tree.
- All parsers attached to a rule create a node when a sucessful match is made.
- These nodes become children of a node created by the rule. So, the following
- code:</p>
- <pre> <code><span class="identifier">rule_t </span><span class="identifier">myrule </span><span class="special">= </span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'a'</span><span class="special">) </span><span class="special">>> </span><span class="literal">',' </span><span class="special">>> </span><span class="special">*</span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'b'</span><span class="special">);<br> </span><span class="keyword">char </span><span class="keyword">const</span><span class="special">* </span><span class="identifier">input </span><span class="special">= </span><span class="string">"a,bb"</span><span class="special">;<br> </span><span class="identifier">scanner_t </span><span class="identifier">scanner</span><span class="special">(</span><span class="identifier">input</span><span class="special">, </span><span class="identifier">input </span><span class="special">+ </span><span class="identifier">strlen</span><span class="special">(</span><span class="identifier">input</span><span class="special">));<br> </span><span class="identifier">tree_match</span><span class="special"><> </span><span class="identifier">m </span><span class="special">= </span><span class="identifier">myrule</span><span class="special">.</span><span class="identifier">parse</span><span class="special">(</span><span class="identifier">scanner</span><span class="special">);<br></span></code></pre>
- <p> When executed, this code would return a tree_match, m. <tt>m.trees[0]</tt>
- would contain a tree like this:</p>
- <table border="0" align="center">
- <tbody><tr>
- <td><img src="theme/trees1.png" width="253" height="151"></td>
- </tr>
- </tbody></table>
- <p> The root node would not contain any text, and it's id would be set to the
- address of myrule. It would have four children. Each child's id would be set
- to the address of myrule, would contain the text as shown in the diagram, and
- would have no children.</p>
- <a name="ast_layout"></a>
- <h2>ast layout</h2>
- <p> When calling <a href="#ast_parse">ast_parse</a>, the tree gets generated differently.
- It mostly works the same as when generating a parse tree. The difference happens
- when a rule only generated one sub-node. Instead of creating a new level, <a href="#ast_parse">ast_parse</a>
- will not create a new level, it will just leave the existing node. So, this
- code:</p>
- <pre> <code><span class="identifier">rule_t </span><span class="identifier">myrule </span><span class="special">= </span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'a'</span><span class="special">);<br> </span><span class="keyword">char </span><span class="keyword">const</span><span class="special">* </span><span class="identifier">input </span><span class="special">= </span><span class="string">"a"</span><span class="special">;<br> </span><span class="identifier">ast_scanner_t </span><span class="identifier">scanner</span><span class="special">(</span><span class="identifier">input</span><span class="special">, </span><span class="identifier">input</span><span class="special">+</span><span class="identifier">strlen</span><span class="special">(</span><span class="identifier">input</span><span class="special">));<br> </span><span class="identifier">tree_match</span><span class="special"><> </span><span class="identifier">m </span><span class="special">= </span><span class="identifier">myrule</span><span class="special">.</span><span class="identifier">parse</span><span class="special">(</span><span class="identifier">scanner</span><span class="special">);<br></span></code></pre>
- <p> will generate a single node that contains 'a'. If <tt>tree_match_policy</tt>
- had been used instead of <tt>ast_match_policy</tt>, the tree would have looked
- like this:</p>
- <table border="0" align="center">
- <tbody><tr>
- <td><img src="theme/trees2.png" width="139" height="151"></td>
- </tr>
- </tbody></table>
- <p> ast_match_policy has the effect of eliminating intermediate rule levels which
- are simply pass-through rules. This is not enough to generate abstract syntax
- trees, <a href="#root_node_d_and_ast_generation">root_node_d</a> is also needed. <a href="#root_node_d_and_ast_generation">root_node_d</a>
- will be explained later.</p>
- <a name="switching__gen_pt_node_d____amp__gen_ast_node_d__"></a>
- <h2>switching: gen_pt_node_d[] & gen_ast_node_d[]</h2>
- <p> If you want to mix and match the parse tree and ast behaviors in your application,
- you can use the <tt>gen_pt_node_d[]</tt> and <tt>gen_ast_node_d[]</tt> directives.
- When parsing passes through the <tt>gen_pt_node_d</tt> directive, parse tree
- creation behavior is turned on. When the <tt>gen_ast_node_d</tt>
- directive is used, the enclosed parser will generate a tree using the
- ast behavior. Note that you must pay attention to how your rules are declared
- if you use a rule inside of these directives. The match policy of
- the scanner will have to correspond to the desired behavior. If you
- avoid rules and use primitive parsers or grammars, then you will not have
- problems.</p>
- <a name="directives"></a>
- <h2>Directives</h2>
- <p> There are a few more directives that can be used to control the generation
- of trees. These directives only effect tree generation. Otherwise, they have
- no effect.<br>
- </p>
- <a name="no_node_d"></a>
- <h3>no_node_d</h3>
- <p> This directive is similar to <tt>gen_pt_node_d</tt> and <tt>gen_ast_node_d</tt>,
- in that is modifies the scanner's match policy used by the enclosed parser. As it's name
- implies, it does no tree generation, it turns it off completely. This is useful
- if there are parts of your grammar which are not needed in the tree. For instance:
- keywords, operators (<tt>*</tt>, <tt>-</tt>, <tt>&&</tt>, etc.) By eliminating
- these from the tree, both memory usage and parsing time can be lowered. This
- directive has the same requirements with respect to rules as <tt>gen_pt_node_d</tt>
- and <tt>gen_ast_node_d</tt> do. See the example file xml_grammar.hpp (in libs/spirit/example/application/xml
- directory) for example
- usage of <tt>no_node_d[]</tt>.</p>
- <a name="discard_node_d"></a>
- <h3>discard_node_d</h3>
- <p> This directive has a similar purpose to <tt>no_node_d</tt>, but works differently.
- It does not switch the scanner's match policy, so the enclosed parser still generates
- nodes. The generated nodes are discarded and do not appear in the tree. Using
- <tt>discard_node_d</tt> is slower than <tt>no_node_d</tt>, but it does not suffer
- from the drawback of having to specify a different rule type for any rule inside
- it.</p>
- <a name="leaf_node_d_token_node_d"></a>
- <h3>leaf_node_d/token_node_d</h3>
- <p> Both <tt>leaf_node_t</tt> and <tt>token_node_d</tt> work the same. They
- create a single node for the match generated by the enclosed parser.
- Unlike with earlier versions of Spirit, this directive is an implicit
- lexeme and alters the scanner (see
- <a href="faq.html#scanner_business">Scanner Business</a>). </p>
- <h3>reduced_node_d</h3>
- <p> This directive groups together all the nodes generated by the enclosed parser.
- For earlier versions of Spirit <tt>leaf_node_d</tt> and <tt>token_node_d</tt>
- were implemented this way. The new implementation of those directives is a
- lot faster, so <tt>reduced_node_d</tt> is primarily provided for portability
- and can be useful when using a custom node factory (see advanced tree
- generation, below).</p>
- <h3>infix_node_d</h3>
- <p> This is useful for removing separators from lists. It discards all the nodes
- in even positions. Thus this rule:</p>
- <pre> <code><span class="identifier">rule_t </span><span class="identifier">intlist </span><span class="special">= </span><span class="identifier">infix_node_d</span><span class="special">[ </span><span class="identifier">integer </span><span class="special">>> </span><span class="special">*(</span><span class="literal">',' </span><span class="special">>> </span><span class="identifier">integer</span><span class="special">) </span><span class="special">];</span></code></pre>
- <p> would discard all the comma nodes and keep all the integer nodes.</p>
- <a name="discard_first_node_d"></a>
- <h3>discard_first_node_d</h3>
- <p> This discards the first node generated.</p>
- <a name="discard_last_node_d"></a>
- <h3>discard_last_node_d</h3>
- <p> This discards the last node generated.</p>
- <a name="inner_node_d"></a>
- <h3>inner_node_d</h3>
- <p> This discards the first and last node generated.</p>
- <a name="root_node_d_and_ast_generation"></a>
- <h2>root_node_d and ast generation</h2>
- <p> The <tt>root_node_d</tt> directive is used to help out ast generation. It
- has no effect when generating a parse tree. When a parser is enclosed in <tt>root_node_d</tt>,
- the node it generates is marked as a root. This affects the way it is treated
- when it's added to the list of nodes being generated. Here's an example:</p>
- <pre> <code><span class="identifier">rule_t </span><span class="identifier">add </span><span class="special">= </span><span class="identifier">integer </span><span class="special">>> </span><span class="special">*(</span><span class="identifier">root_node_d</span><span class="special">[ </span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'+'</span><span class="special">) </span><span class="special">] </span><span class="special">>> </span><span class="identifier">integer</span><span class="special">);</span></code></pre>
- <p> When parsing 5+6 the following tree will be generated:</p>
- <table border="0" align="center">
- <tbody><tr>
- <td><img src="theme/trees3.png"></td>
- </tr>
- </tbody></table>
- <p> When parsing 1+2+3 the following will be generated:</p>
- <table border="0" align="center">
- <tbody><tr>
- <td><img src="theme/trees4.png"></td>
- </tr>
- </tbody></table>
- <p> When a new node is created the following rules are used to determine how the
- tree will be generated:</p>
- <pre><code> Let a be the previously generated node. <br> Let b be the new node.<br><br> If b is a root node then<br><br> b's children become a + b's previous children. <br> a is the new first child of b.<br><br> else if a is a root node and b is not, then<br><br> b becomes the last child of a.<br><br> else<br><br> a and b become siblings.</code></pre>
- <p> After parsing leaves the current rule, the root node flag on the top node
- is turned off. This means that the root_node_d directive only affects the current
- rule.</p>
- <p> <img height="16" width="15" src="theme/lens.gif"> The example <a href="../example/fundamental/ast_calc.cpp">ast_calc.cpp</a> demonstrates the use of root_node_d and <a href="#ast_parse">ast_parse</a>. The full source code can be <a href="../example/fundamental/ast_calc.cpp">viewed here</a>. This is part of the Spirit distribution.</p>
- <a name="parse_tree_iterator"></a>
- <h2>parse_tree_iterator</h2>
- <p> The <tt>parse_tree_iterator</tt> class allows you to parse a tree using spirit.
- The class iterates over the tokens in the leaf nodes in the same order they
- were created. The <tt>parse_tree_iterator</tt> is templated on <tt>ParseTreeMatchT</tt>.
- It is constructed with a container of trees, and a position to start. Here is
- an example usage:</p>
- <pre> <code><span class="identifier">rule_t </span><span class="identifier">myrule </span><span class="special">= </span><span class="identifier">ch_p</span><span class="special">(</span><span class="literal">'a'</span><span class="special">);<br> </span><span class="keyword">char </span><span class="keyword">const</span><span class="special">* </span><span class="identifier">input </span><span class="special">= </span><span class="string">"a"</span><span class="special">;<br><br> </span><span class="comment">// generate parse tree<br> </span><span class="identifier">tree_parse_info</span><span class="special"><> </span><span class="identifier">i </span><span class="special">= </span><span class="identifier">pt_parse</span><span class="special">(</span><span class="identifier">input</span><span class="special">, </span><span class="identifier">myrule</span><span class="special">);<br><br> </span><span class="keyword">typedef </span><span class="identifier">parse_tree_iterator</span><span class="special"><</span><span class="identifier">tree_match</span><span class="special"><> </span><span class="special">> </span><span class="identifier">parse_tree_iterator_t</span><span class="special">;<br><br> </span><span class="comment">// create a first and last iterator to work off the tree<br> </span><span class="identifier">parse_tree_iterator_t </span><span class="identifier">first</span><span class="special">(</span><span class="identifier">i</span><span class="special">.</span><span class="identifier">trees</span><span class="special">, </span><span class="identifier">i</span><span class="special">.</span><span class="identifier">trees</span><span class="special">.</span><span class="identifier">begin</span><span class="special">());<br> </span><span class="identifier">parse_tree_iterator_t </span><span class="identifier">last</span><span class="special">;<br><br> </span><span class="comment">// parse the tree<br> </span><span class="identifier">rule</span><span class="special"><</span><span class="identifier">parse_tree_iterator_t</span><span class="special">> </span><span class="identifier">tree_parser </span><span class="special">=...<br> </span><span class="identifier">tree_parser</span><span class="special">.</span><span class="identifier">parse</span><span class="special">(</span><span class="identifier">first</span><span class="special">, </span><span class="identifier">last</span><span class="special">);<br></span></code></pre>
- <p> <a name="advanced_tree_generation"></a>
- </p>
- <h2>advanced tree generation</h2>
- <a name="node_value"></a>
- <h3>node value</h3>
- <p> The <tt>node_val_data</tt> can contain a value. By default it contains a <tt>void_t</tt>,
- which is an empty class. You can specify the type, using a template parameter,
- which will then be stored in every node. The type must be default constructible,
- and assignable. You can get and set the value using</p>
- <pre> <code><span class="identifier">ValueT </span><span class="identifier">node_val_data</span><span class="special">::</span><span class="identifier">value</span><span class="special">;</span></code></pre>
- <p> and</p>
- <pre> <code><span class="keyword">void </span><span class="identifier">node_val_data</span><span class="special">::</span><span class="identifier">value</span><span class="special">(</span><span class="identifier">Value </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">value</span><span class="special">);</span></code></pre>
- <p> To specify the value type, you must use a different <a href="#node_val_data">node_val_data
- </a>factory than the default. The following example shows how to modify the factory to store and retrieve a double inside each <span class="identifier">node_val_data</span>.
- <pre> <span class=keyword>typedef </span><span class=identifier>node_val_data_factory</span><span class=special><</span><span class=keyword>double</span><span class=special>> </span><span class=identifier>factory_t</span><span class=special>;<br> </span><span class=identifier>my_grammar </span><span class=identifier>gram</span><span class=special>;<br> </span><span class=identifier>my_skip_grammar </span><span class=identifier>skip</span><span class=special>;<br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>iterator_t</span><span class=special>, </span><span class=identifier>factory_t</span><span class=special>> </span><span class=identifier>i </span><span class=special>= <br> </span><span class=identifier>ast_parse</span><span class=special><</span><span class=identifier>factory_t</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>gram</span><span class=special>, </span><span class=identifier>skip</span><span class=special>);<br> // access the double in the root node<br> </span><span class=keyword>double </span><span class=identifier>d </span><span class=special>= </span><span class=identifier>i</span><span class=special>.</span><span class=identifier>trees</span><span class=special>.</span><span class=identifier>begin</span><span class=special>()-></span><span class=identifier>value</span><span class=special>;<br></span></pre>
- </p>
- <a name="access_node_d"></a>
- <h3>access_node_d</h3>
- <p> Now, you may be wondering, "What good does it do to have a value I can
- store in each node, but not to have any way of setting it?" Well, that's
- what <tt>access_node_d</tt> is for. <tt>access_node_d</tt> is a directive. It
- allows you to attach an action to it, like this:</p>
- <pre> <code><span class="identifier">access_node_d</span><span class="special">[...</span><span class="identifier">some </span><span class="identifier">parsers</span><span class="special">...][</span><span class="identifier">my_action</span><span class="special">()]</span></code></pre>
- <p> The attached action will be passed 3 parameters: A reference to the root node
- of the tree generated by the parser, and the current first and last iterators.
- The action can set the value stored in the node.</p>
- <a name="tree_node_factories"></a>
- <h3>Tree node factories</h3>
- <p> By setting the factory, you can control what type of nodes are created and
- how they are created. There are 3 predefined factories: <tt>node_val_data_factory</tt>,
- <tt>node_all_val_data_factory</tt>, and <tt>node_iter_data_factory</tt>. You
- can also create your own factory to support your own node types.</p>
- <p> Using factories with grammars is quite easy, you just need to specify the factory type as explicit template parameter to the free ast_parse function:</p>
- <pre> <span class=keyword>typedef </span><span class=identifier>node_iter_data_factory</span><span class=special><</span><span class=keyword>int</span><span class=special>> </span><span class=identifier>factory_t</span><span class=special>;<br> </span><span class=identifier>my_grammar </span><span class=identifier>gram</span><span class=special>;<br> </span><span class=identifier>my_skip_grammar </span><span class=identifier>skip</span><span class=special>;<br> </span><span class=identifier>tree_parse_info</span><span class=special><</span><span class=identifier>iterator_t</span><span class=special>, </span><span class=identifier>factory_t</span><span class=special>> </span><span class=identifier>i </span><span class=special>= <br> </span><span class=identifier>ast_parse</span><span class=special><</span><span class=identifier>factory_t</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>gram</span><span class=special>, </span><span class=identifier>skip</span><span class=special>);<br></span></pre>
- <p> Instead, using the factory directly with rules is slightly harder because the
- factory is a template parameter to the scanner match policy, so you must use a
- custom scanner:</p>
- <pre> <code><span class="keyword">typedef </span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">void_t </span><span class="identifier">value_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">node_val_data_factory</span><span class="special"><</span><span class="identifier">value_t</span><span class="special">> </span><span class="identifier">factory_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">tree_match</span><span class="special"><</span><span class="identifier">iterator_t</span><span class="special">, </span><span class="identifier">factory_t</span><span class="special">> </span><span class="identifier">match_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">ast_match_policy</span><span class="special"><</span><span class="identifier">iterator_t</span><span class="special">, </span><span class="identifier">factory_t</span><span class="special">> </span><span class="identifier">match_policy_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">scanner</span><span class="special"><</span><span class="identifier">iterator_t</span></code><code><span class="special">,</span></code><code><span class="identifier"> scanner_policies</span></code><code><span class="identifier"></span><span class="special"><</span></code><code><span class="identifier">iter_policy_t</span></code><code><span class="special">,</span></code><code><span class="identifier"> match_policy_t</span><span class="special">></span></code><code><span class="identifier"></span><span class="special"> ></span></code><code><span class="special"> </span><span class="identifier">scanner_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">rule</span><span class="special"><</span><span class="identifier">scanner_t</span><span class="special"></span><span class="identifier"></span><span class="special">> </span><span class="identifier">rule_t</span><span class="special">;<br><br> </span><span class="identifier">rule_t </span><span class="identifier">r </span><span class="special">=...;<br><br></span></code><code><span class="special"> </span><span class="identifier">scanner_t </span><span class="identifier">scan </span><span class="special">= </span><span class="identifier">scanner_t</span><span class="special"></span><span class="identifier"></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"></span><span class="special">);<br></span></code><code><span class="special"></span></code><code><span class="special"> </span><span class="identifier">match_t </span><span class="identifier">hit </span><span class="special">= </span><span class="identifier">r</span><span class="special">.</span><span class="identifier">parse</span><span class="special">(</span><span class="identifier"></span><span class="special"></span><span class="identifier"></span><span class="special"></span><span class="identifier">scan</span><span class="special">);</span></code></pre>
- <a name="node_val_data_factory"></a>
- <h3>node_val_data_factory</h3>
- <p> This is the default factory. It creates <tt>node_val_data</tt> nodes. Leaf
- nodes contain a copy of the matched text, and intermediate nodes don't. <tt>node_val_data_factory</tt>
- has one template parameter: <tt>ValueT</tt>. <tt>ValueT</tt> specifies the type
- of value that will be stored in the <tt>node_val_data</tt>.</p>
- <a name="node_all_val_data_factory"></a>
- <h3>node_all_val_data_factory</h3>
- <p> This factory also creates <tt>node_val_data</tt>. The difference between it
- and <tt>node_val_data_factory</tt> is that <b>every</b> node contains all the
- text that spans it. This means that the root node will contain a copy of the
- entire parsed input sequence. <tt>node_all_val_data_factory</tt> has one template
- parameter: <tt>ValueT</tt>. <tt>ValueT</tt> specifies the type of value that
- will be stored in the <tt>node_val_data</tt>.</p>
- <a name="node_iter_data_factory"></a>
- <h3>node_iter_data_factory</h3>
- <p> This factory creates the <tt>parse_tree_iter_node</tt>. This node stores iterators
- into the input sequence instead of making a copy. It can use a lot less memory.
- However, the input sequence must stay valid for the life of the tree, and it's
- not a good idea to use the <tt>multi_pass</tt> iterator with this type of node.
- All levels of the tree will contain a begin and end iterator. <tt>node_iter_data_factory</tt>
- has one template parameter: <tt>ValueT</tt>. <tt>ValueT</tt> specifies the type
- of value that will be stored in the node_val_data.</p>
- <a name="custom"></a>
- <h3>custom</h3>
- <p> You can create your own factory. It should look like this:</p>
- <pre> <code><span class="keyword">class </span><span class="identifier">my_factory<br> </span><span class="special">{<br> </span><span class="keyword">public</span><span class="special">:<br><br> </span><span class="comment">// This inner class is so that the factory can simulate<br> // a template template parameter<br><br> </span><span class="keyword">template </span><span class="special"><</span><span class="keyword">typename </span><span class="identifier">IteratorT</span><span class="special">><br> </span><span class="keyword">class </span><span class="identifier">factory<br> </span><span class="special">{<br> </span><span class="keyword">public</span><span class="special">:<br><br> </span><span class="comment">// This is your node type<br> </span><span class="keyword">typedef </span><span class="identifier">my_node_type </span><span class="identifier">node_t</span><span class="special">;<br><br> </span><span class="keyword">static </span><span class="identifier">node_t </span><span class="identifier">create_node</span><span class="special">(<br> </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">bool </span><span class="identifier">is_leaf_node</span><span class="special">)<br> </span><span class="special">{<br> </span><span class="comment">// create a node and return it.<br> </span><span class="special">}<br><br> </span><span class="comment">// This function is used by the reduced_node directive.<br> // If you don't use it, then you can leave this function<br> // unimplemented.<br><br> </span><span class="keyword">template </span><span class="special"><</span><span class="keyword">typename </span><span class="identifier">ContainerT</span><span class="special">><br> </span><span class="keyword">static </span><span class="identifier">node_t </span><span class="identifier">group_nodes</span><span class="special">(</span><span class="identifier">ContainerT </span><span class="keyword">const</span><span class="special">& </span><span class="identifier">nodes</span><span class="special">)<br> </span><span class="special">{<br> </span><span class="comment">// Group all the nodes into one and return it.<br> </span><span class="special">}<br> </span><span class="special">};<br> </span><span class="special">};<br><br><br> </span><span class="comment">// Typedefs to use my_factory<br> </span><span class="keyword">typedef </span><span class="identifier">my_factory </span><span class="identifier">factory_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">tree_match</span><span class="special"><</span><span class="identifier">iterator_t</span><span class="special">, </span><span class="identifier">factory_t</span><span class="special">> </span><span class="identifier">match_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">tree_match_policy</span><span class="special"><</span><span class="identifier">iterator_t</span><span class="special">, </span><span class="identifier">factory_t</span><span class="special">> </span><span class="identifier">match_policy_t</span><span class="special">;<br></span></code><code><span class="special"><br> </span><span class="comment">// Typedefs if you are using rules instead of grammars<br></span></code><code><span class="special"> </span><span class="keyword">typedef </span><span class="identifier">scanner</span><span class="special"><</span><span class="identifier">iterator_t</span></code><code><span class="special">,</span></code><code><span class="identifier"> scanner_policies</span></code><code><span class="identifier"></span><span class="special"><</span></code><code><span class="identifier">iter_policy_t</span></code><code><span class="special">,</span></code><code><span class="identifier"> match_policy_t</span><span class="special">></span></code><code><span class="identifier"></span><span class="special"> ></span></code><code><span class="special"> </span><span class="identifier">scanner_t</span><span class="special">;<br> </span><span class="keyword">typedef </span><span class="identifier">rule</span><span class="special"><</span><span class="identifier">scanner_t</span><span class="special"></span><span class="identifier"></span><span class="special">> </span><span class="identifier">rule_t</span><span class="special">;<br></span></code><code><span class="special"></span><span class="special"><br></span></code></pre><table border="0"><tbody><tr><td width="10"><br>
- </td>
- <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
- <td width="30"><a href="symbols.html"><img src="theme/l_arr.gif" border="0"></a></td>
- <td width="30"><a href="multi_pass.html"><img src="theme/r_arr.gif" border="0"></a></td>
- </tr>
- </tbody></table>
- <hr size="1">
- <p class="copyright">Copyright © 2001-2002 Daniel C. Nuffer<br>Revised 2007 Copyright © Tobias Schwinger<br>
- <br>
- <font size="2">Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)</font></p>
- <p class="copyright"> </p>
- <br>
- </body></html>
|