повышение духа on_error не срабатывает

^ Нет, это не так. Это было частью проблемы, но если просмотреть код как есть прямо сейчас, он уже делает то, что показывает указанный вопрос/ответ... и ошибки все еще не запускаются.

У меня есть этот синтаксический анализатор для строкового литерала. Оно работает. Теперь я хотел бы начать обрабатывать ошибки при сбое. Я скопировал дескриптор on_error 1-1 из примера mini xml, и он компилируется, но никогда не запускается (ошибки не выводятся).

Это парсер:

#define BOOST_SPIRIT_USE_PHOENIX_V3
#define BOOST_SPIRIT_DEBUG

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/home/support/iterators/line_pos_iterator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>

#include <boost/fusion/include/adapt_struct.hpp>

namespace qi = boost::spirit::qi;

struct my_handler_f
{
    template <typename...> struct result { typedef void type; };

    template <typename... T>
    void operator()(T&&...) const {
        std::cout << "\nmy_handler_f() invoked with " << sizeof...(T) << " arguments\n";
    }
};

struct append_utf8_f
{
    template <typename, typename>
    struct result { typedef void type; };

    template <typename INT>
    void operator()(INT in, std::string& to) const
    {
        auto out = std::back_inserter(to);
        boost::utf8_output_iterator<decltype(out)> convert(out);
        *convert++ = in;
    }
};


struct get_line_f
{
    template <typename> struct result { typedef size_t type; };
    template <typename It> size_t operator()(It const& pos_iter) const
    {
        return get_line(pos_iter);
    }
};

struct RangePosition { size_t beginLine, endLine; };

struct String : public RangePosition
{
    String()
        : RangePosition()
        , value()
        , source()
    {
    }

    std::string value;
    std::string source;
};

BOOST_FUSION_ADAPT_STRUCT(String,
                            (std::string, value)
                            (std::string, source)
                            (size_t,      beginLine)
                            (size_t,      endLine)
                          )

template <typename Iterator>
struct source_string : qi::grammar<Iterator, String(), qi::space_type>
{
    struct escape_symbols : qi::symbols<char, char>
    {
        escape_symbols()
        {
            add
                ("\'"    , '\'')
                ("\""    , '\"')
                ("\?"    , '\?')
                ("\\"    , '\\')
                ("0"     , '\0')
                ("a"     , '\a')
                ("b"     , '\b')
                ("f"     , '\f')
                ("n"     , '\n')
                ("r"     , '\r')
                ("t"     , '\t')
                ("v"     , '\v')
            ;
        }

    } escape_symbol;

    source_string() : source_string::base_type(start)
    {
        using qi::raw;
        using qi::_val;
        using qi::_1;
        using qi::_2;
        using qi::_3;
        using qi::_4;
        using qi::space;
        using qi::omit;
        using qi::no_case;
        using qi::print;
        using qi::eps;
        using qi::on_error;
        using qi::fail;
        using qi::lit;

        namespace phx = boost::phoenix;
        using phx::at_c;
        using phx::begin;
        using phx::end;
        using phx::construct;
        using phx::ref;
        using phx::val;

        escape %= escape_symbol;

        character %=   (no_case["\\x"] > hex12)
                        | ("\\"  > (oct123 | escape))
                        | (print - (lit('"') | '\\'));

        unicode =   ("\\u" > hex4[append_utf8(_1, _val)])
                    | ("\\U" > hex8[append_utf8(_1, _val)]);

        string_section %= '"' > *(unicode | character) > '"';

        string %= string_section % omit[*space];

        main = raw [
                       string[at_c<0>(_val) = _1]
                   ]
                   [
                       at_c<1>(_val) = construct<std::string>(begin(_1), end(_1)),
                       at_c<2>(_val) = get_line_(begin(_1)),
                       at_c<3>(_val) = get_line_(end(_1))
                   ];

        start %= eps > main;

        on_error<fail>(start, my_handler);
    }

    boost::phoenix::function<my_handler_f> my_handler;

    qi::rule<Iterator, std::string()> escape;
    qi::uint_parser<char, 16, 1, 2> hex12;  
    qi::uint_parser<char,  8, 1, 3> oct123;
    qi::rule<Iterator, std::string()> character;

    qi::uint_parser<uint16_t, 16, 4, 4> hex4;
    qi::uint_parser<uint32_t, 16, 8, 8> hex8;
    boost::phoenix::function<append_utf8_f> append_utf8;
    qi::rule<Iterator, std::string()> unicode;

    qi::rule<Iterator, std::string()> string_section;
    qi::rule<Iterator, std::string()> string;

    boost::phoenix::function<get_line_f> get_line_;
    qi::rule<Iterator, String(), qi::space_type> main;
    qi::rule<Iterator, String(), qi::space_type> start;
};

и это тестовый код

int main()
{
    std::string str[] =
    {
        "\"\\u1234\\U0002345\"",  
        //"\"te\"\"st\"",
        //"\"te\"  \"st\"",
        //"\"te\" \n \"st\"",
        //"\"\"",
        //"\"\\\"\"",
        //"\"test\"",
        //"\"test\" something",
        //"\"\\\'\\\"\\\?\\\\\\a\\b\\f\\n\\r\\t\\v\"",
        //"\"\\x61cd\\X3012\\x7z\"",
        //"\"\\141cd\\06012\\78\\778\"",
        "\"te",
        //"\"te\nst\"",
        //"\"test\\\"",
        //"\"te\\st\"",
        //
    };

    typedef boost::spirit::line_pos_iterator<std::string::const_iterator> Iterator;

    for (size_t i = 0; i < sizeof(str) / sizeof(str[0]); ++i)
    {
        source_string<Iterator> g;
        Iterator iter(str[i].begin());
        Iterator end(str[i].end());

        String string;
        bool r = phrase_parse(iter, end, g, qi::space, string);
        if (r)
            std::cout << string.beginLine << "-" << string.endLine << ": " << string.value << " === " << string.source << "\n";
        else
            std::cout << "Parsing failed\n";
    }
}

person gsf    schedule 07.10.2013    source источник
comment
Не могли бы вы пожалуйста сделать SSCCE автономным в следующий раз? Бесполезно гоняться за отсутствующими пространствами имен RangePosition (заголовок core/), get_line_f, start и compil:: только для того, чтобы посмотреть, правильно ли построен синтаксический анализатор.   -  person sehe    schedule 07.10.2013
comment
Хм. Я этого не вижу. Это должно быть относительно легко, вот отправная точка для тех, кому не нужно тратить время: coliru .stacked-crooked.com/a/ecfa9880fae07fa8   -  person sehe    schedule 07.10.2013
comment
Я не уверен, что получу этот комментарий. Что вы не видите.   -  person gsf    schedule 07.10.2013
comment
Я не вижу проблемы (имеется в виду: я тоже не могу заставить его работать. Пробовал добрых 20 минут)   -  person sehe    schedule 07.10.2013
comment
Я думаю, проблема в том, что у меня нет ничего, что ожидалось. Похоже, это тот случай, когда срабатывает on_error. Если это правда, это кажется упущенным из виду. Для меня имеет смысл считать правило main/start ожидаемым по умолчанию, если это прямой вызов, а не часть другой грамматики (если это технически возможно).   -  person gsf    schedule 07.10.2013
comment
Ха. Я помню, что видел это раньше. Дай ссылку найду. Хм. Слишком сложно найти. В любом случае, это кажется правдоподобным, и я тоже полностью упустил это из виду.   -  person sehe    schedule 07.10.2013
comment
эта версия также компилируется на clang: coliru.stacked-crooked.com/a/341ab55c40de29f3 Теперь все ожидаемо, хотя ошибок по-прежнему не возникает :(   -  person gsf    schedule 07.10.2013
comment
Я только что нашел эту ссылку: Boost. Spirit.Qi - Ошибки в начале правила   -  person sehe    schedule 08.10.2013
comment
да, ничего нового под солнцем   -  person gsf    schedule 08.10.2013
comment
Разве аргументы шаблона для структуры результата append_utf8_f не должны совпадать с оператором?   -  person sje397    schedule 04.04.2014