error_handling.html 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <html>
  2. <head>
  3. <title>Error Handling</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. <body>
  8. <table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2">
  9. <tr>
  10. <td width="10">
  11. </td>
  12. <td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Error
  13. Handling </b></font></td>
  14. <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td>
  15. </tr>
  16. </table>
  17. <br>
  18. <table border="0">
  19. <tr>
  20. <td width="10"></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="debugging.html"><img src="theme/l_arr.gif" border="0"></a></td>
  23. <td width="30"><a href="quickref.html"><img src="theme/r_arr.gif" border="0"></a></td>
  24. </tr>
  25. </table>
  26. <p>C++'s exception handling mechanism is a perfect match for error handling in
  27. the framework. Imagine a complete parser as a maze. At each branch, the input
  28. dictates where we will turn. Given an erroneous input, we may reach a dead end.
  29. If we ever reach one, it would be a waste of time to backtrack from where we
  30. came from. Instead, we supply guards in strategic points. Beyond a certain point,
  31. we put put parser assertions in places where one is not allowed to go. </p>
  32. <p>The assertions are like springs that catapult us back to the guard. If we ever
  33. reach a brick wall given a specific input pattern, everything unwinds quickly
  34. and we are thrown right back to the guard. This can be a very effective optimization
  35. when used wisely. Right back at the guard, we have a chance to correct the situation,
  36. if possible. The following illustration depicts the scenario.</p>
  37. <table border="0" align="center">
  38. <tr>
  39. <td><img src="theme/error_handling.png" width="313" height="238"></td>
  40. </tr>
  41. </table>
  42. <a name="the_parser_exception"></a>
  43. <h2>Parser Errors</h2>
  44. <p> The <tt>parser_error</tt> class is the generic parser exception class used
  45. by Spirit. This is the base class for all parser exceptions.</p>
  46. <pre> <code><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>ErrorDescrT</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>*&gt;
  47. </span><span class=keyword>class </span><span class=identifier>parser_error </span><span class=special>
  48. {
  49. </span><span class=keyword>public</span><span class=special>:
  50. </span><span class=identifier>parser_error</span><span class=special>(</span><span class=identifier>IteratorT </span><span class=identifier>where</span><span class=special>, </span><span class=identifier>ErrorDescrT </span><span class=identifier>descriptor</span><span class=special>);
  51. </span><span class=identifier>IteratorT </span><span class=identifier>where</span><span class=special>;
  52. </span><span class=identifier>ErrorDescrT</span><span class=identifier> descriptor</span><span class=special>;
  53. </span><span class=special>};
  54. </span></code></pre>
  55. <p> The exception holds the iterator position where the error was encountered
  56. in its <tt>where</tt> member variable. In addition to the iterator, <tt>parser_error</tt>
  57. also holds information regarding the error (error descriptor) in its <tt>descriptor
  58. </tt> member variable.</p>
  59. <p> Semantic actions are free to throw parser exceptions when necessary. A utility
  60. function <tt>throw_</tt> may be called. This function creates and throws a <tt>parser_error</tt>
  61. given an iterator and an error descriptor:</p>
  62. <pre>
  63. <code><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>ErrorDescrT</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>IteratorT</span><span class=special>&gt;
  64. </span><span class=keyword>void </span><span class=identifier>throw_</span><span class=special>(</span><span class=identifier>IteratorT where</span><span class=special>, </span><span class=identifier>ErrorDescrT descriptor</span><span class=special>);
  65. </span></code></pre>
  66. <a name="the_parser_assertion"></a>
  67. <h2>Parser Assertions</h2>
  68. <p> Assertions may be put in places where we don't have any other option other
  69. than expect parsing to succeed. If parsing fails, a specific type of exception
  70. is thrown.</p>
  71. <p> Before declaring the grammar, we declare some assertion objects. <tt>assertion</tt>
  72. is a template class parameterized by the type of error that will be thrown once
  73. the assertion fails. The following assertions are parameterized by a user defined
  74. Error enumeration.</p>
  75. <a name="examples"></a>
  76. <h3>Examples</h3>
  77. <pre>
  78. <code><span class=keyword>enum </span><span class=identifier>Errors
  79. </span><span class=special>{
  80. </span><span class=identifier>program_expected</span><span class=special>,
  81. </span><span class=identifier>begin_expected</span><span class=special>,
  82. </span><span class=identifier>end_expected
  83. </span><span class=special>};
  84. </span><span class=identifier>assertion</span><span class=special>&lt;</span><span class=identifier>Errors</span><span class=special>&gt; </span><span class=identifier>expect_program</span><span class=special>(</span><span class=identifier>program_expected</span><span class=special>);
  85. </span><span class=identifier>assertion</span><span class=special>&lt;</span><span class=identifier>Errors</span><span class=special>&gt; </span><span class=identifier>expect_begin</span><span class=special>(</span><span class=identifier>begin_expected</span><span class=special>);
  86. </span><span class=identifier>assertion</span><span class=special>&lt;</span><span class=identifier>Errors</span><span class=special>&gt; </span><span class=identifier>expect_end</span><span class=special>(</span><span class=identifier>end_expected</span><span class=special>);
  87. </span></code></pre>
  88. <p> The example above uses enums to hold the information regarding the error,
  89. we are free to use other types such as integers and strings. For example, <tt>assertion&lt;string&gt;</tt>
  90. accepts a string as its info. It is advisable to use light-weight objects though,
  91. after all, error descriptors are usually static. Enums are convenient for error
  92. handlers to detect and easily catch since C++ treats enums as unique types.</p>
  93. <table width="80%" border="0" align="center">
  94. <tr>
  95. <td class="note_box"> <b><img src="theme/lens.gif" width="15" height="16">
  96. The assertive_parser</b><br>
  97. <br>
  98. Actually, the expression <tt>expect_end(str_p(&quot;end&quot;))</tt>creates
  99. an assertive_parser object. An assertive_parser is a parser that throws
  100. an exception in response to a parsing failure. The assertive_parser throws
  101. a parser_error exception rather than returning an unsuccessful match to
  102. signal that the parser failed to match the input. During parsing, parsers
  103. are given an iterator of type <tt>IteratorT</tt>. This is combined with
  104. the error descriptor type <tt>ErrorDescrT</tt> of the assertion (in this
  105. case enum <tt>Errors</tt>). Both are used to create a <tt>parser_error&lt;Errors,
  106. IteratorT&gt;</tt> which is then thrown to signal the exception. </td>
  107. </tr>
  108. </table>
  109. <p> The predeclared <tt>expect_end</tt> assertion object may now be used in the
  110. grammar as wrappers around parsers. For example:</p>
  111. <pre>
  112. <code><span class=identifier>expect_end</span><span class=special>(</span><span class=identifier>str_p</span><span class=special>(</span><span class=string>&quot;end&quot;</span><span class=special>))
  113. </span></code></pre>
  114. <p> This will throw an exception if it fails to see &quot;end&quot; from the input.</p>
  115. <a name="the_guard"></a>
  116. <h2>The Guard</h2>
  117. <p> The <tt>guard</tt> is used to catch a specific type of <tt>parser_error</tt>.
  118. guards are typically predeclared just like assertions. Extending our previous
  119. example:</p>
  120. <pre>
  121. <code><span class=identifier>guard</span><span class=special>&lt;</span><span class=identifier>Errors</span><span class=special>&gt; </span><span class=identifier>my_guard</span><span class=special>;
  122. </span></code></pre>
  123. <p> <tt>Errors</tt>, in this example is the error descriptor type we want to detect.
  124. This is the same enum as above. <tt>my_guard</tt> may now be used in a grammar
  125. declaration:</p>
  126. <pre> <code><span class=identifier>my_guard</span><span class=special>(</span><span class=identifier>p</span><span class=special>)[</span><span class=identifier>error_handler</span><span class=special>]</span></code></pre>
  127. <p> where <tt>p</tt> is an expression that evaluates to a parser. Somewhere inside
  128. <tt>p</tt>, a parser may throw a parser exception. <tt>error_handler</tt> is
  129. the error handler which may be a function or functor compatible with the interface:</p>
  130. <pre> <code>error_status<span class=special>&lt;</span>T<span class=special>&gt;</span><span class=identifier>
  131. f</span><span class=special>(</span>ScannerT const&amp; scan, ErrorT error<span class=special>);
  132. </span></code></pre>
  133. <p> Where scan points to the scanner state prior to parsing and error is the error
  134. that arose. The handler is allowed to move the scanner position as it sees fit,
  135. possibly in an attempt to perform error correction. The handler must then return
  136. an <tt>error_status&lt;T&gt;</tt> object. </p>
  137. <table width="80%" border="0" align="center">
  138. <tr>
  139. <td class="note_box"> <b><img src="theme/lens.gif" width="15" height="16">
  140. The fallback_parser </b><br>
  141. <br>
  142. The expression <tt>my_guard(expr, error_handler)</tt>creates a fallback_parser
  143. object. The fallback_parser handles parser_error exceptions of a specific
  144. type. Since <tt>my_guard</tt> is declared as <tt>guard&lt;Errors&gt;</tt>,
  145. the fallback_parser catches <tt>Errors</tt> specific parser errors: <tt>parser_error&lt;Errors,
  146. IteratorT&gt;</tt>. The class sets up a try block. When an exception is
  147. caught, the catch block then calls the error_handler. </td>
  148. </tr>
  149. </table>
  150. <h2>error_status&lt;T&gt;</h2>
  151. <pre>
  152. <code><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T </span><span class=special>= </span><span class=identifier>nil_t</span><span class=special>&gt;
  153. </span><span class=keyword>struct </span><span class=identifier>error_status
  154. </span><span class=special>{
  155. </span><span class=keyword>enum </span><span class=identifier>result_t </span><span class=special>{ </span><span class=identifier>fail</span><span class=special>, </span><span class=identifier>retry</span><span class=special>, </span><span class=identifier>accept</span><span class=special>, </span><span class=identifier>rethrow </span><span class=special>};
  156. </span><span class=identifier>error_status</span><span class=special>(</span><span class=identifier>
  157. result_t result </span><span class=special>= </span><span class=identifier>fail</span><span class=special>,
  158. </span><span class=keyword>int </span><span class=identifier>length </span><span class=special>= -</span><span class=number>1</span><span class=special>,
  159. </span><span class=identifier>T </span><span class=keyword>const</span><span class=special>&amp; </span><span class=identifier>value </span><span class=special>= </span><span class=identifier>T</span><span class=special>());
  160. </span>
  161. <span class=identifier>result_t result</span><span class=special>;
  162. </span><span class=keyword>int </span><span class=identifier>length</span><span class=special>;
  163. </span><span class=identifier>T value</span><span class=special>;
  164. };</span></code></pre>
  165. <p>Where <tt>T</tt> is an attribute type compatible with the match attribute of
  166. the <tt>fallback_parser</tt>'s subject (defaults to <tt>nil_t</tt>). The class
  167. <tt>error_status</tt> reports the result of an error handler. This result can
  168. be one of: </p>
  169. <table width="90%" border="0" align="center">
  170. <tr>
  171. <td class="table_title" colspan="8"> error_status result </td>
  172. </tr>
  173. <tr>
  174. <tr>
  175. <td class="table_cells"><b>fail</b></td>
  176. <td class="table_cells">quit and fail. Return a <tt>no_match</tt></td>
  177. </tr>
  178. <td class="table_cells"><b>retry</b></td>
  179. <td class="table_cells">attempt error recovery, possibly moving the scanner</td>
  180. </tr>
  181. <td class="table_cells"><b>accept</b></td>
  182. <td class="table_cells">force success returning a matching length, moving the
  183. scanner appropriately and returning an attribute value</td>
  184. </tr>
  185. <td class="table_cells"><b>rethrow</b></td>
  186. <td class="table_cells">rethrows the error</td>
  187. </tr>
  188. </table>
  189. <p><img src="theme/lens.gif" width="15" height="16"> See <a href="../example/fundamental/error_handling.cpp">error_handling.cpp</a> for a compilable example. This is part of the Spirit distribution.</p>
  190. <table width="80%" border="0" align="center">
  191. </table>
  192. <table border="0">
  193. <tr>
  194. <td width="10"></td>
  195. <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
  196. <td width="30"><a href="debugging.html"><img src="theme/l_arr.gif" border="0"></a></td>
  197. <td width="30"><a href="quickref.html"><img src="theme/r_arr.gif" border="0"></a></td>
  198. </tr>
  199. </table>
  200. <br>
  201. <hr size="1">
  202. <p class="copyright">Copyright &copy; 1998-2003 Joel de Guzman<br>
  203. <br>
  204. <font size="2">Use, modification and distribution is subject to the Boost Software
  205. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  206. http://www.boost.org/LICENSE_1_0.txt)</font></p>
  207. <p class="copyright">&nbsp;</p>
  208. </body>
  209. </html>