Разбор карты вариантов с Boost Spirit X3 - PullRequest
0 голосов
/ 28 декабря 2018

Я пытаюсь (и не могу) проанализировать map<int, variant<string, float>> с помощью Boost Spirit X3 со следующим кодом:

#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <map>
#include <variant>
#include <string>

using namespace std;

namespace x3 = boost::spirit::x3;

int main() {
    auto variantRule = x3::rule<class VariantClass, x3::variant<std::string, float>>() = (*x3::alnum | x3::float_);

    auto pairRule = x3::rule<class PairClass, pair<int, x3::variant<std::string, float>>>() = x3::int_ >> ":" >> variantRule;

    auto mapRule = x3::rule<class MapClass, map<int, x3::variant<std::string, float>>>() = pairRule >>  * ( "," >> pairRule );

    string input = "1 : 1.0, 2 : hello, 3 : world";

    map<int, x3::variant<std::string, float>> variantMap;

    auto success = x3::phrase_parse(input.begin(), input.end(), mapRule, x3::space, variantMap);

    return 0;
}

По какой-то причине я не могу разобрать карты pair<int, variant<string, float>>.Я был в состоянии разобрать вектор вариантов, но только когда я пытаюсь разобрать карты вариантов, мой код дает сбой.Стоит отметить, что я также прошел учебники по X3.Любая помощь будет принята с благодарностью.

Редактировать 1

Принимая во внимание ответ @ liliscent и некоторые другие изменения, я наконец смог заставить ее работать, вотправильный код:

#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <map>
#include <variant>
#include <string>

using namespace std;

namespace x3 = boost::spirit::x3;

int main() {
    auto stringRule = x3::rule<class StringClass, string>() = x3::lexeme[x3::alpha >> *x3::alnum];

    auto variantRule = x3::rule<class VariantClass, x3::variant<std::string, float>>() = (stringRule | x3::float_);

    auto pairRule = x3::rule<class PairClass, pair<int, x3::variant<std::string, float>>>() = x3::int_ >> ':' >> variantRule;

    auto mapRule = x3::rule<class MapClass, map<int, x3::variant<std::string, float>>>() = pairRule % ",";

    string input = "1 : 1.0, 2 : hello, 3 : world";

    map<int, x3::variant<std::string, float>> variantMap;

    auto bg = input.begin(), ed = input.end();

    auto success = x3::phrase_parse(bg, ed, mapRule, x3::space, variantMap) && bg == ed;

    if (!success) cout<<"Parsing not succesfull";

    return 0;
}

1 Ответ

0 голосов
/ 28 декабря 2018

Если вы хотите, чтобы spirit распознал std::pair и std::map, вам необходимо включить адаптер Fusion для std::pair:

#include <boost/fusion/adapted/std_pair.hpp>

Это должно решить вашу проблему компиляции .Но есть и другие проблемы в вашем коде, это правило (*x3::alnum | x3::float_); не будет делать то, что вы хотите, потому что левая часть может напрямую соответствовать пустой.Вам нужно переосмыслить, как определить этот идентификатор.

Кроме того, лучше написать pairRule % ",", чем pairRule >> * ( "," >> pairRule );.

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

...