]>
Commit | Line | Data |
---|---|---|
1 | <html> | |
2 | <head> | |
3 | <title>Parametric Parsers</title> | |
4 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | |
5 | <link rel="stylesheet" href="theme/style.css" type="text/css"> | |
6 | </head> | |
7 | ||
8 | <body> | |
9 | <table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2"> | |
10 | <tr> | |
11 | <td width="10"> | |
12 | </td> | |
13 | <td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Parametric | |
14 | Parsers</b></font> </td> | |
15 | <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td> | |
16 | </tr> | |
17 | </table> | |
18 | <br> | |
19 | <table border="0"> | |
20 | <tr> | |
21 | <td width="10"></td> | |
22 | <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td> | |
23 | <td width="30"><a href="predefined_actors.html"><img src="theme/l_arr.gif" border="0"></a></td> | |
24 | <td width="30"><a href="functional.html"><img src="theme/r_arr.gif" border="0"></a></td> | |
25 | </tr> | |
26 | </table> | |
27 | <p>We already have a hint of the dynamic nature of the Spirit framework. This | |
28 | capability is fundamental to Spirit. Dynamic parsing is a very powerful concept. | |
29 | We shall take this concept further through run-time parametric parsers. We are | |
30 | able to handle parsing tasks that are impossible to do with any EBNF syntax | |
31 | alone.</p> | |
32 | <h2>A Little Secret</h2> | |
33 | <p> A little critter called <tt>boost::ref</tt> lurking in the boost distribution | |
34 | is quite powerful beast when used with Spirit's primitive parsers. We are used | |
35 | to seeing the Spirit primitive parsers created with string or character literals | |
36 | such as:</p> | |
37 | <pre> | |
38 | <code><span class=identifier>ch_p</span><span class=special>(</span><span class=literal>'A'</span><span class=special>) | |
39 | </span><span class=identifier>range_p</span><span class=special>(</span><span class=literal>'A'</span><span class=special>, </span><span class=literal>'Z'</span><span class=special>) | |
40 | </span><span class=identifier>str_p</span><span class=special>(</span><span class=string>"Hello World"</span><span class=special>)</span></code></pre> | |
41 | <p> str_p has a second form that accepts two iterators over the string:</p> | |
42 | <pre> | |
43 | <code><span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>first </span><span class=special>= </span><span class=string>"My oh my"</span><span class=special>; | |
44 | </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>last </span><span class=special>= </span><span class=identifier>first </span><span class=special>+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>strlen</span><span class=special>(</span><span class=identifier>first</span><span class=special>); | |
45 | ||
46 | </span><span class=identifier>str_p</span><span class=special>(</span><span class=identifier>first</span><span class=special>, </span><span class=identifier>last</span><span class=special>)</span></code></pre> | |
47 | <p> What is not obvious is that we can use <tt>boost::ref</tt> as well:</p> | |
48 | <pre> | |
49 | <code><span class=keyword>char </span><span class=identifier>ch </span><span class=special>= </span><span class=literal>'A'</span><span class=special>; | |
50 | </span><span class=keyword>char </span><span class=identifier>from </span><span class=special>= </span><span class=literal>'A'</span><span class=special>; | |
51 | </span><span class=keyword>char </span><span class=identifier>to </span><span class=special>= </span><span class=literal>'Z'</span><span class=special>; | |
52 | ||
53 | </span><span class=identifier>ch_p</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>ref</span><span class=special>(</span><span class=identifier>ch</span><span class=special>)) | |
54 | </span><span class=identifier>range_p</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>ref</span><span class=special>(</span><span class=identifier>from</span><span class=special>), </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>ref</span><span class=special>(</span><span class=identifier>to</span><span class=special>))</span></code></pre> | |
55 | <p> When <tt>boost::ref</tt> is used, the actual parameters to <tt>ch_p</tt> and | |
56 | <tt>range_p</tt> are held by reference. This means that we can change the values | |
57 | of <tt>ch</tt>, <tt>from</tt> and <tt>to</tt> anytime and the corresponding | |
58 | <tt>ch_p</tt> and <tt>range_p</tt> parser will follow their dynamic values. | |
59 | Of course, since they are held by reference, you must make sure that the referenced | |
60 | object is not destructed while parsing.</p> | |
61 | <p> What about <tt>str_p</tt>?</p> | |
62 | <p> While the first form of <tt>str_p</tt> (the single argument form) is reserved | |
63 | for null terminated string constants, the second form (the two argument first/last | |
64 | iterator form) may be used:</p> | |
65 | <pre> | |
66 | <code><span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>first </span><span class=special>= </span><span class=string>"My oh my"</span><span class=special>; | |
67 | </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>last </span><span class=special>= </span><span class=identifier>first </span><span class=special>+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>strlen</span><span class=special>(</span><span class=identifier>first</span><span class=special>); | |
68 | ||
69 | </span><span class=identifier>str_p</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>ref</span><span class=special>(</span><span class=identifier>first</span><span class=special>), </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>ref</span><span class=special>(</span><span class=identifier>last</span><span class=special>))</span></code></pre> | |
70 | <table width="80%" border="0" align="center"> | |
71 | <tr> | |
72 | <td class="note_box"> <img src="theme/note.gif" width="16" height="16"> Hey, | |
73 | don't forget <tt>chseq_p</tt>. All these apply to this seldom used primitive | |
74 | as well. </td> | |
75 | </tr> | |
76 | </table> | |
77 | <h2>Functional Parametric Primitives</h2> | |
78 | <pre> <span class="preprocessor">#include</span> <span class="special"><</span>boost<span class="special">/</span>spirit<span class="special">/</span>attribute<span class="special">/</span><span class="identifier">parametric</span><span class="special">.</span>hpp<span class="special">></span></pre> | |
79 | <p> Taking this further, Spirit includes functional versions of the primitives. | |
80 | Rather than taking in characters, strings or references to characters and strings | |
81 | (using boost::ref), the functional versions take in functions or functors.</p> | |
82 | <h3>f_chlit and f_ch_p</h3> | |
83 | <p> The functional version of <tt>chlit</tt>. This parser takes in a function | |
84 | or functor (function object). The function is expected to have an interface | |
85 | compatible with:</p> | |
86 | <pre> | |
87 | <code><span class=identifier>CharT </span><span class=identifier>func</span><span class=special>()</span></code></pre> | |
88 | <p> where CharT is the character type (e.g. <tt>char</tt>, <tt>int</tt>, <tt>wchar_t</tt>).</p> | |
89 | <p> The functor is expected to have an interface compatible with:</p> | |
90 | <pre> | |
91 | <code><span class=keyword>struct </span><span class=identifier>functor | |
92 | </span><span class=special>{ | |
93 | </span><span class=identifier>CharT </span><span class=keyword>operator</span><span class=special>()() </span><span class=keyword>const</span><span class=special>; | |
94 | </span><span class=special>};</span></code></pre> | |
95 | <p> where CharT is the character type (e.g. <tt>char</tt>, <tt>int</tt>, <tt>wchar_t</tt>).</p> | |
96 | <p> Here's a contrived example:</p> | |
97 | <pre> | |
98 | <code><span class=keyword>struct </span><span class=identifier>X | |
99 | </span><span class=special>{ | |
100 | </span><span class=keyword>char </span><span class=keyword>operator</span><span class=special>()() </span><span class=keyword>const | |
101 | </span><span class=special>{ | |
102 | </span><span class=keyword>return </span><span class=literal>'X'</span><span class=special>; </span><span class=special> | |
103 | } | |
104 | </span><span class=special>};</span></code></pre> | |
105 | <p> Now we can use X to create our f_chlit parser:</p> | |
106 | <pre> | |
107 | <code><span class=identifier>f_ch_p</span><span class=special>(</span><span class=identifier>X</span><span class=special>())</span></code></pre> | |
108 | <h3>f_range and f_range_p</h3> | |
109 | <p> The functional version of <tt>range</tt>. This parser takes in a function | |
110 | or functor compatible with the interfaces above. The difference is that <tt>f_range</tt> | |
111 | (and <tt>f_range_p</tt>) expects two functors. One for the start and one for | |
112 | the end of the range.</p> | |
113 | <h3>f_chseq and f_chseq_p</h3> | |
114 | <p> The functional version of <tt>chseq</tt>. This parser takes in two functions | |
115 | or functors. One for the begin iterator and one for the end iterator. The function | |
116 | is expected to have an interface compatible with:</p> | |
117 | <pre> | |
118 | <code><span class=identifier>IteratorT </span><span class=identifier>func</span><span class=special>()</span></code></pre> | |
119 | <p> where <tt>IteratorT</tt> is the iterator type (e.g. <tt>char const*</tt>, | |
120 | <tt>wchar_t const*</tt>).</p> | |
121 | <p> The functor is expected to have an interface compatible with:</p> | |
122 | <pre> | |
123 | <code><span class=keyword>struct </span><span class=identifier>functor | |
124 | </span><span class=special>{ | |
125 | </span><span class=identifier>IteratorT </span><span class=keyword>operator</span><span class=special>()() </span><span class=keyword>const</span><span class=special>; | |
126 | </span><span class=special>};</span></code></pre> | |
127 | <p> where <tt>IteratorT</tt> is the iterator type (e.g. <tt>char const*</tt>, | |
128 | <tt>wchar_t const*</tt>).</p> | |
129 | <h3>f_strlit and f_str_p</h3> | |
130 | <p> The functional version of <tt>strlit</tt>. This parser takes in two functions | |
131 | or functors compatible with the interfaces that <tt>f_chseq</tt> expects.</p> | |
132 | <table border="0"> | |
133 | <tr> | |
134 | <td width="10"></td> | |
135 | <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td> | |
136 | <td width="30"><a href="predefined_actors.html"><img src="theme/l_arr.gif" border="0"></a></td> | |
137 | <td width="30"><a href="functional.html"><img src="theme/r_arr.gif" border="0"></a></td> | |
138 | </tr> | |
139 | </table> | |
140 | <br> | |
141 | <hr size="1"> | |
142 | <p class="copyright">Copyright © 1998-2003 Joel de Guzman<br> | |
143 | <br> | |
144 | <font size="2">Use, modification and distribution is subject to the Boost Software | |
145 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
146 | http://www.boost.org/LICENSE_1_0.txt)</font></p> | |
147 | <p class="copyright"> </p> | |
148 | </body> | |
149 | </html> |