[/==============================================================================
    Copyright (C) 2001-2008 Joel de Guzman
    Copyright (C) 2001-2008 Hartmut Kaiser

    Distributed under 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)
===============================================================================/]

[section Mini XML - Error Handling]

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.

[@../../example/qi/mini_xml1.cpp] and here: [@../../example/qi/mini_xml2.cpp]

[import ../../example/qi/mini_xml3.cpp]

Here's the grammar:

[tutorial_xml3_grammar]

What's new?

[heading Readable Names]

First, when we call the base class, we give the grammar a name:

    : mini_xml_grammar::base_type(xml, "xml")

Then, we name all our rules:

    xml.name("xml");
    node.name("node");
    text.name("text");
    start_tag.name("start_tag");
    end_tag.name("end_tag");

[heading On Error]

`on_error` declares our error handler:

    on_error<Action>(rule, handler)

This will specify what we will do when we get an error. We will print out an
error message using phoenix:

    on_error<fail>
    (
        xml
      , std::cout
            << val("Error! Expecting ")
            << _4                               // what failed?
            << val(" here: \"")
            << construct<std::string>(_3, _2)   // iterators to error-pos, end
            << val("\"")
            << std::endl
    );

we choose to `fail` in our example for the `Action`: Quit and fail. Return a
no_match (false). It can be one of:

[table
    [[`Action`]     [Description]]
    [[fail]         [Quit and fail. Return a no_match.]]
    [[retry]        [Attempt error recovery, possibly moving the iterator position.]]
    [[accept]       [Force success, moving the iterator position appropriately.]]
    [[rethrow]      [Rethrows the error.]]
]


`rule` is the rule we attach the handler to. In our case, we are attaching to the
`xml` rule.

`handler` is the actual error handling function. It expects 4 arguments:

[table
    [[Arg]          [Description]]
    [[first]        [The position of the iterator when the rule with the handler was entered.]]
    [[last]         [The end of input.]]
    [[error-pos]    [The actual position of the iterator where the error occurred.]]
    [[what]         [What failed: a string decribing the failure.]]
]

[heading Expectation Points]

You might not have noticed it, but some of our expressions changed from using
the `>>` to `>`. Look, for example:

    end_tag =
            "</"
        >   lit(_r1)
        >   '>'
    ;

What is it? It's the /expectation/ operator. You will have some "deterministic
points" in the grammar. Those are the places where backtracking *cannot* occur.
For our example above, when you get a `"</"`, 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 `'>'` next. Otherwise, there is no point in
proceeding forward 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.

Try building the parser: [@../../example/qi/mini_xml2.cpp]. You can find some
examples in: [@../../example/qi/mini_xml_samples] for testing purposes.
"4.toyxml" has an error in it:

    <foo><bar></foo></bar>

Running the example with this gives you:

    Error! Expecting "bar" here: "foo></bar>"
    Error! Expecting end_tag here: "<bar></foo></bar>"
    -------------------------
    Parsing failed
    -------------------------

[endsect]
