Семантическое действие Boost.Spirit для разбора строки не работает

Я пытаюсь написать анализатор Boost.Spirit, который анализирует строку, которая должна представлять простую команду, например «print foo.txt». Каждый раз, когда ввод соответствует грамматике, должно вызываться семантическое действие.

Вот код:

template<class Iterator>
struct my_parser : qi::grammar<Iterator, void(), qi::ascii::space_type>
{
    void test(std::string const & s) const
    {
        std::cerr << s << std::endl;
    }

    my_parser() : my_parser::base_type(print)
    {
        using qi::_1;
        using qi::char_;

        filename =
            *qi::char_("a-zA-Z_0-9./ ")
            ;

        print =
            qi::lit("print")
            >> filename [ boost::bind(&my_parser::test, this, _1) ]
            ;
    }

    qi::rule<Iterator, std::string()> filename;
    qi::rule<Iterator, void(), qi::ascii::space_type> print;
};

Если я попытаюсь скомпилировать это, я получу что-то вроде:

no match for call to ‘(const boost::_mfi::cmf1<void, parser::my_parser<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> > >, const std::basic_string<char>&>) (parser::my_parser<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> > >* const&, const boost::phoenix::actor<boost::spirit::argument<0> >&)’

Если я заменю _1 на "abc", например, код скомпилируется, но фраза_parse() вернет false для ввода "print foo.txt". Если я закомментирую [ boost:bind(...) ] фраза_parse() вернет значение true.

Кто-нибудь знает, что я делаю неправильно? Спасибо.


person Franz    schedule 31.07.2012    source источник


Ответы (1)


Я считаю, что ваша проблема в том, что вы пытаетесь передать заполнитель духа boost::bind, который обычно работает только со встроенными заполнителями (которые вы скрыли с помощью using qi::_1). Я бы попробовал добавить определение BOOST_SPIRIT_USE_PHOENIX_V3, добавить #include "boost/phoenix.hpp", а затем перейти к boost::phoenix::bind(&my_parser::test, this, _1 ).

person Ylisar    schedule 31.07.2012
comment
+1 Это сработает. Я считаю, что простое удаление using qi::_1; также сработает, поскольку используется здесь. Вы можете найти здесь в разделе Важно внизу страницы описание проблемы. - person ; 31.07.2012