error_handling.html 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  4. <title>Error Handling</title>
  5. <link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
  6. <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
  7. <link rel="home" href="../../index.html" title="Spirit X3 3.0.4">
  8. <link rel="up" href="../tutorials.html" title="Tutorials">
  9. <link rel="prev" href="rexpr.html" title="RExpressions - Recursive ASTs!">
  10. <link rel="next" href="../quick_reference.html" title="Quick Reference">
  11. </head>
  12. <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
  13. <table cellpadding="2" width="100%"><tr>
  14. <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
  15. <td align="center"><a href="../../../../../../../index.html">Home</a></td>
  16. <td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
  17. <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
  18. <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
  19. <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
  20. </tr></table>
  21. <hr>
  22. <div class="spirit-nav">
  23. <a accesskey="p" href="rexpr.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorials.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../quick_reference.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
  24. </div>
  25. <div class="section">
  26. <div class="titlepage"><div><div><h3 class="title">
  27. <a name="spirit_x3.tutorials.error_handling"></a><a class="link" href="error_handling.html" title="Error Handling">Error Handling</a>
  28. </h3></div></div></div>
  29. <p>
  30. This tutorial wouldn't be complete without touching on error handling. As
  31. a prerequisite in understanding this tutorial, please review the previous
  32. <a class="link" href="employee.html" title="Employee - Parsing into structs">employee</a> and <a class="link" href="annotation.html" title="Annotations - Decorating the ASTs">annotations</a>
  33. examples. This example builds on top of these previous examples.
  34. </p>
  35. <p>
  36. The full cpp file for this example can be found here: <a href="../../../../../example/x3/error_handling.cpp" target="_top">error_handling.cpp</a>
  37. </p>
  38. <p>
  39. Please review the previous <a class="link" href="annotation.html" title="Annotations - Decorating the ASTs">annotations
  40. example</a>. The information there will be very helpful in understanding
  41. error handling.
  42. </p>
  43. <h5>
  44. <a name="spirit_x3.tutorials.error_handling.h0"></a>
  45. <span class="phrase"><a name="spirit_x3.tutorials.error_handling.the_ast"></a></span><a class="link" href="error_handling.html#spirit_x3.tutorials.error_handling.the_ast">The
  46. AST</a>
  47. </h5>
  48. <p>
  49. Our AST is exactly the same as what we had before in the <a class="link" href="annotation.html" title="Annotations - Decorating the ASTs">annotations</a>:
  50. </p>
  51. <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">client</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">ast</span>
  52. <span class="special">{</span>
  53. <span class="keyword">struct</span> <span class="identifier">person</span> <span class="special">:</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">position_tagged</span>
  54. <span class="special">{</span>
  55. <span class="identifier">person</span><span class="special">(</span>
  56. <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">first_name</span> <span class="special">=</span> <span class="string">""</span>
  57. <span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">last_name</span> <span class="special">=</span> <span class="string">""</span>
  58. <span class="special">)</span>
  59. <span class="special">:</span> <span class="identifier">first_name</span><span class="special">(</span><span class="identifier">first_name</span><span class="special">)</span>
  60. <span class="special">,</span> <span class="identifier">last_name</span><span class="special">(</span><span class="identifier">last_name</span><span class="special">)</span>
  61. <span class="special">{}</span>
  62. <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">first_name</span><span class="special">,</span> <span class="identifier">last_name</span><span class="special">;</span>
  63. <span class="special">};</span>
  64. <span class="keyword">struct</span> <span class="identifier">employee</span> <span class="special">:</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">position_tagged</span>
  65. <span class="special">{</span>
  66. <span class="keyword">int</span> <span class="identifier">age</span><span class="special">;</span>
  67. <span class="identifier">person</span> <span class="identifier">who</span><span class="special">;</span>
  68. <span class="keyword">double</span> <span class="identifier">salary</span><span class="special">;</span>
  69. <span class="special">};</span>
  70. <span class="special">}}</span>
  71. </pre>
  72. <p>
  73. We have two structs, the <code class="computeroutput"><span class="identifier">person</span></code>
  74. and the <code class="computeroutput"><span class="identifier">employee</span></code>. Each inherits
  75. from <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">position_tagged</span></code> which provides positional
  76. information that we can use to tell the AST's position in the input stream
  77. anytime. We will need these information for error handling and reporting.
  78. </p>
  79. <p>
  80. Like before, we need to tell <a href="../../../../../../../libs/fusion/doc/html/index.html" target="_top">Boost.Fusion</a>
  81. about our structs to make them first-class fusion citizens that the grammar
  82. can utilize:
  83. </p>
  84. <pre class="programlisting"><span class="identifier">BOOST_FUSION_ADAPT_STRUCT</span><span class="special">(</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">person</span><span class="special">,</span>
  85. <span class="identifier">first_name</span><span class="special">,</span> <span class="identifier">last_name</span>
  86. <span class="special">)</span>
  87. <span class="identifier">BOOST_FUSION_ADAPT_STRUCT</span><span class="special">(</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">,</span>
  88. <span class="identifier">age</span><span class="special">,</span> <span class="identifier">who</span><span class="special">,</span> <span class="identifier">salary</span>
  89. <span class="special">)</span>
  90. </pre>
  91. <h5>
  92. <a name="spirit_x3.tutorials.error_handling.h1"></a>
  93. <span class="phrase"><a name="spirit_x3.tutorials.error_handling.expectations"></a></span><a class="link" href="error_handling.html#spirit_x3.tutorials.error_handling.expectations">Expectations</a>
  94. </h5>
  95. <p>
  96. There are occasions in which it is expected that the input must match a particular
  97. parser or the input is invalid. Such cases generally arise after matching
  98. a portion of a grammar, such that the context is fully known. In such a situation,
  99. failure to match should result in an exception. For example, when parsing
  100. an e-mail address, a name, an "@" and a domain name must be matched
  101. or the address is invalid.
  102. </p>
  103. <p>
  104. Two X3 mechanisms facilitate parser expectations:
  105. </p>
  106. <div class="orderedlist"><ol class="orderedlist" type="1">
  107. <li class="listitem">
  108. The expectation operator (Expectation operator)
  109. </li>
  110. <li class="listitem">
  111. The expect directive (<code class="computeroutput"><span class="identifier">expect</span></code><code class="computeroutput"><span class="special">[</span><span class="identifier">p</span><span class="special">]</span></code>)
  112. </li>
  113. </ol></div>
  114. <p>
  115. The expectation operator (Expectation operator) requires that the following
  116. parser (<code class="computeroutput"><span class="identifier">b</span></code>) match the input
  117. or an <code class="computeroutput"><span class="identifier">expectation_failure</span></code>
  118. is emitted. Using a client supplied <code class="computeroutput"><span class="identifier">on_error</span></code>
  119. handler, the exception can be serviced by calling the handler with the source
  120. iterators and context at which the parsing failed can be reported.
  121. </p>
  122. <p>
  123. By contrast, the sequence operator (Sequence) does not require that the following
  124. parser match the input, which allows for backtracking or simply returning
  125. false from the parse function with no exceptions.
  126. </p>
  127. <p>
  128. The expect directive (<code class="computeroutput"><span class="identifier">expect</span></code><code class="computeroutput"><span class="special">[</span><span class="identifier">p</span><span class="special">]</span></code>)
  129. requires that the argument parser matches the input or an exception is emitted.
  130. Using on_error(), that exception can be handled by calling a handler with
  131. the context at which the parsing failed can be reported.
  132. </p>
  133. <h5>
  134. <a name="spirit_x3.tutorials.error_handling.h2"></a>
  135. <span class="phrase"><a name="spirit_x3.tutorials.error_handling.on_error"></a></span><a class="link" href="error_handling.html#spirit_x3.tutorials.error_handling.on_error">on_error</a>
  136. </h5>
  137. <p>
  138. <code class="computeroutput"><span class="identifier">on_error</span></code> is the counterpart
  139. of <code class="computeroutput"><span class="identifier">on_success</span></code>, as discussed
  140. in the <a class="link" href="annotation.html" title="Annotations - Decorating the ASTs">annotations example</a>.
  141. While <code class="computeroutput"><span class="identifier">on_success</span></code> handlers
  142. are callback hooks to client code that are executed by the parser after a
  143. <span class="emphasis"><em>successful</em></span> parse, <code class="computeroutput"><span class="identifier">on_error</span></code>
  144. handlers are callback hooks to client code that are executed by the parser
  145. when an <code class="computeroutput"><span class="identifier">expectation_failure</span></code>
  146. is thrown via the expect operator or directive. <code class="computeroutput"><span class="identifier">on_error</span></code>
  147. handlers have access to the iterators, the context and the exception that
  148. was thrown.
  149. </p>
  150. <h5>
  151. <a name="spirit_x3.tutorials.error_handling.h3"></a>
  152. <span class="phrase"><a name="spirit_x3.tutorials.error_handling.error_handling"></a></span><a class="link" href="error_handling.html#spirit_x3.tutorials.error_handling.error_handling">Error
  153. Handling</a>
  154. </h5>
  155. <p>
  156. Before we proceed, let me introduce a helper class, the x3::error_handler.
  157. It is utility class that provides <a href="https://clang.llvm.org/" target="_top">Clang</a>
  158. style error reporting which gives you nice reports such as the following:
  159. </p>
  160. <pre class="programlisting">In line 16:
  161. Error! Expecting: person here:
  162. 'I am not a person!' &lt;--- this should be a person
  163. ____^_
  164. </pre>
  165. <p>
  166. We'll see later that this error message is exactly what this example emits.
  167. </p>
  168. <p>
  169. Here's our <code class="computeroutput"><span class="identifier">on_error</span></code> handler:
  170. </p>
  171. <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">error_handler</span>
  172. <span class="special">{</span>
  173. <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Iterator</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Exception</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Context</span><span class="special">&gt;</span>
  174. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">error_handler_result</span> <span class="identifier">on_error</span><span class="special">(</span>
  175. <span class="identifier">Iterator</span><span class="special">&amp;</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">Iterator</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">last</span>
  176. <span class="special">,</span> <span class="identifier">Exception</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">Context</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">context</span><span class="special">)</span>
  177. <span class="special">{</span>
  178. <span class="keyword">auto</span><span class="special">&amp;</span> <span class="identifier">error_handler</span> <span class="special">=</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">get</span><span class="special">&lt;</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">error_handler_tag</span><span class="special">&gt;(</span><span class="identifier">context</span><span class="special">).</span><span class="identifier">get</span><span class="special">();</span>
  179. <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">message</span> <span class="special">=</span> <span class="string">"Error! Expecting: "</span> <span class="special">+</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">which</span><span class="special">()</span> <span class="special">+</span> <span class="string">" here:"</span><span class="special">;</span>
  180. <span class="identifier">error_handler</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">where</span><span class="special">(),</span> <span class="identifier">message</span><span class="special">);</span>
  181. <span class="keyword">return</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">error_handler_result</span><span class="special">::</span><span class="identifier">fail</span><span class="special">;</span>
  182. <span class="special">}</span>
  183. <span class="special">};</span>
  184. </pre>
  185. <p>
  186. <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">error_handler_tag</span></code> is a special tag we will
  187. use to get a reference to the actual x3::error_handler that we will inject
  188. at very start, when we call parse. We get the x3::error_handler here:
  189. </p>
  190. <pre class="programlisting"><span class="keyword">auto</span><span class="special">&amp;</span> <span class="identifier">error_handler</span> <span class="special">=</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">get</span><span class="special">&lt;</span><span class="identifier">error_handler_tag</span><span class="special">&gt;(</span><span class="identifier">context</span><span class="special">).</span><span class="identifier">get</span><span class="special">();</span>
  191. </pre>
  192. <p>
  193. The x3::error_handler handles all the nitty gritty details such as determining
  194. the line number and actual column position, and formatting the error message
  195. printed. All we have to do is provide the actual error string which we extract
  196. from the <code class="computeroutput"><span class="identifier">expectation_failure</span></code>
  197. exception:
  198. </p>
  199. <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">message</span> <span class="special">=</span> <span class="string">"Error! Expecting: "</span> <span class="special">+</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">which</span><span class="special">()</span> <span class="special">+</span> <span class="string">" here:"</span><span class="special">;</span>
  200. </pre>
  201. <p>
  202. Then, we return <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">error_handler_result</span><span class="special">::</span><span class="identifier">fail</span></code> to tell X3 that we want to fail the
  203. parse when such an event is caught. You can return one of:
  204. </p>
  205. <div class="informaltable"><table class="table">
  206. <colgroup>
  207. <col>
  208. <col>
  209. </colgroup>
  210. <thead><tr>
  211. <th>
  212. <p>
  213. <code class="computeroutput"><span class="identifier">Action</span></code>
  214. </p>
  215. </th>
  216. <th>
  217. <p>
  218. Description
  219. </p>
  220. </th>
  221. </tr></thead>
  222. <tbody>
  223. <tr>
  224. <td>
  225. <p>
  226. fail
  227. </p>
  228. </td>
  229. <td>
  230. <p>
  231. Quit and fail. Return a no_match.
  232. </p>
  233. </td>
  234. </tr>
  235. <tr>
  236. <td>
  237. <p>
  238. retry
  239. </p>
  240. </td>
  241. <td>
  242. <p>
  243. Attempt error recovery, possibly moving the iterator position.
  244. </p>
  245. </td>
  246. </tr>
  247. <tr>
  248. <td>
  249. <p>
  250. accept
  251. </p>
  252. </td>
  253. <td>
  254. <p>
  255. Force success, moving the iterator position appropriately.
  256. </p>
  257. </td>
  258. </tr>
  259. <tr>
  260. <td>
  261. <p>
  262. rethrow
  263. </p>
  264. </td>
  265. <td>
  266. <p>
  267. Rethrows the error.
  268. </p>
  269. </td>
  270. </tr>
  271. </tbody>
  272. </table></div>
  273. <h5>
  274. <a name="spirit_x3.tutorials.error_handling.h4"></a>
  275. <span class="phrase"><a name="spirit_x3.tutorials.error_handling.the_parser"></a></span><a class="link" href="error_handling.html#spirit_x3.tutorials.error_handling.the_parser">The
  276. Parser</a>
  277. </h5>
  278. <p>
  279. Now we'll rewrite employee parser with error handling in mind. Like the
  280. <a class="link" href="annotation.html" title="Annotations - Decorating the ASTs">annotations</a> example,
  281. inputs will be of the form:
  282. </p>
  283. <pre class="programlisting"><span class="special">{</span> <span class="identifier">age</span><span class="special">,</span> <span class="string">"forename"</span><span class="special">,</span> <span class="string">"surname"</span><span class="special">,</span> <span class="identifier">salary</span> <span class="special">}</span>
  284. </pre>
  285. <p>
  286. Here we go:
  287. </p>
  288. <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">parser</span>
  289. <span class="special">{</span>
  290. <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">int_</span><span class="special">;</span>
  291. <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">double_</span><span class="special">;</span>
  292. <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">lexeme</span><span class="special">;</span>
  293. <span class="keyword">using</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">char_</span><span class="special">;</span>
  294. <span class="keyword">struct</span> <span class="identifier">quoted_string_class</span><span class="special">;</span>
  295. <span class="keyword">struct</span> <span class="identifier">person_class</span><span class="special">;</span>
  296. <span class="keyword">struct</span> <span class="identifier">employee_class</span><span class="special">;</span>
  297. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">quoted_string_class</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">quoted_string</span> <span class="special">=</span> <span class="string">"quoted_string"</span><span class="special">;</span>
  298. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">person_class</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">person</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">person</span> <span class="special">=</span> <span class="string">"person"</span><span class="special">;</span>
  299. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">employee_class</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">employee</span> <span class="special">=</span> <span class="string">"employee"</span><span class="special">;</span>
  300. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">quoted_string_def</span> <span class="special">=</span> <span class="identifier">lexeme</span><span class="special">[</span><span class="char">'"'</span> <span class="special">&gt;&gt;</span> <span class="special">+(</span><span class="identifier">char_</span> <span class="special">-</span> <span class="char">'"'</span><span class="special">)</span> <span class="special">&gt;&gt;</span> <span class="char">'"'</span><span class="special">];</span>
  301. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">person_def</span> <span class="special">=</span> <span class="identifier">quoted_string</span> <span class="special">&gt;</span> <span class="char">','</span> <span class="special">&gt;</span> <span class="identifier">quoted_string</span><span class="special">;</span>
  302. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">employee_def</span> <span class="special">=</span>
  303. <span class="char">'{'</span>
  304. <span class="special">&gt;</span> <span class="identifier">int_</span> <span class="special">&gt;</span> <span class="char">','</span>
  305. <span class="special">&gt;</span> <span class="identifier">person</span> <span class="special">&gt;</span> <span class="char">','</span>
  306. <span class="special">&gt;</span> <span class="identifier">double_</span>
  307. <span class="special">&gt;</span> <span class="char">'}'</span>
  308. <span class="special">;</span>
  309. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">employees</span> <span class="special">=</span> <span class="identifier">employee</span> <span class="special">&gt;&gt;</span> <span class="special">*(</span><span class="char">','</span> <span class="special">&gt;&gt;</span> <span class="identifier">employee</span><span class="special">);</span>
  310. <span class="identifier">BOOST_SPIRIT_DEFINE</span><span class="special">(</span><span class="identifier">quoted_string</span><span class="special">,</span> <span class="identifier">person</span><span class="special">,</span> <span class="identifier">employee</span><span class="special">);</span>
  311. <span class="keyword">struct</span> <span class="identifier">quoted_string_class</span> <span class="special">{};</span>
  312. <span class="keyword">struct</span> <span class="identifier">person_class</span> <span class="special">:</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">annotate_on_success</span> <span class="special">{};</span>
  313. <span class="keyword">struct</span> <span class="identifier">employee_class</span> <span class="special">:</span> <span class="identifier">error_handler</span><span class="special">,</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">annotate_on_success</span> <span class="special">{};</span>
  314. <span class="special">}</span>
  315. </pre>
  316. <p>
  317. Go back and review the <a class="link" href="annotation.html#__tutorial_annotated_employee_parser__">annotated
  318. employee parser</a>. What has changed? It is almost identical, except:
  319. </p>
  320. <p>
  321. Where appropriate, we're using the expectation operator (Expectation operator)
  322. in place of the sequence operator (Sequence):
  323. </p>
  324. <pre class="programlisting"><span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">person_def</span> <span class="special">=</span> <span class="identifier">quoted_string</span> <span class="special">&gt;</span> <span class="char">','</span> <span class="special">&gt;</span> <span class="identifier">quoted_string</span><span class="special">;</span>
  325. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">employee_def</span> <span class="special">=</span>
  326. <span class="char">'{'</span>
  327. <span class="special">&gt;</span> <span class="identifier">int_</span> <span class="special">&gt;</span> <span class="char">','</span>
  328. <span class="special">&gt;</span> <span class="identifier">person</span> <span class="special">&gt;</span> <span class="char">','</span>
  329. <span class="special">&gt;</span> <span class="identifier">double_</span>
  330. <span class="special">&gt;</span> <span class="char">'}'</span>
  331. <span class="special">;</span>
  332. </pre>
  333. <p>
  334. You will have some "deterministic points" in the grammar. Those
  335. are the places where backtracking <span class="bold"><strong>cannot</strong></span>
  336. occur. For our example above, when you get a <code class="computeroutput"><span class="char">'{'</span></code>,
  337. you definitely must see an <code class="computeroutput"><span class="identifier">int_</span></code>
  338. next. After that, you definitely must have a <code class="computeroutput"><span class="char">','</span></code>
  339. next and then a <code class="computeroutput"><span class="identifier">person</span></code> and
  340. so on until the final <code class="computeroutput"><span class="char">'}'</span></code>. Otherwise,
  341. there is no point in proceeding and trying other branches, regardless where
  342. they are. The input is definitely erroneous. When this happens, an expectation_failure
  343. exception is thrown. Somewhere outward, the error handler will catch the
  344. exception. In our case, it is caught in our <code class="computeroutput"><span class="identifier">on_error</span></code>
  345. handler.
  346. </p>
  347. <p>
  348. Notice too that we subclass the <code class="computeroutput"><span class="identifier">employee_class</span></code>
  349. from our <code class="computeroutput"><span class="identifier">error_handler</span></code>. By
  350. doing so, we tell X3 that we want to call our <code class="computeroutput"><span class="identifier">error_handler</span></code>
  351. whenever an exception is thrown somewhere inside the <code class="computeroutput"><span class="identifier">employee</span></code>
  352. rule and whatever else it calls (i.e. the <code class="computeroutput"><span class="identifier">person</span></code>
  353. and <code class="computeroutput"><span class="identifier">quoted_string</span></code> rules).
  354. </p>
  355. <h5>
  356. <a name="spirit_x3.tutorials.error_handling.h5"></a>
  357. <span class="phrase"><a name="spirit_x3.tutorials.error_handling.let_s_parse"></a></span><a class="link" href="error_handling.html#spirit_x3.tutorials.error_handling.let_s_parse">Let's
  358. Parse</a>
  359. </h5>
  360. <p>
  361. Now we have the complete parse mechanism with error handling:
  362. </p>
  363. <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">parse</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">input</span><span class="special">)</span>
  364. <span class="special">{</span>
  365. <span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space</span><span class="special">;</span>
  366. <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">::</span><span class="identifier">const_iterator</span> <span class="identifier">iterator_type</span><span class="special">;</span>
  367. <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">&gt;</span> <span class="identifier">ast</span><span class="special">;</span>
  368. <span class="identifier">iterator_type</span> <span class="identifier">iter</span> <span class="special">=</span> <span class="identifier">input</span><span class="special">.</span><span class="identifier">begin</span><span class="special">();</span>
  369. <span class="identifier">iterator_type</span> <span class="keyword">const</span> <span class="identifier">end</span> <span class="special">=</span> <span class="identifier">input</span><span class="special">.</span><span class="identifier">end</span><span class="special">();</span>
  370. <span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">with</span><span class="special">;</span>
  371. <span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">error_handler_tag</span><span class="special">;</span>
  372. <span class="keyword">using</span> <span class="identifier">error_handler_type</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">error_handler</span><span class="special">&lt;</span><span class="identifier">iterator_type</span><span class="special">&gt;;</span>
  373. <span class="comment">// Our error handler</span>
  374. <span class="identifier">error_handler_type</span> <span class="identifier">error_handler</span><span class="special">(</span><span class="identifier">iter</span><span class="special">,</span> <span class="identifier">end</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span><span class="special">);</span>
  375. <span class="comment">// Our parser</span>
  376. <span class="keyword">using</span> <span class="identifier">client</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">employees</span><span class="special">;</span>
  377. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">parser</span> <span class="special">=</span>
  378. <span class="comment">// we pass our error handler to the parser so we can access</span>
  379. <span class="comment">// it later in our on_error and on_sucess handlers</span>
  380. <span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">error_handler_tag</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">error_handler</span><span class="special">))</span>
  381. <span class="special">[</span>
  382. <span class="identifier">employees</span>
  383. <span class="special">];</span>
  384. <span class="keyword">bool</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">phrase_parse</span><span class="special">(</span><span class="identifier">iter</span><span class="special">,</span> <span class="identifier">end</span><span class="special">,</span> <span class="identifier">parser</span><span class="special">,</span> <span class="identifier">space</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">);</span>
  385. <span class="comment">// ... Some final reports here</span>
  386. <span class="special">}</span>
  387. </pre>
  388. <p>
  389. Prior to calling <code class="computeroutput"><span class="identifier">phrase_parse</span></code>,
  390. we first create an AST where parsed data will be stored:
  391. </p>
  392. <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">&gt;</span> <span class="identifier">ast</span><span class="special">;</span>
  393. </pre>
  394. <p>
  395. We also create the actual error handler, sending message to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span></code>:
  396. </p>
  397. <pre class="programlisting"><span class="identifier">error_handler_type</span> <span class="identifier">error_handler</span><span class="special">(</span><span class="identifier">iter</span><span class="special">,</span> <span class="identifier">end</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span><span class="special">);</span>
  398. </pre>
  399. <p>
  400. Then, we inject a reference to <code class="computeroutput"><span class="identifier">error_handler</span></code>,
  401. using the <code class="computeroutput"><span class="identifier">with</span></code> directive
  402. similar to what we did in the <a class="link" href="annotation.html#__tutorial_with_directive__">annotations
  403. example</a>:
  404. </p>
  405. <pre class="programlisting"><span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">parser</span> <span class="special">=</span>
  406. <span class="comment">// we pass our error handler to the parser so we can access</span>
  407. <span class="comment">// it later in our on_error and on_sucess handlers</span>
  408. <span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">error_handler_tag</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">error_handler</span><span class="special">))</span>
  409. <span class="special">[</span>
  410. <span class="identifier">employees</span>
  411. <span class="special">];</span>
  412. </pre>
  413. <p>
  414. Now, if we give the parser an erroneous input:
  415. </p>
  416. <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">bad_input</span> <span class="special">=</span> <span class="identifier">R</span><span class="string">"(
  417. {
  418. 23,
  419. "</span><span class="identifier">Amanda</span><span class="string">",
  420. "</span><span class="identifier">Stefanski</span><span class="string">",
  421. 1000.99
  422. },
  423. {
  424. 35,
  425. "</span><span class="identifier">Angie</span><span class="string">",
  426. "</span><span class="identifier">Chilcote</span><span class="string">",
  427. 2000.99
  428. },
  429. {
  430. 43,
  431. 'I am not a person!' &lt;--- this should be a person
  432. 3000.99
  433. },
  434. {
  435. 22,
  436. "</span><span class="identifier">Dorene</span><span class="string">",
  437. "</span><span class="identifier">Dole</span><span class="string">",
  438. 2500.99
  439. },
  440. {
  441. 38,
  442. "</span><span class="identifier">Rossana</span><span class="string">",
  443. "</span><span class="identifier">Rafferty</span><span class="string">",
  444. 5000.99
  445. }
  446. )"</span><span class="special">;</span>
  447. </pre>
  448. <p>
  449. The parser will complain as expected:
  450. </p>
  451. <pre class="programlisting">-------------------------
  452. Now we have some errors
  453. In line 16:
  454. Error! Expecting: person here:
  455. 'I am not a person!' &lt;--- this should be a person
  456. ____^_
  457. -------------------------
  458. Parsing failed
  459. -------------------------
  460. </pre>
  461. </div>
  462. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  463. <td align="left"></td>
  464. <td align="right"><div class="copyright-footer">Copyright &#169; 2001-2018 Joel de Guzman,
  465. Hartmut Kaiser<p>
  466. Distributed under the Boost Software License, Version 1.0. (See accompanying
  467. file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
  468. </p>
  469. </div></td>
  470. </tr></table>
  471. <hr>
  472. <div class="spirit-nav">
  473. <a accesskey="p" href="rexpr.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorials.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../quick_reference.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
  474. </div>
  475. </body>
  476. </html>