0a753e0ba91a4917fa51e003b247cfa2bdd71ad9
[platform/upstream/boost.git] / libs / spirit / doc / qi / error_handling.qbk
1 [/==============================================================================
2     Copyright (C) 2001-2011 Joel de Guzman
3     Copyright (C) 2001-2011 Hartmut Kaiser
4
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ===============================================================================/]
8
9 [section Mini XML - Error Handling]
10
11 A parser will not be complete without error handling. Spirit2 provides some
12 facilities to make it easy to adapt a grammar for error handling. We'll wrap up
13 the Qi tutorial with another version of the mini xml parser, this time, with
14 error handling.
15
16 The full cpp file for this example can be found here:
17 [@../../example/qi/mini_xml3.cpp]
18
19 [import ../../example/qi/mini_xml3.cpp]
20
21 Here's the grammar:
22
23 [tutorial_xml3_grammar]
24
25 What's new?
26
27 [heading Readable Names]
28
29 First, when we call the base class, we give the grammar a name:
30
31     : mini_xml_grammar::base_type(xml, "xml")
32
33 Then, we name all our rules:
34
35     xml.name("xml");
36     node.name("node");
37     text.name("text");
38     start_tag.name("start_tag");
39     end_tag.name("end_tag");
40
41 [heading On Success]
42
43 `on_success` declares a handler that is applied when a rule is
44 succesfully matched.
45
46         on_success(rule, handler)
47
48 This specifies that the handler will be called when a rule is
49 matched successfully.  The handler has the following signature:
50
51         void handler(
52                 fusion::vector<
53                         Iterator& first,
54                         Iterator const& last,
55                         Iterator const& i> args,
56                 Context& context)
57
58 `first` points to the position in the input sequence before the rule
59 is matched.  `last` points to the last position in the input sequence.
60 `i` points to the position in the input sequence following the last
61 character that was consumed by the rule.
62
63 A success handler can be used to annotate each matched rule in the
64 grammar with additional information about the portion of the input
65 that matched the rule.  In a compiler application, this can be a
66 combination of file, line number and column number from the input
67 stream for reporting diagnostics or other messages.
68
69 [heading On Error]
70
71 `on_error` declares our error handler:
72
73     on_error<Action>(rule, handler)
74
75 This will specify what we will do when we get an error. We will print out an
76 error message using phoenix:
77
78     on_error<fail>
79     (
80         xml
81       , std::cout
82             << val("Error! Expecting ")
83             << _4                               // what failed?
84             << val(" here: \"")
85             << construct<std::string>(_3, _2)   // iterators to error-pos, end
86             << val("\"")
87             << std::endl
88     );
89
90 we choose to `fail` in our example for the `Action`: Quit and fail. Return a
91 no_match (false). It can be one of:
92
93 [table
94     [[`Action`]     [Description]]
95     [[fail]         [Quit and fail. Return a no_match.]]
96     [[retry]        [Attempt error recovery, possibly moving the iterator position.]]
97     [[accept]       [Force success, moving the iterator position appropriately.]]
98     [[rethrow]      [Rethrows the error.]]
99 ]
100
101
102 `rule` is the rule to which the handler is attached. In our case, we are attaching to the
103 `xml` rule.
104
105 `handler` is the actual error handling function. It expects 4 arguments:
106
107 [table
108     [[Arg]          [Description]]
109     [[first]        [The position of the iterator when the rule with the handler was entered.]]
110     [[last]         [The end of input.]]
111     [[error-pos]    [The actual position of the iterator where the error occured.]]
112     [[what]         [What failed: a string describing the failure.]]
113 ]
114
115 [heading Expectation Points]
116
117 You might not have noticed it, but some of our expressions changed from using
118 the `>>` to `>`. Look, for example:
119
120     end_tag =
121             "</"
122         >   lit(_r1)
123         >   '>'
124     ;
125
126 What is it? It's the /expectation/ operator. You will have some "deterministic
127 points" in the grammar. Those are the places where backtracking *cannot* occur.
128 For our example above, when you get a `"</"`, you definitely must see a valid
129 end-tag label next. It should be the one you got from the start-tag. After that,
130 you definitely must have a `'>'` next. Otherwise, there is no point in
131 proceeding and trying other branches, regardless where they are. The
132 input is definitely erroneous. When this happens, an expectation_failure
133 exception is thrown. Somewhere outward, the error handler will catch the
134 exception.
135
136 Try building the parser: [@../../example/qi/mini_xml3.cpp]. You can find some
137 examples in: [@../../example/qi/mini_xml_samples] for testing purposes.
138 "4.toyxml" has an error in it:
139
140     <foo><bar></foo></bar>
141
142 Running the example with this gives you:
143
144     Error! Expecting "bar" here: "foo></bar>"
145     Error! Expecting end_tag here: "<bar></foo></bar>"
146     -------------------------
147     Parsing failed
148     -------------------------
149
150 [endsect]