1 | <html> |
---|
2 | <head> |
---|
3 | <title>Debugging</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>Debugging</b></font> |
---|
14 | </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="position_iterator.html"><img src="theme/l_arr.gif" border="0"></a></td> |
---|
24 | <td width="30"><a href="error_handling.html"><img src="theme/r_arr.gif" border="0"></a></td> |
---|
25 | </tr> |
---|
26 | </table> |
---|
27 | <p>The top-down nature of Spirit makes the generated parser easy to micro- debug |
---|
28 | using the standard debugger bundled with the C++ compiler we are using. With |
---|
29 | recursive-descent, the parse traversal utilizes the hardware stack through C++ |
---|
30 | function call mechanisms. There are no difficult to debug tables or state machines |
---|
31 | that obscure the parsing logic flow. The stack trace we see in the debugger |
---|
32 | follows faithfully the hierarchical grammar structure.</p> |
---|
33 | <p> Since any production rule can initiate a parse traversal , it is a lot easier |
---|
34 | to pinpoint the bugs by focusing on one or a few rules. For relatively complex |
---|
35 | parsing tasks, the same way we write robust C++ programs, it is advisable to |
---|
36 | develop a grammar iteratively on a per-module basis where each module is a small |
---|
37 | subset of the complete grammar. That way, we can stress-test individual modules |
---|
38 | piecemeal until we reach the top-most module. For instance, when developing |
---|
39 | a scripting language, we can start with expressions, then move on to statements, |
---|
40 | then functions, upwards until we have a complete grammar. </p> |
---|
41 | <p> At some point when the grammar gets quite complicated, it is desirable to |
---|
42 | visualize the parse traversal and see what's happening. There are some facilities |
---|
43 | in the framework that aid in the visualisation of the parse traversal for the |
---|
44 | purpose of debugging. The following macros enable these features.</p> |
---|
45 | <a name="debugging_macros"></a> |
---|
46 | <h2>Debugging Macros</h2> |
---|
47 | <a name="spirit_assert_exception"></a> |
---|
48 | <h3>BOOST_SPIRIT_ASSERT_EXCEPTION</h3> |
---|
49 | <p> Spirit contains assertions that may activate when spirit is used incorrectly. |
---|
50 | By default these assertions use the assert macro from the standard library. |
---|
51 | If you want spirit to throw an exception instead, define <tt>BOOST_SPIRIT_ASSERT_EXCEPTION</tt> |
---|
52 | to the name of the class that you want to be thrown. This class's constructor |
---|
53 | will be passed a <tt>const char*</tt> stringified version of the file, line, |
---|
54 | and assertion condition, when it is thrown. If you want to totally disable the |
---|
55 | assertion, <tt>#define NDEBUG</tt>.</p> |
---|
56 | <a name="spirit_debug"></a> |
---|
57 | <h3>BOOST_SPIRIT_DEBUG</h3> |
---|
58 | <p>Define this to enable debugging.</p> |
---|
59 | <p>With debugging enabled, special output is generated at key points of the |
---|
60 | parse process, using the standard output operator (<tt><span class="keyword">operator</span><span class="special"><<</span></tt>) |
---|
61 | with <tt>BOOST_SPIRIT_DEBUG_OUT</tt> (default is <tt><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span></tt>, |
---|
62 | see below) as its left operand.</p> |
---|
63 | <table width="80%" border="0" align="center"> |
---|
64 | <tr> |
---|
65 | <td class="note_box"><img src="theme/note.gif"> In order to use spirit's |
---|
66 | debugging support you must ensure that appropriate overloads of |
---|
67 | <tt><span class="identifier">operator</span><span class="special"><<</span></tt> |
---|
68 | taking <tt>BOOST_SPIRIT_DEBUG_OUT</tt> as its left operand are available. |
---|
69 | The expected semantics are those of the standard output operator.<br> |
---|
70 | <br> |
---|
71 | These overloads may be provided either within the namespace where the |
---|
72 | corresponding class is declared (will be found through Argument Dependent Lookup) or [within an |
---|
73 | anonymous namespace] within <tt><span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span></tt>, |
---|
74 | so it is visible where it is called.<br> |
---|
75 | <br> |
---|
76 | <img src="theme/alert.gif"> Note in particular that when <tt>BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES</tt> |
---|
77 | is set, overloads of <tt><span class="identifier">operator</span><span class="special"><<</span></tt> |
---|
78 | taking instances of the types used in closures as their right operands are required.<br> |
---|
79 | <br> |
---|
80 | You may find an example of overloading the output operator for |
---|
81 | <tt><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span></tt> |
---|
82 | in a <a href="faq.html#output_operator">related FAQ entry</a>.</td> |
---|
83 | </tr> |
---|
84 | </table> |
---|
85 | |
---|
86 | <p>By default, if the <tt>BOOST_SPIRIT_DEBUG</tt> macro is defined, all available |
---|
87 | debug output is generated. To fine tune the amount of generated text you can |
---|
88 | define the <tt>BOOST_SPIRIT_DEBUG_FLAGS</tt> constant to be equal of a combination |
---|
89 | of the following flags:</p> |
---|
90 | <table width="90%" border="0" align="center"> |
---|
91 | <tr> |
---|
92 | <td colspan="2" class="table_title"><b>Available flags to fine tune debug |
---|
93 | output </b></td> |
---|
94 | </tr> |
---|
95 | <tr> |
---|
96 | <td width="29%" height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_NODES</tt></td> |
---|
97 | <td width="71%" class="table_cells"><p>print information about nodes (general |
---|
98 | for all parsers)</p></td> |
---|
99 | </tr> |
---|
100 | <tr> |
---|
101 | <td height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_TREES</tt></td> |
---|
102 | <td class="table_cells"><p>print information about parse trees and AST's (general |
---|
103 | for all tree parsers)</p></td> |
---|
104 | </tr> |
---|
105 | <tr> |
---|
106 | <td height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES</tt></td> |
---|
107 | <td class="table_cells">print information about closures (general for all |
---|
108 | parsers with closures)</td> |
---|
109 | </tr> |
---|
110 | <tr> |
---|
111 | <td height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_ESCAPE_CHAR</tt></td> |
---|
112 | <td class="table_cells"><p>print information out of the <tt>esc_char_parser</tt></p></td> |
---|
113 | </tr> |
---|
114 | <tr> |
---|
115 | <td height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_SLEX</tt></td> |
---|
116 | <td class="table_cells">print information out of the <tt>SLEX</tt> parser</td> |
---|
117 | </tr> |
---|
118 | </table> |
---|
119 | <p><a name="spirit_debug_out"></a> </p> |
---|
120 | <h3>BOOST_SPIRIT_DEBUG_OUT</h3> |
---|
121 | <p> Define this to redirect the debugging diagnostics printout to somewhere else |
---|
122 | (e.g. a file or stream). Defaults to <tt>std::cout</tt>.</p> |
---|
123 | <a name="spirit_debug_token printer"></a> |
---|
124 | <h3>BOOST_SPIRIT_DEBUG_TOKEN_PRINTER</h3> |
---|
125 | <p> The <tt>BOOST_SPIRIT_DEBUG_TOKEN_PRINTER</tt> macro allows you to redefine the way characters are printed on the stream. </p> |
---|
126 | <p>If <tt>BOOST_SPIRIT_DEBUG_OUT</tt> is of type <tt>StreamT</tt>, the character type is <tt>CharT</tt> and <tt>BOOST_SPIRIT_DEBUG_TOKEN_PRINTER</tt> is |
---|
127 | defined to <tt>foo</tt>, it must be compatible with this usage:</p> |
---|
128 | <pre><code><span class=identifier> foo</span><span class=special>(</span><span class=identifier>StreamT</span><span class=special>, </span><span class=identifier>CharT</span><span class=special>)</span></code></pre> |
---|
129 | <p>The default printer requires <tt>operator<<(StreamT, CharT)</tt> to |
---|
130 | be defined. Additionaly, if <tt>CharT</tt> is convertible to a normal character |
---|
131 | type (<tt>char</tt>, <tt>wchar_t</tt> or <tt>int</tt>), it prints control |
---|
132 | characters in a friendly manner (e.g., when it receives <span class=special>'\n'</span> it |
---|
133 | actually prints the <span class=special>\</span> and <span class=special>n</span> charactes, |
---|
134 | instead of a newline).</p> |
---|
135 | <a name="spirit_debug_print_some"></a> |
---|
136 | <h3>BOOST_SPIRIT_DEBUG_PRINT_SOME</h3> |
---|
137 | <p> The <tt>BOOST_SPIRIT_DEBUG_PRINT_SOME</tt> constant defines the number of |
---|
138 | characters from the stream to be printed for diagnosis. This defaults to the |
---|
139 | first 20 characters.</p> |
---|
140 | <p><a name="spirit_debug_tracenode"></a> </p> |
---|
141 | <h3>BOOST_SPIRIT_DEBUG_TRACENODE</h3> |
---|
142 | <p> By default all parser nodes are traced. This constant may be used to redefine |
---|
143 | this default. If this is <tt>1</tt> (<tt>true</tt>), then tracing is enabled |
---|
144 | by default, if this constant is <tt>0</tt> (<tt>false</tt>), the tracing is |
---|
145 | disabled by default. This preprocessor constant is set to <tt>1 </tt>(<tt>true</tt>) |
---|
146 | by default.</p> |
---|
147 | <p>Please note, that the following <tt>BOOST_SPIRIT_DEBUG_...() </tt>macros are |
---|
148 | to be used at function scope only.</p> |
---|
149 | <a name="spirit_debug_node_p_"></a> |
---|
150 | <h3>BOOST_SPIRIT_DEBUG_NODE(p)</h3> |
---|
151 | <p> Define this to print some debugging diagnostics for parser p. This macro</p> |
---|
152 | <ul> |
---|
153 | <li>Registers the parser name for debugging</li> |
---|
154 | <li>Enables/disables the tracing for parser depending on <tt>BOOST_SPIRIT_DEBUG_TRACENODE</tt></li> |
---|
155 | </ul> |
---|
156 | <p> <b>Pre-parse</b>: Before entering the rule, the rule name followed by a peek |
---|
157 | into the data at the current iterator position is printed.</p> |
---|
158 | <p> <b>Post-parse</b>: After parsing the rule, the rule name followed by a peek |
---|
159 | into the data at the current iterator position is printed. Here, <tt>'/'</tt> |
---|
160 | before the rule name flags a succesful match while <tt>'#'</tt> before the rule |
---|
161 | name flags an unsuccesful match.</p> |
---|
162 | <p> The following are synonyms for <tt>BOOST_SPIRIT_DEBUG_NODE</tt></p> |
---|
163 | <ol> |
---|
164 | <li>BOOST_SPIRIT_DEBUG_RULE</li> |
---|
165 | <li>BOOST_SPIRIT_DEBUG_GRAMMAR</li> |
---|
166 | </ol> |
---|
167 | <a name="spirit_trace_node_p__flag_"></a> |
---|
168 | <h3>BOOST_SPIRIT_DEBUG_TRACE_NODE(p, flag)</h3> |
---|
169 | <p> Similar to <tt>BOOST_SPIRIT_DEBUG_NODE</tt>. Additionally allows selective debugging. |
---|
170 | This is useful in situations where we want to debug just a hand picked set of |
---|
171 | nodes.</p> |
---|
172 | <p> The following are synonyms for <tt>BOOST_SPIRIT_DEBUG_TRACE_NODE</tt></p> |
---|
173 | <ol> |
---|
174 | <li>BOOST_SPIRIT_DEBUG_TRACE_RULE</li> |
---|
175 | <li>BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR</li> |
---|
176 | </ol> |
---|
177 | <p><a name="spirit_trace_node_p__flag__name_"></a> </p> |
---|
178 | <h3>BOOST_SPIRIT_DEBUG_TRACE_NODE_NAME(p, name, flag)</h3> |
---|
179 | <p> Similar to <tt>BOOST_SPIRIT_DEBUG_NODE</tt>. Additionally allows selective |
---|
180 | debugging and allows to specify the name used during debug printout. This is |
---|
181 | useful in situations where we want to debug just a hand picked set of nodes. |
---|
182 | The <tt>name</tt> may be redefined in situations, where the parser parameter does not reflect the name of the parser to debug.</p> |
---|
183 | <p> The following are synonyms for <tt>BOOST_SPIRIT_DEBUG_TRACE_NODE</tt></p> |
---|
184 | <ol> |
---|
185 | <li>BOOST_SPIRIT_DEBUG_TRACE_RULE_NAME</li> |
---|
186 | <li>BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME</li> |
---|
187 | </ol> |
---|
188 | <hr> |
---|
189 | <p>Here's the original calculator with debugging features enabled:</p> |
---|
190 | <pre> |
---|
191 | <code><span class=preprocessor>#define </span><span class=identifier>BOOST_SPIRIT_DEBUG </span><span class=comment>///$$$ DEFINE THIS BEFORE ANYTHING ELSE $$$/// |
---|
192 | </span><span class=preprocessor>#include </span><span class=string>"boost/spirit.hpp" |
---|
193 | |
---|
194 | </span><span class=comment>/***/ |
---|
195 | |
---|
196 | /*** CALCULATOR GRAMMAR DEFINITIONS HERE ***/ |
---|
197 | |
---|
198 | </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>integer</span><span class=special>); |
---|
199 | </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>group</span><span class=special>); |
---|
200 | </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>factor</span><span class=special>); |
---|
201 | </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>term</span><span class=special>); |
---|
202 | </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>expr</span><span class=special>); |
---|
203 | </span></code></pre> |
---|
204 | <p> <img src="theme/note.gif" width="16" height="16"> Be sure to add the macros <strong>inside</strong> the grammar definition's constructor. Now here's a sample session with the calculator.</p> |
---|
205 | |
---|
206 | <pre><code> <span class="preprocessor">Type an expression...or [q or Q] to quit</span> |
---|
207 | |
---|
208 | <span class="preprocessor">1 + 2</span> |
---|
209 | |
---|
210 | grammar(calc): "1 + 2" |
---|
211 | rule(expression): "1 + 2" |
---|
212 | rule(term): "1 + 2" |
---|
213 | rule(factor): "1 + 2" |
---|
214 | rule(integer): "1 + 2" |
---|
215 | <span class="preprocessor">push 1</span> |
---|
216 | /rule(integer): " + 2" |
---|
217 | /rule(factor): " + 2" |
---|
218 | /rule(term): " + 2" |
---|
219 | rule(term): "2" |
---|
220 | rule(factor): "2" |
---|
221 | rule(integer): "2" |
---|
222 | <span class="preprocessor">push 2</span> |
---|
223 | /rule(integer): "" |
---|
224 | /rule(factor): "" |
---|
225 | /rule(term): "" |
---|
226 | <span class="preprocessor">popped 1 and 2 from the stack. pushing 3 onto the stack.</span> |
---|
227 | /rule(expression): "" |
---|
228 | /grammar(calc): "" |
---|
229 | <span class="preprocessor">------------------------- |
---|
230 | Parsing succeeded |
---|
231 | result = 3 |
---|
232 | -------------------------</span></code></pre> |
---|
233 | |
---|
234 | <p> We typed in "1 + 2". Notice that there are two successful branches |
---|
235 | from the top rule <tt>expr</tt>. The text in red is generated by the parser's |
---|
236 | semantic actions while the others are generated by the debug-diagnostics of |
---|
237 | our rules. Notice how the first <tt>integer</tt> rule took "1", the |
---|
238 | first <tt>term</tt> rule took "+" and finally the second <tt>integer</tt> |
---|
239 | rule took "2".</p> |
---|
240 | <p>Please note the special meaning of the first characters appearing on the printed |
---|
241 | lines:</p> |
---|
242 | <ul> |
---|
243 | <li>a single <span class="literal">'/'</span> starts a line containing the information |
---|
244 | about a successfully matched parser node (<tt>rule<></tt>, <tt>grammar<></tt> |
---|
245 | or <tt>subrule<></tt>)</li> |
---|
246 | <li>a single <span class="literal">'#'</span> starts a line containing the information |
---|
247 | about a failed parser node</li> |
---|
248 | <li>a single <span class="literal">'^'</span> starts a line containing the first member (return value/synthesised |
---|
249 | attribute) of the closure of a successfully matched parser node.</li> |
---|
250 | </ul> |
---|
251 | <p>Check out <a href="../example/fundamental/calc_debug.cpp">calc_debug.cpp</a> to see debugging in action. </p> |
---|
252 | <table border="0"> |
---|
253 | <tr> |
---|
254 | <td width="10"></td> |
---|
255 | <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td> |
---|
256 | <td width="30"><a href="position_iterator.html"><img src="theme/l_arr.gif" border="0"></a></td> |
---|
257 | <td width="30"><a href="error_handling.html"><img src="theme/r_arr.gif" border="0"></a></td> |
---|
258 | </tr> |
---|
259 | </table> |
---|
260 | <br> |
---|
261 | <hr size="1"> |
---|
262 | <p class="copyright">Copyright © 1998-2003 Joel de Guzman<br> |
---|
263 | Copyright © 2003 Hartmut Kaiser<br> |
---|
264 | <br> |
---|
265 | <font size="2">Use, modification and distribution is subject to the Boost Software |
---|
266 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
267 | http://www.boost.org/LICENSE_1_0.txt)</font></p> |
---|
268 | <p class="copyright"> </p> |
---|
269 | </body> |
---|
270 | </html> |
---|