]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>Trees</title> |
2 | ||
3 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | |
4 | <link rel="stylesheet" href="theme/style.css" type="text/css"></head> | |
5 | <body> | |
6 | <table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2"> | |
7 | <tbody><tr> | |
8 | <td width="10"> | |
9 | <br> | |
10 | </td> | |
11 | <td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Trees</b></font> | |
12 | </td> | |
13 | <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td> | |
14 | </tr> | |
15 | </tbody></table> | |
16 | <br> | |
17 | <table border="0"> | |
18 | <tbody><tr> | |
19 | <td width="10"><br> | |
20 | </td> | |
21 | <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td> | |
22 | <td width="30"><a href="symbols.html"><img src="theme/l_arr.gif" border="0"></a></td> | |
23 | <td width="30"><a href="multi_pass.html"><img src="theme/r_arr.gif" border="0"></a></td> | |
24 | </tr> | |
25 | </tbody></table> | |
26 | <h2>Why use parse trees</h2> | |
27 | <p> Parse trees are an in-memory representation of the input with a structure | |
28 | that conforms to the grammar.</p> | |
29 | <p> The advantages of using parse trees instead of semantic actions:</p> | |
30 | <ul> | |
31 | <li>You can make multiple passes over the data without having to re-parse the | |
32 | input.</li> | |
33 | <li>You can perform transformations on the tree.</li> | |
34 | <li>You can evaluate things in any order you want, whereas with attribute schemes | |
35 | you have to process in a begin to end fashion.</li> | |
36 | <li>You do not have to worry about backtracking and action side effects that | |
37 | may occur with an ambiguous grammar.</li> | |
38 | </ul> | |
39 | <p> <b>Example</b></p> | |
40 | <p> Now that you think you may want to use trees, I'll give an example of how | |
41 | to use them and you can see how easy they are to use. So, following with tradition | |
42 | (and the rest of the documentation) we'll do a calculator. Here's the grammar:</p> | |
43 | <pre> <code><span class="identifier">integer </span><span class="special"> | |
44 | = </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"> | |
45 | >> *( (</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> | |
46 | <p> Now, you'll notice the only thing different in this grammar is the <tt>token_node_d</tt> | |
47 | directive. This causes the match of the integer rule to end up in one node. | |
48 | Without <tt>token_node_d</tt>, each character would get it's own node. | |
49 | Further note that <tt>token_node_d</tt> is an implicit lexeme (that means | |
50 | no <tt>lexeme_d</tt> is needed to switch to character level parsing). | |
51 | As you'll soon see, it's easier to convert the input into an int when all | |
52 | the characters are in one node. Here is how the parse is done to create a tree:</p> | |
53 | <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> | |
54 | <p> <tt>pt_parse()</tt> is similar to <tt>parse()</tt>. There are four overloads: | |
55 | two for pairs of first and last iterators and two for character strings. Two | |
56 | of the functions take a skipper parser and the other two do not.</p> | |
57 | <p> The <tt>tree_parse_info</tt> struct contains the same information as a <tt>parse_info</tt> | |
58 | struct as well as one extra data member called trees. When the parse finishes, | |
59 | trees will contain the parse tree.</p> | |
60 | <p> Here is how you can use the tree to evaluate the input:</p> | |
61 | <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> | |
62 | <p> Now you ask, where did <tt>evaluate()</tt> come from? Is it part of spirit? | |
63 | Unfortunately, no, <tt>evaluate()</tt> is only a part of the sample. Here it | |
64 | is:</p> | |
65 | <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> | |
66 | <p> So here you see evaluate() simply calls <tt>eval_expression()</tt> passing | |
67 | the begin() iterator of info.trees. Now here's the rest of the example:</p> | |
68 | <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> | |
69 | <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> | |
70 | <p>So, you like what you see, but maybe you think that the parse tree is too | |
71 | hard to process? With a few more directives you can generate an abstract syntax | |
72 | tree (ast) and cut the amount of evaluation code by at least <b>50%</b>. So | |
73 | without any delay, here's the ast calculator grammar:</p> | |
74 | <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"> | |
75 | >> *( (</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> | |
76 | <p> The differences from the parse tree grammar are hi-lighted in <b><font color="#ff0000">bold-red</font></b>. | |
77 | The <tt>inner_node_d</tt> directive causes the first and last nodes generated | |
78 | by the enclosed parser to be discarded, since we don't really care about the | |
79 | parentheses when evaluating the expression. The <tt>root_node_d</tt> directive | |
80 | is the key to ast generation. A node that is generated by the parser inside | |
81 | of <tt>root_node_d</tt> is marked as a root node. When a root node is created, | |
82 | it becomes a root or parent node of the other nodes generated by the same rule.</p> | |
83 | <p> To start the parse and generate the ast, you must use the ast_parse functions, | |
84 | which are similar to the pt_parse functions.</p> | |
85 | <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> | |
86 | <p> Here is the eval_expression function (note that to process the ast we only | |
87 | need one function instead of four):</p> | |
88 | <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> | |
89 | <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 | |
90 | trees. For more nitty-gritty details, keep on reading the rest of this chapter.</p> | |
91 | <a name="usage"></a> | |
92 | <h2>Usage</h2> | |
93 | <a name="pt_parse"></a> | |
94 | <h3>pt_parse</h3> | |
95 | <p> To create a parse tree, you can call one of the five free functions:</p> | |
96 | <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>, | |
97 | </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> | |
98 | <a name="ast_parse"></a> | |
99 | <h3>ast_parse</h3> | |
100 | <p> To create an abstract syntax tree (ast for short) you call one of the five | |
101 | free functions:</p> | |
102 | <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>, | |
103 | </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> | |
104 | <a name="tree_parse_info"></a> | |
105 | <h3>tree_parse_info</h3> | |
106 | <p> The <tt>tree_parse_info</tt> struct returned from pt_parse and ast_parse contains | |
107 | information about the parse:</p> | |
108 | <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> | |
109 | <table width="90%" border="0" align="center"> | |
110 | <tbody><tr> | |
111 | <td class="table_title" colspan="10"> tree_parse_info </td> | |
112 | </tr> | |
113 | <tr> | |
114 | </tr><tr> | |
115 | <td class="table_cells"><b>stop</b></td> | |
116 | <td class="table_cells">points to the final parse position (i.e. parsing processed | |
117 | the input up to this point).</td> | |
118 | </tr> | |
119 | <tr><td class="table_cells"><b>match</b></td> | |
120 | <td class="table_cells">true if parsing is successful. This may be full (the | |
121 | parser consumed all the input), or partial (the parser consumed only a portion | |
122 | of the input.)</td> | |
123 | </tr> | |
124 | <tr><td class="table_cells"><b>full</b></td> | |
125 | <td class="table_cells">true when we have a full match (when the parser consumed | |
126 | all the input).</td> | |
127 | </tr> | |
128 | <tr><td class="table_cells"><b>length</b></td> | |
129 | <td class="table_cells">The number of characters consumed by the parser. This | |
130 | is valid only if we have a successful match (either partial or full).</td> | |
131 | </tr> | |
132 | <tr><td class="table_cells"><b>trees</b></td> | |
133 | <td class="table_cells">Contains the root node(s) of the tree.</td> | |
134 | </tr> | |
135 | </tbody></table> | |
136 | <a name="tree_match"></a> | |
137 | <h3>tree_match</h3> | |
138 | <p> When Spirit is generating a tree, the parser's parse() member function will | |
139 | return a tree_match object, instead of a match object. tree_match has three | |
140 | template parameters. The first is the Iterator type which defaults to <tt>char | |
141 | const*</tt>. The second is the node factory, which defaults to <a href="#node_val_data_factory">node_val_data_factory</a>. | |
142 | The third is the attribute type stored in the match. A tree_match has a member | |
143 | variable which is a container (a <tt>std::vector</tt>) of <a href="#tree_node">tree_node</a> | |
144 | objects named trees. For efficiency reasons, when a tree_match is copied, the | |
145 | trees are <b>not</b> copied, they are moved to the new object, and the source | |
146 | object is left with an empty tree container. tree_match supports the same interface | |
147 | as the match class: it has an operator bool() so you can test it for a sucessful | |
148 | match: if (matched), and you can query the match length via the length() function. | |
149 | The class has this interface:</p> | |
150 | <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> | |
151 | <p> When a parse has sucessfully completed, the trees data member will contain | |
152 | the root node of the tree. </p> | |
153 | <table width="80%" border="0" align="center"> | |
154 | <tbody><tr> | |
155 | <td class="note_box"><img src="theme/lens.gif" width="15" height="16"> <b>vector?</b><br> | |
156 | <br> | |
157 | You may wonder, why is it a vector then? The answer is that it is partly | |
158 | for implementation purposes, and also if you do not use any rules in your | |
159 | grammar, then trees will contain a sequence of nodes that will not have | |
160 | any children.</td> | |
161 | </tr> | |
162 | </tbody></table> | |
163 | <p> Having spirit create a tree is similar to how a normal parse is done:</p> | |
164 | <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> | |
165 | <a name="tree_node"></a> | |
166 | <h3>tree_node</h3> | |
167 | <p> Once you have created a tree by calling <a href="#pt_parse">pt_parse</a> | |
168 | or <a href="#ast_parse">ast_parse</a>, you have a <a href="#tree_parse_info">tree_parse_info</a> | |
169 | which contains the root node of the tree, and now you need to do something with | |
170 | the tree. The data member trees of <a href="#tree_parse_info">tree_parse_info</a> | |
171 | is a std::vector<tree_node>. tree_node provides the tree structure. The | |
172 | class has one template parameter named T. tree_node contains an instance of | |
173 | type T. It also contains a std::vector<tree_node<T> > which are | |
174 | the node's children. The class looks like this:</p> | |
175 | <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> | |
176 | <p> This class is simply used to separate the tree framework from the data stored | |
177 | in the tree. It is a generic node and any type can be stored inside it and acessed | |
178 | via the data member value. The default type for T is <tt>node_val_data</tt>.</p> | |
179 | <a name="node_val_data"></a> | |
180 | <h3>node_val_data</h3> | |
181 | <p> The <tt>node_val_data</tt> class contains the actual information about each | |
182 | node. This includes the text or token sequence that was parsed, an <tt>id</tt> | |
183 | that indicates which rule created the node, a boolean flag that indicates whether | |
184 | the node was marked as a root node, and an optional user-specified value. This | |
185 | is the interface:</p> | |
186 | <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> | |
187 | <a name="parser_id__checking_and_setting"></a> | |
188 | <h3>parser_id, checking and setting</h3> | |
189 | <p> If a node is generated by a rule, it will have an <tt>id</tt> set. Each rule | |
190 | has an id that it sets of all nodes generated by that rule. The id is of type | |
191 | <tt><a href="rule.html#tag">parser_id</a></tt>. The default id of each rule | |
192 | is set to the address of that rule (converted to an integer). This is not always | |
193 | the most convenient, since the code that processes the tree may not have access | |
194 | to the rules, and may not be able to compare addresses. So, you can override | |
195 | the default id used by each rule by <a href="rule.html#tag">giving it a specific | |
196 | ID</a>. Then, when processing the tree you can call <tt>node_val_data::id()</tt> | |
197 | to see which rule created that node.</p> | |
198 | <a name="structure_layout_of_a_parse_tree"></a> | |
199 | <h2>structure/layout of a parse tree</h2> | |
200 | <a name="parse_tree_layout"></a> | |
201 | <h3>parse tree layout</h3> | |
202 | <p> The tree is organized by the rules. Each rule creates a new level in the tree. | |
203 | All parsers attached to a rule create a node when a sucessful match is made. | |
204 | These nodes become children of a node created by the rule. So, the following | |
205 | code:</p> | |
206 | <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> | |
207 | <p> When executed, this code would return a tree_match, m. <tt>m.trees[0]</tt> | |
208 | would contain a tree like this:</p> | |
209 | <table border="0" align="center"> | |
210 | <tbody><tr> | |
211 | <td><img src="theme/trees1.png" width="253" height="151"></td> | |
212 | </tr> | |
213 | </tbody></table> | |
214 | <p> The root node would not contain any text, and it's id would be set to the | |
215 | address of myrule. It would have four children. Each child's id would be set | |
216 | to the address of myrule, would contain the text as shown in the diagram, and | |
217 | would have no children.</p> | |
218 | <a name="ast_layout"></a> | |
219 | <h2>ast layout</h2> | |
220 | <p> When calling <a href="#ast_parse">ast_parse</a>, the tree gets generated differently. | |
221 | It mostly works the same as when generating a parse tree. The difference happens | |
222 | when a rule only generated one sub-node. Instead of creating a new level, <a href="#ast_parse">ast_parse</a> | |
223 | will not create a new level, it will just leave the existing node. So, this | |
224 | code:</p> | |
225 | <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> | |
226 | <p> will generate a single node that contains 'a'. If <tt>tree_match_policy</tt> | |
227 | had been used instead of <tt>ast_match_policy</tt>, the tree would have looked | |
228 | like this:</p> | |
229 | <table border="0" align="center"> | |
230 | <tbody><tr> | |
231 | <td><img src="theme/trees2.png" width="139" height="151"></td> | |
232 | </tr> | |
233 | </tbody></table> | |
234 | <p> ast_match_policy has the effect of eliminating intermediate rule levels which | |
235 | are simply pass-through rules. This is not enough to generate abstract syntax | |
236 | 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> | |
237 | will be explained later.</p> | |
238 | <a name="switching__gen_pt_node_d____amp__gen_ast_node_d__"></a> | |
239 | <h2>switching: gen_pt_node_d[] & gen_ast_node_d[]</h2> | |
240 | <p> If you want to mix and match the parse tree and ast behaviors in your application, | |
241 | you can use the <tt>gen_pt_node_d[]</tt> and <tt>gen_ast_node_d[]</tt> directives. | |
242 | When parsing passes through the <tt>gen_pt_node_d</tt> directive, parse tree | |
243 | creation behavior is turned on. When the <tt>gen_ast_node_d</tt> | |
244 | directive is used, the enclosed parser will generate a tree using the | |
245 | ast behavior. Note that you must pay attention to how your rules are declared | |
246 | if you use a rule inside of these directives. The match policy of | |
247 | the scanner will have to correspond to the desired behavior. If you | |
248 | avoid rules and use primitive parsers or grammars, then you will not have | |
249 | problems.</p> | |
250 | <a name="directives"></a> | |
251 | <h2>Directives</h2> | |
252 | <p> There are a few more directives that can be used to control the generation | |
253 | of trees. These directives only effect tree generation. Otherwise, they have | |
254 | no effect.<br> | |
255 | </p> | |
256 | <a name="no_node_d"></a> | |
257 | <h3>no_node_d</h3> | |
258 | <p> This directive is similar to <tt>gen_pt_node_d</tt> and <tt>gen_ast_node_d</tt>, | |
259 | in that is modifies the scanner's match policy used by the enclosed parser. As it's name | |
260 | implies, it does no tree generation, it turns it off completely. This is useful | |
261 | if there are parts of your grammar which are not needed in the tree. For instance: | |
262 | keywords, operators (<tt>*</tt>, <tt>-</tt>, <tt>&&</tt>, etc.) By eliminating | |
263 | these from the tree, both memory usage and parsing time can be lowered. This | |
264 | directive has the same requirements with respect to rules as <tt>gen_pt_node_d</tt> | |
265 | and <tt>gen_ast_node_d</tt> do. See the example file xml_grammar.hpp (in libs/spirit/example/application/xml | |
266 | directory) for example | |
267 | usage of <tt>no_node_d[]</tt>.</p> | |
268 | <a name="discard_node_d"></a> | |
269 | <h3>discard_node_d</h3> | |
270 | <p> This directive has a similar purpose to <tt>no_node_d</tt>, but works differently. | |
271 | It does not switch the scanner's match policy, so the enclosed parser still generates | |
272 | nodes. The generated nodes are discarded and do not appear in the tree. Using | |
273 | <tt>discard_node_d</tt> is slower than <tt>no_node_d</tt>, but it does not suffer | |
274 | from the drawback of having to specify a different rule type for any rule inside | |
275 | it.</p> | |
276 | <a name="leaf_node_d_token_node_d"></a> | |
277 | <h3>leaf_node_d/token_node_d</h3> | |
278 | <p> Both <tt>leaf_node_t</tt> and <tt>token_node_d</tt> work the same. They | |
279 | create a single node for the match generated by the enclosed parser. | |
280 | Unlike with earlier versions of Spirit, this directive is an implicit | |
281 | lexeme and alters the scanner (see | |
282 | <a href="faq.html#scanner_business">Scanner Business</a>). </p> | |
283 | <h3>reduced_node_d</h3> | |
284 | <p> This directive groups together all the nodes generated by the enclosed parser. | |
285 | For earlier versions of Spirit <tt>leaf_node_d</tt> and <tt>token_node_d</tt> | |
286 | were implemented this way. The new implementation of those directives is a | |
287 | lot faster, so <tt>reduced_node_d</tt> is primarily provided for portability | |
288 | and can be useful when using a custom node factory (see advanced tree | |
289 | generation, below).</p> | |
290 | <h3>infix_node_d</h3> | |
291 | <p> This is useful for removing separators from lists. It discards all the nodes | |
292 | in even positions. Thus this rule:</p> | |
293 | <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> | |
294 | <p> would discard all the comma nodes and keep all the integer nodes.</p> | |
295 | <a name="discard_first_node_d"></a> | |
296 | <h3>discard_first_node_d</h3> | |
297 | <p> This discards the first node generated.</p> | |
298 | <a name="discard_last_node_d"></a> | |
299 | <h3>discard_last_node_d</h3> | |
300 | <p> This discards the last node generated.</p> | |
301 | <a name="inner_node_d"></a> | |
302 | <h3>inner_node_d</h3> | |
303 | <p> This discards the first and last node generated.</p> | |
304 | <a name="root_node_d_and_ast_generation"></a> | |
305 | <h2>root_node_d and ast generation</h2> | |
306 | <p> The <tt>root_node_d</tt> directive is used to help out ast generation. It | |
307 | has no effect when generating a parse tree. When a parser is enclosed in <tt>root_node_d</tt>, | |
308 | the node it generates is marked as a root. This affects the way it is treated | |
309 | when it's added to the list of nodes being generated. Here's an example:</p> | |
310 | <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> | |
311 | <p> When parsing 5+6 the following tree will be generated:</p> | |
312 | <table border="0" align="center"> | |
313 | <tbody><tr> | |
314 | <td><img src="theme/trees3.png"></td> | |
315 | </tr> | |
316 | </tbody></table> | |
317 | <p> When parsing 1+2+3 the following will be generated:</p> | |
318 | <table border="0" align="center"> | |
319 | <tbody><tr> | |
320 | <td><img src="theme/trees4.png"></td> | |
321 | </tr> | |
322 | </tbody></table> | |
323 | <p> When a new node is created the following rules are used to determine how the | |
324 | tree will be generated:</p> | |
325 | <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> | |
326 | <p> After parsing leaves the current rule, the root node flag on the top node | |
327 | is turned off. This means that the root_node_d directive only affects the current | |
328 | rule.</p> | |
329 | <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> | |
330 | <a name="parse_tree_iterator"></a> | |
331 | <h2>parse_tree_iterator</h2> | |
332 | <p> The <tt>parse_tree_iterator</tt> class allows you to parse a tree using spirit. | |
333 | The class iterates over the tokens in the leaf nodes in the same order they | |
334 | were created. The <tt>parse_tree_iterator</tt> is templated on <tt>ParseTreeMatchT</tt>. | |
335 | It is constructed with a container of trees, and a position to start. Here is | |
336 | an example usage:</p> | |
337 | <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> | |
338 | <p> <a name="advanced_tree_generation"></a> | |
339 | </p> | |
340 | <h2>advanced tree generation</h2> | |
341 | <a name="node_value"></a> | |
342 | <h3>node value</h3> | |
343 | <p> The <tt>node_val_data</tt> can contain a value. By default it contains a <tt>void_t</tt>, | |
344 | which is an empty class. You can specify the type, using a template parameter, | |
345 | which will then be stored in every node. The type must be default constructible, | |
346 | and assignable. You can get and set the value using</p> | |
347 | <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> | |
348 | <p> and</p> | |
349 | <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> | |
350 | <p> To specify the value type, you must use a different <a href="#node_val_data">node_val_data | |
351 | </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>. | |
352 | <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> | |
353 | </p> | |
354 | <a name="access_node_d"></a> | |
355 | <h3>access_node_d</h3> | |
356 | <p> Now, you may be wondering, "What good does it do to have a value I can | |
357 | store in each node, but not to have any way of setting it?" Well, that's | |
358 | what <tt>access_node_d</tt> is for. <tt>access_node_d</tt> is a directive. It | |
359 | allows you to attach an action to it, like this:</p> | |
360 | <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> | |
361 | <p> The attached action will be passed 3 parameters: A reference to the root node | |
362 | of the tree generated by the parser, and the current first and last iterators. | |
363 | The action can set the value stored in the node.</p> | |
364 | <a name="tree_node_factories"></a> | |
365 | <h3>Tree node factories</h3> | |
366 | <p> By setting the factory, you can control what type of nodes are created and | |
367 | how they are created. There are 3 predefined factories: <tt>node_val_data_factory</tt>, | |
368 | <tt>node_all_val_data_factory</tt>, and <tt>node_iter_data_factory</tt>. You | |
369 | can also create your own factory to support your own node types.</p> | |
370 | <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> | |
371 | <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> | |
372 | <p> Instead, using the factory directly with rules is slightly harder because the | |
373 | factory is a template parameter to the scanner match policy, so you must use a | |
374 | custom scanner:</p> | |
375 | <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> | |
376 | <a name="node_val_data_factory"></a> | |
377 | <h3>node_val_data_factory</h3> | |
378 | <p> This is the default factory. It creates <tt>node_val_data</tt> nodes. Leaf | |
379 | nodes contain a copy of the matched text, and intermediate nodes don't. <tt>node_val_data_factory</tt> | |
380 | has one template parameter: <tt>ValueT</tt>. <tt>ValueT</tt> specifies the type | |
381 | of value that will be stored in the <tt>node_val_data</tt>.</p> | |
382 | <a name="node_all_val_data_factory"></a> | |
383 | <h3>node_all_val_data_factory</h3> | |
384 | <p> This factory also creates <tt>node_val_data</tt>. The difference between it | |
385 | and <tt>node_val_data_factory</tt> is that <b>every</b> node contains all the | |
386 | text that spans it. This means that the root node will contain a copy of the | |
387 | entire parsed input sequence. <tt>node_all_val_data_factory</tt> has one template | |
388 | parameter: <tt>ValueT</tt>. <tt>ValueT</tt> specifies the type of value that | |
389 | will be stored in the <tt>node_val_data</tt>.</p> | |
390 | <a name="node_iter_data_factory"></a> | |
391 | <h3>node_iter_data_factory</h3> | |
392 | <p> This factory creates the <tt>parse_tree_iter_node</tt>. This node stores iterators | |
393 | into the input sequence instead of making a copy. It can use a lot less memory. | |
394 | However, the input sequence must stay valid for the life of the tree, and it's | |
395 | not a good idea to use the <tt>multi_pass</tt> iterator with this type of node. | |
396 | All levels of the tree will contain a begin and end iterator. <tt>node_iter_data_factory</tt> | |
397 | has one template parameter: <tt>ValueT</tt>. <tt>ValueT</tt> specifies the type | |
398 | of value that will be stored in the node_val_data.</p> | |
399 | <a name="custom"></a> | |
400 | <h3>custom</h3> | |
401 | <p> You can create your own factory. It should look like this:</p> | |
402 | <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> | |
403 | </td> | |
404 | <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td> | |
405 | <td width="30"><a href="symbols.html"><img src="theme/l_arr.gif" border="0"></a></td> | |
406 | <td width="30"><a href="multi_pass.html"><img src="theme/r_arr.gif" border="0"></a></td> | |
407 | </tr> | |
408 | </tbody></table> | |
409 | <hr size="1"> | |
410 | <p class="copyright">Copyright © 2001-2002 Daniel C. Nuffer<br>Revised 2007 Copyright © Tobias Schwinger<br> | |
411 | <br> | |
412 | <font size="2">Use, modification and distribution is subject to the Boost Software | |
413 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
414 | http://www.boost.org/LICENSE_1_0.txt)</font></p> | |
415 | <p class="copyright"> </p> | |
416 | <br> | |
417 | </body></html> |