2017-02-12 20 views
1

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

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>.... Теперь мне непонятно, как создать вектор произвольной длины из этого правила, так как я не делаю никаких предположений о том, как долго будет вход или будет использовать предопределенный вектор, такой как examples.

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

+0

Если вы считаете, что разрешение будет существенно отличаться/сложнее из-за ваших предполагаемых типов деревьев выражений, вы должны были включить их. Все, что имеет значение сейчас, это то, что вы можете использовать распространение наивных атрибутов, чтобы получить вектор, и передать это где угодно, когда захотите его использовать. – sehe

ответ

0

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

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

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 заголовок:

Live On Coliru

#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,) 

БОНУС

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

Also Live On Coliru

#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

Версия [с воображаемым типом Ast] (http://coliru.stacked-crooked.com/a/d7e115e203af4bfa) 'phoenix :: construct' добавлено в качестве бонуса – sehe

+0

Большое вам спасибо за это решение. Я не знал, что так возможно. – s0vereign

+0

Старики, но лакомства: http://boost-spirit.com/home/articles/attribute_handling/attribute-propagation-and-attribute-compatibility/, http://boost-spirit.com/home/articles/attribute_handling/the- магические силы-атрибуты-в-духе-примитивы/и многое другое в той же серии – sehe

 Смежные вопросы

  • Нет связанных вопросов^_^