Духовная грамматика не скомпилируется: ошибка аргумента шаблона функции? - PullRequest
0 голосов
/ 23 марта 2019

Компиляция этой простой грамматики Spirit приводит к единственной ошибке (несмотря на огромное сообщение об ошибке), возможно, связанной с моим шкипером или каким-то другим параметром шаблона, который я по ошибке использовал.

Iэкспериментировал с различными определениями атрибутов для грамматики и правила запуска, но это не повлияло на ошибку.

#include <string>
#include "/usr/local/boost/include/boost/spirit/include/qi.hpp"
#include "/usr/local/boost/include/boost/spirit/include/qi_symbols.hpp"

using std::string;

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

boost::spirit::qi::rule<string::const_iterator>
    skipper_rule = qi::space | '#' >> *(qi::char_ - qi::eol) >> qi::eol;

typedef BOOST_TYPEOF(skipper_rule) skipper_T;

template <typename Iterator, typename Skipper>
    class Grammar1 : boost::spirit::qi::grammar<Iterator, Skipper>
{
    public:

    typedef boost::spirit::qi::rule<Iterator, Skipper>  rule_nil_T;
    typedef boost::spirit::qi::rule<Iterator, string()> rule_str_T;

    rule_nil_T under =  qi::char_('_');
    rule_nil_T dot   =  qi::char_('.');
    rule_nil_T star  =  qi::char_('*');

    rule_str_T file_name_star = qi::lexeme [ (qi::alpha | under) >> *(qi::alnum | under) >> dot >> star ];

    rule_nil_T start = +file_name_star;

    Grammar1(void) : Grammar1::base_type(start)  { };
    ~Grammar1(void) { };

    void parseInputFile(Iterator itr, Iterator itr_end)
    {
        bool b;
        bool r = phrase_parse(itr, itr_end, start, skipper_rule);
        if (r && itr == itr_end)
        {
            std::cout << "Parsing succeeded\n";
        } else
        {
            string rest(itr, itr_end);
            std::cout << "stopped at: \": " << rest << "\"\n";
       }
    }
};


int main(int argc, char **argv)
{
    Grammar1<string::const_iterator, skipper_T> g;
    string input("input1.* input2.*");

    g.parseInputFile(input.cbegin(), input.cend());

 }

Важные части сообщения об ошибке:

/usr/local/boost/include/boost/spirit/home/qi/nonterminal/rule.hpp:304:17:
error: no match for call to ‘(const function_type *REMOVED*)’
                 if (f(first, last, context, skipper))
                 ^

Комментарий в строке 304 в вышеупомянутом файле Spirit утверждает, что я могу использовать несовместимый шкипер, но я пробовал гораздо более простой шкипер ascii :: space_type безрезультатно.

Остальноесообщения об ошибке:

usr/local/boost/include/boost/function/function_template.hpp:1048:7: note: 
candidate is:
 class function<BOOST_FUNCTION_PARTIAL_SPEC>
       ^
/usr/local/boost/include/boost/function/function_template.hpp:758:17: note:
 boost::function4<R, T1, T2, T3, T4>:: *REMOVED*
     result_type operator()(BOOST_FUNCTION_PARMS) const
                 ^
/usr/local/boost/include/boost/function/function_template.hpp:758:17: note:
   no known conversion for argument 4 from ‘const 
boost::spirit::unused_type’ to ‘const boost::spirit::qi::reference<const 
boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*,
 std::basic_string<char> > > >&’

Есть идеи, что я делаю неправильно?Мой компилятор gcc 4.8.5.

1 Ответ

1 голос
/ 23 марта 2019

Вы пытаетесь использовать правило rule_nil_T, у которого есть шкипер внутри rule_str_T правило, которого нет. По внутренним причинам Дух может потерять шкипера только при вызове правила. Эту проблему легко решить, вставив under, dot и star на сайте использования.

Примечание: вызов правила в Ци имеет накладные расходы. Создание правила для такого простого парсера и последующее использование его внутри повторяющегося парсера не очень хорошая идея.

Подсказка: вы можете использовать директиву raw и использовать литеральные парсеры внутри нее, чтобы получить более производительный и понятный вид парсера. Учтите это: qi::lexeme[qi::raw[(qi::alpha | '_') >> qi::alnum % '.'] >> ".*"].

...