![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Roman NumeralsBoost , Spirit 2.5.2 , Tutorials
|
![]() | Tip |
---|---|
Все аргументы шаблона правил после Итератора могут быть предоставлены в любом порядке. |
Подпись указывает атрибуты правила. Вы видели, что у наших парсеров может быть атрибут. Напомним, что ДП_
parser имеет атрибут ДП
. Точнее, это атрибуты synthesized. Парсер «синтезирует» значение атрибута. Думайте о них как о функциях возвращающих значений.
Существует еще один тип атрибута, называемый «наследованным» атрибутом. Пока они нам не понадобятся, но хорошо, что вы знаете о таких атрибутах. Вы можете думать о них как о функциональных аргументах. И, по праву, подпись правила - это функциональная подпись формы:
result(argN, argN,..., argN)
После объявления правила, теперь вы можете назначить ему любое выражение. Пример:
r = double_ >> *(',' >> double_);
Грамматика инкапсулирует один или несколько правил. Он имеет те же параметры шаблона, что и правило. Вы объявляете грамматику:
grammar
шаблон классаРимская цифра - очень хороший и простой пример грамматики:
template <typename Iterator> struct roman : qi::grammar<Iterator, unsigned()> { roman() : roman::base_type(start) { using qi::eps; using qi::lit; using qi::_val; using qi::_1; using ascii::char_; start = eps [_val = 0] >> ( +lit('M') [_val += 1000] || hundreds [_val += _1] || tens [_val += _1] || ones [_val += _1] ) ; } qi::rule<Iterator, unsigned()> start; };
Вещи, которые следует учитывать:
Неподписано()
. Он имеет синтезированный атрибут (возвратное значение) типа неподписанный
без унаследованных атрибутов (аргументов).роман::base_type
- это тип-дефицит для грамма<Итератор, неподписанный()>
. Если roman
не был шаблоном, вы могли бы просто написать: base_type(start)_val
- это еще один Phoenix, представляющий синтезированный атрибут правила.eps
- это особый духовный парсер, который не потребляет никаких входов, но всегда успешен. Мы используем его для инициализации _val
, синтезированного атрибута правила, до нуля перед чем-либо еще. Фактический парсер начинается по адресу +lit('M')
, разбивая римские тысячи. Используя eps
, этот способ хорош для предварительной и пост-инициализации.a || b
читает: совпадает a или b и последовательность. То есть, если и a
, и b
матч, он должен быть в последовательности; это эквивалентно a > -b b b
, но более эффективно.bool r = parse(iter, end, roman_parser, result); if (r && iter == end) { std::cout << "-------------------------\n"; std::cout << "Parsing succeeded\n"; std::cout << "result = " << result << std::endl; std::cout << "-------------------------\n"; } else { std::string rest(iter, end); std::cout << "-------------------------\n"; std::cout << "Parsing failed\n"; std::cout << "stopped at: \": " << rest << "\"\n"; std::cout << "-------------------------\n"; }
roman_parser
- это объект типа roman
, наш римский числитель. На этот раз мы используем нескользящую версию функций парса. Мы не хотим пропустить какие-либо пространства! Мы также проходим в атрибуте , неподписанном результат
, который получит парсированное значение.
The full cpp file for this example can be found here: ../../example/qi/roman.cpp
Статья Roman Numerals раздела Spirit 2.5.2 Tutorials может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
реклама |