Как разобрать две строки используя boost :: spirit? - PullRequest
0 голосов
/ 21 марта 2020

Я все еще пытаюсь обернуть голову вокруг Boost :: Spirit.
Я хочу разобрать два слова в переменную. Когда я могу это сделать, в структуру.

Одно слово компилируется, а переменная - нет. Почему?

#include <boost/spirit/include/qi.hpp>
#include <boost/tuple/tuple.hpp>
#include <string>
#include <iostream>

using namespace boost::spirit;

/*
class Syntax : public qi::parser{

};
*/

int main()
{
    //get user input
    std::string input;
    std::getline(std::cin, input);
    auto it = input.begin();

    bool result;
    //define grammar for a single word
    auto word_grammar = +qi::alnum - qi::space;

    std::string singleWord;

    result = qi::parse(
        it, input.end(),
        word_grammar,
        singleWord
    );

    if(!result){
        std::cout << "Failed to parse a word" << '\n';
        return -1;
    }

    std::cout << "\"" << singleWord << "\"" << '\n';

    //Now parse two words into a variable
    std::cout << "Variable:\n";
    typedef boost::tuple<std::string, std::string> Variable;
    Variable variable;
    auto variable_grammar = word_grammar >> word_grammar;

    result = qi::parse(
        it, input.end(),
        variable_grammar,
        variable
    );

    if(!result){
        std::cout << "Failed to parse a variable" << '\n';
        return -1;
    }

    std::cout << "\"" << variable.get<0>() << "\" \"" << variable.get<1>() << "\"" << '\n';

    //now parse a list of variables
    std::cout << "List of Variables:\n";
    std::list<Variable> variables;

    result = qi::parse(
        it, input.end(),
        variable_grammar % +qi::space,
        variable
    );

    if(!result){
        std::cout << "Failed to parse a list of variables" << '\n';
        return -1;
    }

    for(auto var : variables)
        std::cout << "DataType: " << var.get<0>() << ", VariableName: " << var.get<1>() << '\n';

}

В конце я хочу разобрать что-то вроде этого:

int a
float b
string name

Шаблоны хороши, но когда возникают проблемы, сообщения об ошибках просто не читаются человеком (таким образом, нет указать их здесь).
Я использую g cc

Ответы [ 2 ]

1 голос
/ 25 марта 2020

Извините, что так долго. Я спешил создать новый веб-сервер и многому научился.

Вот как это выглядит в X3. Я думаю, что легче иметь дело, чем qi. И потом, я использовал это намного больше. Но тогда qi намного зрелее, богаче. Тем не менее, x3 предназначен для адаптации, взлома. Таким образом, вы можете заставить его делать все, что захотите.

Итак, живите на coliru

#include <string>
#include <iostream>
#include <vector>
#include <boost/spirit/home/x3.hpp>
#include <boost/tuple/tuple.hpp>
//as pointed out, for the error 'The parser expects tuple-like attribute type'
#include <boost/fusion/adapted/boost_tuple.hpp>

//our declarations
using Variable = boost::tuple<std::string, std::string>;
using Vector = std::vector<Variable>;

namespace parsers {
    using namespace boost::spirit::x3;

    auto const word = lexeme[+char_("a-zA-Z")];
    //note, using 'space' as the stock skipper
    auto const tuple = word >> word;
}

std::ostream& operator << (std::ostream& os, /*const*/ Variable& obj) {
    return os << obj.get<0>() << ' ' << obj.get<1>();
}

std::ostream& operator << (std::ostream& os, /*const*/ Vector& obj) {
    for (auto& item : obj)
        os << item << " : ";
    return os;
}

template<typename P, typename A>
bool test_parse(std::string in, P parser, A& attr) {
    auto begin(in.begin());
    bool r = phrase_parse(begin, in.end(), parser, boost::spirit::x3::space, attr);
    std::cout << "result:\n " << attr << std::endl;
    return r;
}

int main()
{
    //not recomended but this is testing stuff
    using namespace boost::spirit::x3;
    using namespace parsers;

    std::string input("first second third forth");

    //parse one word
    std::string singleWord;
    test_parse(input, word, singleWord);

    //parse two words into a variable
    Variable variable;
    test_parse(input, tuple, variable);

    //parse two sets of two words
    Vector vector;
    test_parse(input, *tuple, vector);
}

Вам может понравиться эта форма тестирования. Вы можете сосредоточиться на тестировании парсеров без лишнего кода. В дальнейшем вам будет проще держать ваши basi c парсеры в их собственном пространстве имен. Ах да, x3 компилируется намного быстрее, чем qi!

1 голос
/ 22 марта 2020

Одно слово компилируется, переменная - нет. Почему?

Отсутствуют два #include:

#include <boost/fusion/adapted/boost_tuple.hpp>
#include <boost/spirit/include/qi_list.hpp>
...