123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- <html>
- <head>
- <title>Debugging</title>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <link rel="stylesheet" href="theme/style.css" type="text/css">
- </head>
- <body>
- <table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2">
- <tr>
- <td width="10">
- </td>
- <td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Debugging</b></font>
- </td>
- <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td>
- </tr>
- </table>
- <br>
- <table border="0">
- <tr>
- <td width="10"></td>
- <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
- <td width="30"><a href="position_iterator.html"><img src="theme/l_arr.gif" border="0"></a></td>
- <td width="30"><a href="error_handling.html"><img src="theme/r_arr.gif" border="0"></a></td>
- </tr>
- </table>
- <p>The top-down nature of Spirit makes the generated parser easy to micro- debug
- using the standard debugger bundled with the C++ compiler we are using. With
- recursive-descent, the parse traversal utilizes the hardware stack through C++
- function call mechanisms. There are no difficult to debug tables or state machines
- that obscure the parsing logic flow. The stack trace we see in the debugger
- follows faithfully the hierarchical grammar structure.</p>
- <p> Since any production rule can initiate a parse traversal , it is a lot easier
- to pinpoint the bugs by focusing on one or a few rules. For relatively complex
- parsing tasks, the same way we write robust C++ programs, it is advisable to
- develop a grammar iteratively on a per-module basis where each module is a small
- subset of the complete grammar. That way, we can stress-test individual modules
- piecemeal until we reach the top-most module. For instance, when developing
- a scripting language, we can start with expressions, then move on to statements,
- then functions, upwards until we have a complete grammar. </p>
- <p> At some point when the grammar gets quite complicated, it is desirable to
- visualize the parse traversal and see what's happening. There are some facilities
- in the framework that aid in the visualisation of the parse traversal for the
- purpose of debugging. The following macros enable these features.</p>
- <a name="debugging_macros"></a>
- <h2>Debugging Macros</h2>
- <a name="spirit_assert_exception"></a>
- <h3>BOOST_SPIRIT_ASSERT_EXCEPTION</h3>
- <p> Spirit contains assertions that may activate when spirit is used incorrectly.
- By default these assertions use the assert macro from the standard library.
- If you want spirit to throw an exception instead, define <tt>BOOST_SPIRIT_ASSERT_EXCEPTION</tt>
- to the name of the class that you want to be thrown. This class's constructor
- will be passed a <tt>const char*</tt> stringified version of the file, line,
- and assertion condition, when it is thrown. If you want to totally disable the
- assertion, <tt>#define NDEBUG</tt>.</p>
- <a name="spirit_debug"></a>
- <h3>BOOST_SPIRIT_DEBUG</h3>
- <p>Define this to enable debugging.</p>
- <p>With debugging enabled, special output is generated at key points of the
- parse process, using the standard output operator (<tt><span class="keyword">operator</span><span class="special"><<</span></tt>)
- 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>,
- see below) as its left operand.</p>
- <table width="80%" border="0" align="center">
- <tr>
- <td class="note_box"><img src="theme/note.gif"> In order to use spirit's
- debugging support you must ensure that appropriate overloads of
- <tt><span class="identifier">operator</span><span class="special"><<</span></tt>
- taking <tt>BOOST_SPIRIT_DEBUG_OUT</tt> as its left operand are available.
- The expected semantics are those of the standard output operator.<br>
- <br>
- These overloads may be provided either within the namespace where the
- corresponding class is declared (will be found through Argument Dependent Lookup) or [within an
- anonymous namespace] within <tt><span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span></tt>,
- so it is visible where it is called.<br>
- <br>
- <img src="theme/alert.gif"> Note in particular that when <tt>BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES</tt>
- is set, overloads of <tt><span class="identifier">operator</span><span class="special"><<</span></tt>
- taking instances of the types used in closures as their right operands are required.<br>
- <br>
- You may find an example of overloading the output operator for
- <tt><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span></tt>
- in a <a href="faq.html#output_operator">related FAQ entry</a>.</td>
- </tr>
- </table>
- <p>By default, if the <tt>BOOST_SPIRIT_DEBUG</tt> macro is defined, all available
- debug output is generated. To fine tune the amount of generated text you can
- define the <tt>BOOST_SPIRIT_DEBUG_FLAGS</tt> constant to be equal of a combination
- of the following flags:</p>
- <table width="90%" border="0" align="center">
- <tr>
- <td colspan="2" class="table_title"><b>Available flags to fine tune debug
- output </b></td>
- </tr>
- <tr>
- <td width="29%" height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_NODES</tt></td>
- <td width="71%" class="table_cells"><p>print information about nodes (general
- for all parsers)</p></td>
- </tr>
- <tr>
- <td height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_TREES</tt></td>
- <td class="table_cells"><p>print information about parse trees and AST's (general
- for all tree parsers)</p></td>
- </tr>
- <tr>
- <td height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES</tt></td>
- <td class="table_cells">print information about closures (general for all
- parsers with closures)</td>
- </tr>
- <tr>
- <td height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_ESCAPE_CHAR</tt></td>
- <td class="table_cells"><p>print information out of the <tt>esc_char_parser</tt></p></td>
- </tr>
- <tr>
- <td height="27" class="table_cells"><tt>BOOST_SPIRIT_DEBUG_FLAGS_SLEX</tt></td>
- <td class="table_cells">print information out of the <tt>SLEX</tt> parser</td>
- </tr>
- </table>
- <p><a name="spirit_debug_out"></a> </p>
- <h3>BOOST_SPIRIT_DEBUG_OUT</h3>
- <p> Define this to redirect the debugging diagnostics printout to somewhere else
- (e.g. a file or stream). Defaults to <tt>std::cout</tt>.</p>
- <a name="spirit_debug_token printer"></a>
- <h3>BOOST_SPIRIT_DEBUG_TOKEN_PRINTER</h3>
- <p> The <tt>BOOST_SPIRIT_DEBUG_TOKEN_PRINTER</tt> macro allows you to redefine the way characters are printed on the stream. </p>
- <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
- defined to <tt>foo</tt>, it must be compatible with this usage:</p>
- <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>
- <p>The default printer requires <tt>operator<<(StreamT, CharT)</tt> to
- be defined. Additionaly, if <tt>CharT</tt> is convertible to a normal character
- type (<tt>char</tt>, <tt>wchar_t</tt> or <tt>int</tt>), it prints control
- characters in a friendly manner (e.g., when it receives <span class=special>'\n'</span> it
- actually prints the <span class=special>\</span> and <span class=special>n</span> charactes,
- instead of a newline).</p>
- <a name="spirit_debug_print_some"></a>
- <h3>BOOST_SPIRIT_DEBUG_PRINT_SOME</h3>
- <p> The <tt>BOOST_SPIRIT_DEBUG_PRINT_SOME</tt> constant defines the number of
- characters from the stream to be printed for diagnosis. This defaults to the
- first 20 characters.</p>
- <p><a name="spirit_debug_tracenode"></a> </p>
- <h3>BOOST_SPIRIT_DEBUG_TRACENODE</h3>
- <p> By default all parser nodes are traced. This constant may be used to redefine
- this default. If this is <tt>1</tt> (<tt>true</tt>), then tracing is enabled
- by default, if this constant is <tt>0</tt> (<tt>false</tt>), the tracing is
- disabled by default. This preprocessor constant is set to <tt>1 </tt>(<tt>true</tt>)
- by default.</p>
- <p>Please note, that the following <tt>BOOST_SPIRIT_DEBUG_...() </tt>macros are
- to be used at function scope only.</p>
- <a name="spirit_debug_node_p_"></a>
- <h3>BOOST_SPIRIT_DEBUG_NODE(p)</h3>
- <p> Define this to print some debugging diagnostics for parser p. This macro</p>
- <ul>
- <li>Registers the parser name for debugging</li>
- <li>Enables/disables the tracing for parser depending on <tt>BOOST_SPIRIT_DEBUG_TRACENODE</tt></li>
- </ul>
- <p> <b>Pre-parse</b>: Before entering the rule, the rule name followed by a peek
- into the data at the current iterator position is printed.</p>
- <p> <b>Post-parse</b>: After parsing the rule, the rule name followed by a peek
- into the data at the current iterator position is printed. Here, <tt>'/'</tt>
- before the rule name flags a succesful match while <tt>'#'</tt> before the rule
- name flags an unsuccesful match.</p>
- <p> The following are synonyms for <tt>BOOST_SPIRIT_DEBUG_NODE</tt></p>
- <ol>
- <li>BOOST_SPIRIT_DEBUG_RULE</li>
- <li>BOOST_SPIRIT_DEBUG_GRAMMAR</li>
- </ol>
- <a name="spirit_trace_node_p__flag_"></a>
- <h3>BOOST_SPIRIT_DEBUG_TRACE_NODE(p, flag)</h3>
- <p> Similar to <tt>BOOST_SPIRIT_DEBUG_NODE</tt>. Additionally allows selective debugging.
- This is useful in situations where we want to debug just a hand picked set of
- nodes.</p>
- <p> The following are synonyms for <tt>BOOST_SPIRIT_DEBUG_TRACE_NODE</tt></p>
- <ol>
- <li>BOOST_SPIRIT_DEBUG_TRACE_RULE</li>
- <li>BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR</li>
- </ol>
- <p><a name="spirit_trace_node_p__flag__name_"></a> </p>
- <h3>BOOST_SPIRIT_DEBUG_TRACE_NODE_NAME(p, name, flag)</h3>
- <p> Similar to <tt>BOOST_SPIRIT_DEBUG_NODE</tt>. Additionally allows selective
- debugging and allows to specify the name used during debug printout. This is
- useful in situations where we want to debug just a hand picked set of nodes.
- The <tt>name</tt> may be redefined in situations, where the parser parameter does not reflect the name of the parser to debug.</p>
- <p> The following are synonyms for <tt>BOOST_SPIRIT_DEBUG_TRACE_NODE</tt></p>
- <ol>
- <li>BOOST_SPIRIT_DEBUG_TRACE_RULE_NAME</li>
- <li>BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME</li>
- </ol>
- <hr>
- <p>Here's the original calculator with debugging features enabled:</p>
- <pre>
- <code><span class=preprocessor>#define </span><span class=identifier>BOOST_SPIRIT_DEBUG </span><span class=comment>///$$$ DEFINE THIS BEFORE ANYTHING ELSE $$$///
- </span><span class=preprocessor>#include </span><span class=string>"boost/spirit/include/classic.hpp"
- </span><span class=comment>/***/
- /*** CALCULATOR GRAMMAR DEFINITIONS HERE ***/
- </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>integer</span><span class=special>);
- </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>group</span><span class=special>);
- </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>factor</span><span class=special>);
- </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>term</span><span class=special>);
- </span><span class=identifier>BOOST_SPIRIT_DEBUG_RULE</span><span class=special>(</span><span class=identifier>expr</span><span class=special>);
- </span></code></pre>
- <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>
- <pre><code> <span class="preprocessor">Type an expression...or [q or Q] to quit</span>
- <span class="preprocessor">1 + 2</span>
- grammar(calc): "1 + 2"
- rule(expression): "1 + 2"
- rule(term): "1 + 2"
- rule(factor): "1 + 2"
- rule(integer): "1 + 2"
- <span class="preprocessor">push 1</span>
- /rule(integer): " + 2"
- /rule(factor): " + 2"
- /rule(term): " + 2"
- rule(term): "2"
- rule(factor): "2"
- rule(integer): "2"
- <span class="preprocessor">push 2</span>
- /rule(integer): ""
- /rule(factor): ""
- /rule(term): ""
- <span class="preprocessor">popped 1 and 2 from the stack. pushing 3 onto the stack.</span>
- /rule(expression): ""
- /grammar(calc): ""
- <span class="preprocessor">-------------------------
- Parsing succeeded
- result = 3
- -------------------------</span></code></pre>
- <p> We typed in "1 + 2". Notice that there are two successful branches
- from the top rule <tt>expr</tt>. The text in red is generated by the parser's
- semantic actions while the others are generated by the debug-diagnostics of
- our rules. Notice how the first <tt>integer</tt> rule took "1", the
- first <tt>term</tt> rule took "+" and finally the second <tt>integer</tt>
- rule took "2".</p>
- <p>Please note the special meaning of the first characters appearing on the printed
- lines:</p>
- <ul>
- <li>a single <span class="literal">'/'</span> starts a line containing the information
- about a successfully matched parser node (<tt>rule<></tt>, <tt>grammar<></tt>
- or <tt>subrule<></tt>)</li>
- <li>a single <span class="literal">'#'</span> starts a line containing the information
- about a failed parser node</li>
- <li>a single <span class="literal">'^'</span> starts a line containing the first member (return value/synthesised
- attribute) of the closure of a successfully matched parser node.</li>
- </ul>
- <p>Check out <a href="../example/fundamental/calc_debug.cpp">calc_debug.cpp</a> to see debugging in action. </p>
- <table border="0">
- <tr>
- <td width="10"></td>
- <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
- <td width="30"><a href="position_iterator.html"><img src="theme/l_arr.gif" border="0"></a></td>
- <td width="30"><a href="error_handling.html"><img src="theme/r_arr.gif" border="0"></a></td>
- </tr>
- </table>
- <br>
- <hr size="1">
- <p class="copyright">Copyright © 1998-2003 Joel de Guzman<br>
- Copyright © 2003 Hartmut Kaiser<br>
- <br>
- <font size="2">Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)</font></p>
- <p class="copyright"> </p>
- </body>
- </html>
|