parse std :: vector & lt; int & gt; целые числа через запятую

Я пытаюсь реализовать очень специфическую грамматику, которая требует от меня в определенный момент для анализа списка целых чисел через запятую. Правило ци выглядит следующим образом:

qi::rule<Iterator, ascii::space_type> ident;
qi::rule<Iterator, ascii::space_type> nlist;

...

ident = char_ >> nlist;
nlist = ("(" >> int_ % "," >> ")");

...

Мне нужно передать значения до ident правило (выражение идентификатора должно создать узел дерева синтаксиса, где для конструктора требуются проанализированные значения из nlist). Я думал о создании и наполнении std::vector и использовать семантическое действие, как _val = vector<int>..., Теперь мне неясно, как я могу создать вектор произвольной длины из этого правила, поскольку я не делаю никаких предположений о том, как долго будет вводиться, или использую предопределенный вектор, такой как Примеры.

Это вообще возможно или есть лучший способ сделать это?

1

Решение

Это хлеб с маслом Духа Ци.

Просто используйте любой совместимый тип атрибута и прибыль:

    using nlist_t = std::vector<int>;
using ident_t = std::pair<char, nlist_t>;

qi::rule<Iterator, ident_t(), qi::ascii::space_type> ident;
qi::rule<Iterator, nlist_t(), qi::ascii::space_type> nlist;

Примечание: для std::pair Атрибут совместимости, включают соответствующие fusion заголовок:

Жить на Колиру

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

namespace qi = boost::spirit::qi;

int main()
{
using nlist_t = std::vector<int>;
using ident_t = std::pair<char, nlist_t>;

using Iterator = std::string::const_iterator;
qi::rule<Iterator, ident_t(), qi::ascii::space_type> ident;
qi::rule<Iterator, nlist_t(), qi::ascii::space_type> nlist;

ident = qi::char_ >> nlist;
nlist = '(' >> qi::int_ % ',' >> ')';

for (std::string const input : { "a (1,2,3)", "+(881,-2,42)    \n", "?(0)" }) {

ident_t data;
if (qi::phrase_parse(input.begin(), input.end(), ident, qi::ascii::space, data)) {
std::cout << "Parsed: " << data.first << "(";
for (auto i : data.second) std::cout << i << ",";
std::cout << ")\n";
} else
std::cout << "Parse failed: '" << input << "'\n";
}
}

Печать

Parsed: a(1,2,3,)
Parsed: +(881,-2,42,)
Parsed: ?(0,)

БОНУС

Версия с воображаемым типом Ast с использованием phoenix::construct:

Также живи на Колиру

#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix.hpp>

namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;

namespace OoShinyAst {

using MyName = char;
using MyArgument = int;
using MyArgumentList = std::vector<MyArgument>;

struct MyIdent {
MyName         name;
MyArgumentList args;

MyIdent() = default;
MyIdent(MyName name, MyArgumentList args)
: name(std::move(name)), args(std::move(args)) { }
};
}

int main()
{
using Iterator = std::string::const_iterator;
qi::rule<Iterator, OoShinyAst::MyIdent(),        qi::ascii::space_type> ident;
qi::rule<Iterator, OoShinyAst::MyArgumentList(), qi::ascii::space_type> nlist;

nlist = '(' >> qi::int_ % ',' >> ')';
ident = (qi::char_ >> nlist) [ qi::_val = px::construct<OoShinyAst::MyIdent>(qi::_1, qi::_2) ];

for (std::string const input : { "a (1,2,3)", "+(881,-2,42)    \n", "?(0)" }) {

OoShinyAst::MyIdent data;
if (qi::phrase_parse(input.begin(), input.end(), ident, qi::ascii::space, data)) {
std::cout << "Parsed: " << data.name << "(";
for (auto i : data.args) std::cout << i << ",";
std::cout << ")\n";
} else
std::cout << "Parse failed: '" << input << "'\n";
}
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector