Boost :: spirit получить значение из нетерминала

У меня есть это в моей поддержке: грамматика духа;

paren = (qi::token(LEFT_PAREN) >> character >> qi::token(RIGHT_PAREN)) [ build_paren ]
;
character = qi::token(CHARACTER) [ build_character]
;

Где они определены как;

qi::rule<Iterator> paren;
qi::rule<Iterator, char> character;

Функция build_paren, имеет следующий прототип (найден с помощью ошибки приведения компилятора);

void build_paren(boost::fusion::vector2<boost::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char>>>, boost::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char>>>> v)

Здесь вектор, содержит две строки соответственно "(\0" а также ")\0", это, как я и ожидал, однако, как я могу получить char соответствует по характеру?

Действительно, прототип, который я хотел бы для моего build_paran функция есть;

void build_paren(std::string left_paren, char character, std::string right_paren)

Или, альтернативно, то же самое, однако с char аргумент как последний в списке.

2

Решение

Вам не нужно работать так усердно 🙂

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

char parsed_char;
bool ok = qi::phrase_parse(f,l, '(' >> qi::char_("0-9") >> ')', qi::space, parsed_char);

Это просто свяжет выставленный атрибут из char_ компонент парсера для ссылка на атрибут (parsed_char) перешел в VARIADIC API синтаксического анализа (phrase_parse).

Ниже приведена обобщенная демонстрация, показывающая, как вы можете повлиять на то, что именно выявляется. Точно то, что раскрывается, документируется с помощью директив синтаксического анализатора, например, здесь, для парсера списка ‘%’.

Для вашего конкретного вопроса вы бы хотели просто:

qi::rule<Iterator, char()> character;
qi::rule<Iterator, char()> parenthesized;

character     = qi::char_("0-9a-z_"); // or qi::alnum, qi::graph, qi::alpha etc...
parenthesized = '(' >> character >> ')';

Заметка главное, нужно сказать qi::rule<Iterator, char()> вместо qi::rule<Iterator, char>!

Демонстрации

Видеть это Жить на Колиру:

#include <boost/spirit/include/qi.hpp>
#include <cassert>

namespace qi = boost::spirit::qi;

template<typename ParseExpr, typename... Attr>
void test(const std::string& input, const ParseExpr& p, Attr&... attrs)
{
auto f = input.begin(),
l = input.end();

bool ok = qi::phrase_parse(f,l, p, qi::space, attrs...);

if (!ok)
std::cerr << "parse failed at: '" << std::string(f,l) << "'\n";

if (f!=l)
std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
}

int main()
{
char parsed_char1, parsed_char2;
int parsed_int;
std::string parsed_str;

test("( 0 )",                        // input
'(' >> qi::char_("0-9") >> ')', // parser/grammar
parsed_char1                     // output
);
assert(parsed_char1 == '0');

test("( q 123 )",
'(' >> qi::graph >> qi::int_ >> ')',
parsed_char1,
parsed_int);
assert(parsed_char1 == 'q');
assert(parsed_int == 123);

// parsing strings: with the skipper
test("( hello world )",
'(' >> *~qi::char_(")") >> ')',
parsed_str = "");
assert(parsed_str == "helloworld");

// parsing strings: qi::char_ exposes the char
test("( hello world )",
qi::char_('(') >>  *~qi::char_(")") >> qi::char_(')'),
parsed_char1, parsed_str = "", parsed_char2);
assert(parsed_char1 == '(');
assert(parsed_str == "helloworld");
assert(parsed_char2 == ')');

// parsing strings: qi::char_ exposes the char, chars get 'combined' into attribute
test("( hello world )",
qi::char_('(') >>  *~qi::char_(")") >> qi::char_(')'),
parsed_str = "");
assert(parsed_str == "(helloworld)");

// parsing strings: as a lexeme
test("( hello world )",
'(' >> qi::lexeme [ *~qi::char_(")") ] >> ')',
parsed_str = "");
assert(parsed_str == "hello world ");

// parsing strings: as bigger lexeme
test("( hello world )",
qi::lexeme [ '(' >>  *~qi::char_(")") >> ')' ],
parsed_str = "");
assert(parsed_str == " hello world ");

// parsing anything as "raw" - exposes an iterator pair, but still 'converts' to a string!
test("( hello 42 false )",
qi::raw [ '(' >>  qi::lexeme[*qi::graph] >> qi::int_ >> qi::bool_ >> ')' ],
parsed_str = "");
assert(parsed_str == "( hello 42 false )");

// note: this would fail to parse, because with the skipper, *qi::graph would eat "42 false )" as well:
std::cout << "next parse should fail:\n";
test("( hello 42 false )", qi::raw [ '(' >>  *qi::graph >> qi::int_ >> qi::bool_ >> ')' ]);
}
2

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

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

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