Плюс оператор в надстройке ци не работает должным образом - PullRequest
2 голосов
/ 23 января 2011

Вот пример кода

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;

    template <typename Iterator>
    struct input : qi::grammar<Iterator, unsigned()>
    {
        input() : input::base_type(start)
        {
            using qi::lit;
            using qi::double_;

            start = lit("ADD") 
                            >> +(
                                    +lit(" ")
                                    >> double_ 
                                    >> +lit(" ")
                                    >> double_
                                ); 
        }

        qi::rule<Iterator, unsigned()> start;
    };

int main()
{

    input<std::string::const_iterator> input_parser; // Our grammar
    std::string str = "ADD 1132.324 2342.234";
    unsigned result;

    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();

    bool r = qi::parse(iter, end, input_parser, result);

}

Я получаю следующую ошибку:

/ usr / local / include / boost / spirit / home / qi / nonterminal / rule.hpp: 201: создается из «Boost :: spirit :: qi :: rule & boost :: spirit :: qi :: rule :: operator = (const Expr &) [с Expr = boost :: proto :: exprns_ ::expr &, const boost :: proto :: exprns _ :: expr &>, 1l> &, const boost :: spirit :: терминал &>, 2l> &, const boost :: proto :: exprns _ :: expr &>, 1l> &>, 2l> &, const boost :: spirit :: Terminal &>, 2l> &>, 1l> &>, 2l>, Iterator = __gnu_cxx :: __ normal_iterator, std :: allocator>>, T1 = unsigned int () (), T2 = boost :: fusion :: unused_type, T3 = boost :: fusion :: unused_type, T4 = boost :: fusion :: unused_type] mini.c ++: 34: создается из входных данных :: input () [with Iterator = __gnu_cxx :: __ normal_iterator, std :: allocator>>] mini.c ++: 49: создан здесь /usr/local/include/boost/spirit/home/qi/operator/plus.hpp:62: ошибка: нет типа с именем type в struct boost :: spirit :: traits :: container_valueâ

Странно, если я использую операцию минус (-), то есть

start = lit("ADD") 
                            >> -(
                                    +lit(" ")
                                    >> double_ 
                                    >> +lit(" ")
                                    >> double_
                                );

... она прекрасно компилируется!

Компиляция на gcc4.3.4.

1 Ответ

2 голосов
/ 23 января 2011

Атрибут, предоставляемый вашим правилом запуска, - unsigned, тогда как анализатор плюсов предоставляет тип контейнера, содержащий атрибуты обернутых элементов.Вот правила распространения атрибутов из документов :

a: A --> +a: vector<A>

(т. Е. Если синтаксический анализатор a предоставляет атрибут типа A, анализатор +a предоставит(стандартный) контейнер, содержащий экземпляры A, например std::vector<A>).

В вашем случае встроенный анализатор предоставляет double.По этой причине вам нужно изменить код, чтобы он работал должным образом:

template <typename Iterator>
struct input : qi::grammar<Iterator, std::vector<double>()>
{
    input() : input::base_type(start)
    {
        using qi::lit;
        using qi::double_;
        start = lit("ADD") >> +(+lit(" ") >> double_ >> +lit(" ") >> double_);
    }

    qi::rule<Iterator, std::vector<double>()> start;
};

int main() 
{
    input<std::string::const_iterator> input_parser; // Our grammar
    std::string str = "ADD 1132.324 2342.234";

    std::vector<double> result;
    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();
    bool r = qi::parse(iter, end, input_parser, result);  
} 

Но, к сожалению, все не так просто, как кажется.В текущей версии Spirit есть ошибка, препятствующая работе кода (даже в скором выпуске Boost V1.46 эта ошибка все еще будет присутствовать, но она исправлена ​​в соединительной линии SVN).Проблема заключается в том, что plus не «сглаживает» встроенные элементы в предоставленном контейнере, что приводит к потере каждой второй двойной переменной, проанализированной приведенным выше кодом.

Обходной путь - избегать последовательностей, раскрывающих более одного атрибутаinside plus:

start = lit("ADD") >> +(+lit(" ") >> double_);

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

Примечание: вы, кажется, хотите пропустить пробелы между элементами на входе.Этого можно добиться проще, используя парсер пропуска:

template <typename Iterator>
struct input : qi::grammar<Iterator, std::vector<double>(), qi::space_type>
{
    input() : input::base_type(start)
    {
        using qi::lit;
        using qi::double_;
        start = lit("ADD") >> +double_;
    }

    qi::rule<Iterator, std::vector<double>(), qi::space_type> start;
};

int main() 
{
    input<std::string::const_iterator> input_parser; // Our grammar
    std::string str = "ADD 1132.324 2342.234";

    std::vector<double> result;
    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();
    bool r = qi::phrase_parse(iter, end, input_parser, qi::space, result);  
} 

, который в то же время обходит проблему, описанную выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...