summaryrefslogtreecommitdiff
path: root/libs/spirit/doc/html/spirit/qi/tutorials/mini_xml___error_handling.html
blob: 1938949cfdb719030551bbba661f3c37370ccd74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Mini XML - Error Handling</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
<link rel="home" href="../../../index.html" title="Spirit 2.5.2">
<link rel="up" href="../tutorials.html" title="Tutorials">
<link rel="prev" href="mini_xml___asts_.html" title="Mini XML - ASTs!">
<link rel="next" href="../quick_reference.html" title="Quick Reference">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="mini_xml___asts_.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>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="spirit.qi.tutorials.mini_xml___error_handling"></a><a class="link" href="mini_xml___error_handling.html" title="Mini XML - Error Handling">Mini
        XML - Error Handling</a>
</h4></div></div></div>
<p>
          A parser will not be complete without error handling. Spirit2 provides
          some facilities to make it easy to adapt a grammar for error handling.
          We'll wrap up the Qi tutorial with another version of the mini xml parser,
          this time, with error handling.
        </p>
<p>
          The full cpp file for this example can be found here: <a href="../../../../../example/qi/mini_xml3.cpp" target="_top">../../example/qi/mini_xml3.cpp</a>
        </p>
<p>
          Here's the grammar:
        </p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Iterator</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">mini_xml_grammar</span>
  <span class="special">:</span> <span class="identifier">qi</span><span class="special">::</span><span class="identifier">grammar</span><span class="special">&lt;</span><span class="identifier">Iterator</span><span class="special">,</span> <span class="identifier">mini_xml</span><span class="special">(),</span> <span class="identifier">qi</span><span class="special">::</span><span class="identifier">locals</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;,</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space_type</span><span class="special">&gt;</span>
<span class="special">{</span>
    <span class="identifier">mini_xml_grammar</span><span class="special">()</span>
      <span class="special">:</span> <span class="identifier">mini_xml_grammar</span><span class="special">::</span><span class="identifier">base_type</span><span class="special">(</span><span class="identifier">xml</span><span class="special">,</span> <span class="string">"xml"</span><span class="special">)</span>
    <span class="special">{</span>
        <span class="keyword">using</span> <span class="identifier">qi</span><span class="special">::</span><span class="identifier">lit</span><span class="special">;</span>
        <span class="keyword">using</span> <span class="identifier">qi</span><span class="special">::</span><span class="identifier">lexeme</span><span class="special">;</span>
        <span class="keyword">using</span> <span class="identifier">qi</span><span class="special">::</span><span class="identifier">on_error</span><span class="special">;</span>
        <span class="keyword">using</span> <span class="identifier">qi</span><span class="special">::</span><span class="identifier">fail</span><span class="special">;</span>
        <span class="keyword">using</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">char_</span><span class="special">;</span>
        <span class="keyword">using</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">string</span><span class="special">;</span>
        <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">qi</span><span class="special">::</span><span class="identifier">labels</span><span class="special">;</span>

        <span class="keyword">using</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">construct</span><span class="special">;</span>
        <span class="keyword">using</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">val</span><span class="special">;</span>

        <span class="identifier">text</span> <span class="special">%=</span> <span class="identifier">lexeme</span><span class="special">[+(</span><span class="identifier">char_</span> <span class="special">-</span> <span class="char">'&lt;'</span><span class="special">)];</span>
        <span class="identifier">node</span> <span class="special">%=</span> <span class="identifier">xml</span> <span class="special">|</span> <span class="identifier">text</span><span class="special">;</span>

        <span class="identifier">start_tag</span> <span class="special">%=</span>
                <span class="char">'&lt;'</span>
            <span class="special">&gt;&gt;</span>  <span class="special">!</span><span class="identifier">lit</span><span class="special">(</span><span class="char">'/'</span><span class="special">)</span>
            <span class="special">&gt;</span>   <span class="identifier">lexeme</span><span class="special">[+(</span><span class="identifier">char_</span> <span class="special">-</span> <span class="char">'&gt;'</span><span class="special">)]</span>
            <span class="special">&gt;</span>   <span class="char">'&gt;'</span>
        <span class="special">;</span>

        <span class="identifier">end_tag</span> <span class="special">=</span>
                <span class="string">"&lt;/"</span>
            <span class="special">&gt;</span>   <span class="identifier">string</span><span class="special">(</span><span class="identifier">_r1</span><span class="special">)</span>
            <span class="special">&gt;</span>   <span class="char">'&gt;'</span>
        <span class="special">;</span>

        <span class="identifier">xml</span> <span class="special">%=</span>
                <span class="identifier">start_tag</span><span class="special">[</span><span class="identifier">_a</span> <span class="special">=</span> <span class="identifier">_1</span><span class="special">]</span>
            <span class="special">&gt;</span>   <span class="special">*</span><span class="identifier">node</span>
            <span class="special">&gt;</span>   <span class="identifier">end_tag</span><span class="special">(</span><span class="identifier">_a</span><span class="special">)</span>
        <span class="special">;</span>

        <span class="identifier">xml</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"xml"</span><span class="special">);</span>
        <span class="identifier">node</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"node"</span><span class="special">);</span>
        <span class="identifier">text</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"text"</span><span class="special">);</span>
        <span class="identifier">start_tag</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"start_tag"</span><span class="special">);</span>
        <span class="identifier">end_tag</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"end_tag"</span><span class="special">);</span>

        <span class="identifier">on_error</span><span class="special">&lt;</span><span class="identifier">fail</span><span class="special">&gt;</span>
        <span class="special">(</span>
            <span class="identifier">xml</span>
          <span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span>
                <span class="special">&lt;&lt;</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"Error! Expecting "</span><span class="special">)</span>
                <span class="special">&lt;&lt;</span> <span class="identifier">_4</span>                               <span class="comment">// what failed?</span>
                <span class="special">&lt;&lt;</span> <span class="identifier">val</span><span class="special">(</span><span class="string">" here: \""</span><span class="special">)</span>
                <span class="special">&lt;&lt;</span> <span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;(</span><span class="identifier">_3</span><span class="special">,</span> <span class="identifier">_2</span><span class="special">)</span>   <span class="comment">// iterators to error-pos, end</span>
                <span class="special">&lt;&lt;</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"\""</span><span class="special">)</span>
                <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span>
        <span class="special">);</span>
    <span class="special">}</span>

    <span class="identifier">qi</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">Iterator</span><span class="special">,</span> <span class="identifier">mini_xml</span><span class="special">(),</span> <span class="identifier">qi</span><span class="special">::</span><span class="identifier">locals</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;,</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space_type</span><span class="special">&gt;</span> <span class="identifier">xml</span><span class="special">;</span>
    <span class="identifier">qi</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">Iterator</span><span class="special">,</span> <span class="identifier">mini_xml_node</span><span class="special">(),</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space_type</span><span class="special">&gt;</span> <span class="identifier">node</span><span class="special">;</span>
    <span class="identifier">qi</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">Iterator</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">(),</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space_type</span><span class="special">&gt;</span> <span class="identifier">text</span><span class="special">;</span>
    <span class="identifier">qi</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">Iterator</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">(),</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space_type</span><span class="special">&gt;</span> <span class="identifier">start_tag</span><span class="special">;</span>
    <span class="identifier">qi</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">Iterator</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">),</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space_type</span><span class="special">&gt;</span> <span class="identifier">end_tag</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
        </p>
<p>
          What's new?
        </p>
<h6>
<a name="spirit.qi.tutorials.mini_xml___error_handling.h0"></a>
          <span><a name="spirit.qi.tutorials.mini_xml___error_handling.readable_names"></a></span><a class="link" href="mini_xml___error_handling.html#spirit.qi.tutorials.mini_xml___error_handling.readable_names">Readable
          Names</a>
        </h6>
<p>
          First, when we call the base class, we give the grammar a name:
        </p>
<pre class="programlisting"><span class="special">:</span> <span class="identifier">mini_xml_grammar</span><span class="special">::</span><span class="identifier">base_type</span><span class="special">(</span><span class="identifier">xml</span><span class="special">,</span> <span class="string">"xml"</span><span class="special">)</span>
</pre>
<p>
          Then, we name all our rules:
        </p>
<pre class="programlisting"><span class="identifier">xml</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"xml"</span><span class="special">);</span>
<span class="identifier">node</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"node"</span><span class="special">);</span>
<span class="identifier">text</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"text"</span><span class="special">);</span>
<span class="identifier">start_tag</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"start_tag"</span><span class="special">);</span>
<span class="identifier">end_tag</span><span class="special">.</span><span class="identifier">name</span><span class="special">(</span><span class="string">"end_tag"</span><span class="special">);</span>
</pre>
<h6>
<a name="spirit.qi.tutorials.mini_xml___error_handling.h1"></a>
          <span><a name="spirit.qi.tutorials.mini_xml___error_handling.on_error"></a></span><a class="link" href="mini_xml___error_handling.html#spirit.qi.tutorials.mini_xml___error_handling.on_error">On Error</a>
        </h6>
<p>
          <code class="computeroutput"><span class="identifier">on_error</span></code> declares our error
          handler:
        </p>
<pre class="programlisting"><span class="identifier">on_error</span><span class="special">&lt;</span><span class="identifier">Action</span><span class="special">&gt;(</span><span class="identifier">rule</span><span class="special">,</span> <span class="identifier">handler</span><span class="special">)</span>
</pre>
<p>
          This will specify what we will do when we get an error. We will print out
          an error message using phoenix:
        </p>
<pre class="programlisting"><span class="identifier">on_error</span><span class="special">&lt;</span><span class="identifier">fail</span><span class="special">&gt;</span>
<span class="special">(</span>
    <span class="identifier">xml</span>
  <span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span>
        <span class="special">&lt;&lt;</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"Error! Expecting "</span><span class="special">)</span>
        <span class="special">&lt;&lt;</span> <span class="identifier">_4</span>                               <span class="comment">// what failed?</span>
        <span class="special">&lt;&lt;</span> <span class="identifier">val</span><span class="special">(</span><span class="string">" here: \""</span><span class="special">)</span>
        <span class="special">&lt;&lt;</span> <span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;(</span><span class="identifier">_3</span><span class="special">,</span> <span class="identifier">_2</span><span class="special">)</span>   <span class="comment">// iterators to error-pos, end</span>
        <span class="special">&lt;&lt;</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"\""</span><span class="special">)</span>
        <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span>
<span class="special">);</span>
</pre>
<p>
          we choose to <code class="computeroutput"><span class="identifier">fail</span></code> in our
          example for the <code class="computeroutput"><span class="identifier">Action</span></code>:
          Quit and fail. Return a no_match (false). It can be one of:
        </p>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
                  <p>
                    <code class="computeroutput"><span class="identifier">Action</span></code>
                  </p>
                </th>
<th>
                  <p>
                    Description
                  </p>
                </th>
</tr></thead>
<tbody>
<tr>
<td>
                  <p>
                    fail
                  </p>
                </td>
<td>
                  <p>
                    Quit and fail. Return a no_match.
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    retry
                  </p>
                </td>
<td>
                  <p>
                    Attempt error recovery, possibly moving the iterator position.
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    accept
                  </p>
                </td>
<td>
                  <p>
                    Force success, moving the iterator position appropriately.
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    rethrow
                  </p>
                </td>
<td>
                  <p>
                    Rethrows the error.
                  </p>
                </td>
</tr>
</tbody>
</table></div>
<p>
          <code class="computeroutput"><span class="identifier">rule</span></code> is the rule to which
          the handler is attached. In our case, we are attaching to the <code class="computeroutput"><span class="identifier">xml</span></code> rule.
        </p>
<p>
          <code class="computeroutput"><span class="identifier">handler</span></code> is the actual error
          handling function. It expects 4 arguments:
        </p>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
                  <p>
                    Arg
                  </p>
                </th>
<th>
                  <p>
                    Description
                  </p>
                </th>
</tr></thead>
<tbody>
<tr>
<td>
                  <p>
                    first
                  </p>
                </td>
<td>
                  <p>
                    The position of the iterator when the rule with the handler was
                    entered.
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    last
                  </p>
                </td>
<td>
                  <p>
                    The end of input.
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    error-pos
                  </p>
                </td>
<td>
                  <p>
                    The actual position of the iterator where the error occured.
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    what
                  </p>
                </td>
<td>
                  <p>
                    What failed: a string describing the failure.
                  </p>
                </td>
</tr>
</tbody>
</table></div>
<h6>
<a name="spirit.qi.tutorials.mini_xml___error_handling.h2"></a>
          <span><a name="spirit.qi.tutorials.mini_xml___error_handling.expectation_points"></a></span><a class="link" href="mini_xml___error_handling.html#spirit.qi.tutorials.mini_xml___error_handling.expectation_points">Expectation
          Points</a>
        </h6>
<p>
          You might not have noticed it, but some of our expressions changed from
          using the <code class="computeroutput"><span class="special">&gt;&gt;</span></code> to <code class="computeroutput"><span class="special">&gt;</span></code>. Look, for example:
        </p>
<pre class="programlisting"><span class="identifier">end_tag</span> <span class="special">=</span>
        <span class="string">"&lt;/"</span>
    <span class="special">&gt;</span>   <span class="identifier">lit</span><span class="special">(</span><span class="identifier">_r1</span><span class="special">)</span>
    <span class="special">&gt;</span>   <span class="char">'&gt;'</span>
<span class="special">;</span>
</pre>
<p>
          What is it? It's the <span class="emphasis"><em>expectation</em></span> operator. You will
          have some "deterministic points" in the grammar. Those are the
          places where backtracking <span class="bold"><strong>cannot</strong></span> occur.
          For our example above, when you get a <code class="computeroutput"><span class="string">"&lt;/"</span></code>,
          you definitely must see a valid end-tag label next. It should be the one
          you got from the start-tag. After that, you definitely must have a <code class="computeroutput"><span class="char">'&gt;'</span></code> next. Otherwise, there is no point in
          proceeding and trying other branches, regardless where they are. The input
          is definitely erroneous. When this happens, an expectation_failure exception
          is thrown. Somewhere outward, the error handler will catch the exception.
        </p>
<p>
          Try building the parser: <a href="../../../../../example/qi/mini_xml3.cpp" target="_top">../../example/qi/mini_xml3.cpp</a>.
          You can find some examples in: <a href="../../../../../example/qi/mini_xml_samples" target="_top">../../example/qi/mini_xml_samples</a>
          for testing purposes. "4.toyxml" has an error in it:
        </p>
<pre class="programlisting"><span class="special">&lt;</span><span class="identifier">foo</span><span class="special">&gt;&lt;</span><span class="identifier">bar</span><span class="special">&gt;&lt;/</span><span class="identifier">foo</span><span class="special">&gt;&lt;/</span><span class="identifier">bar</span><span class="special">&gt;</span>
</pre>
<p>
          Running the example with this gives you:
        </p>
<pre class="programlisting"><span class="identifier">Error</span><span class="special">!</span> <span class="identifier">Expecting</span> <span class="string">"bar"</span> <span class="identifier">here</span><span class="special">:</span> <span class="string">"foo&gt;&lt;/bar&gt;"</span>
<span class="identifier">Error</span><span class="special">!</span> <span class="identifier">Expecting</span> <span class="identifier">end_tag</span> <span class="identifier">here</span><span class="special">:</span> <span class="string">"&lt;bar&gt;&lt;/foo&gt;&lt;/bar&gt;"</span>
<span class="special">-------------------------</span>
<span class="identifier">Parsing</span> <span class="identifier">failed</span>
<span class="special">-------------------------</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2001-2011 Joel de Guzman, Hartmut Kaiser<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        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>)
      </p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="mini_xml___asts_.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>
</div>
</body>
</html>