Римские цифры

  1. Таблица символов
  2. правила
  3. грамматики
  4. Давайте разберемся!

Этот пример демонстрирует:

  • таблица символов
  • правило
  • грамматика
Таблица символов

Таблица символов содержит словарь символов, где каждый символ представляет собой последовательность символов (char, wchar_t, int, перечисление и т. Д.). Класс шаблона, параметризованный типом символа, может эффективно работать с 8, 16, 32 и даже 64-битными символами. Изменяемые данные типа T связаны с каждым символом.

Традиционно управление таблицей символов поддерживается отдельно от грамматики BNF посредством семантических действий. Вопреки стандартной практике символы класса таблицы символов Spirit являются синтаксическим анализатором, объект которого может использоваться где угодно в спецификации грамматики EBNF. Это пример динамического парсера. Динамический синтаксический анализатор характеризуется своей способностью изменять свое поведение во время выполнения. Первоначально, пустой объект символов ничего не соответствует. В любое время символы могут быть добавлены или удалены, таким образом, динамически изменяя его поведение.

Каждая запись в таблице символов имеет связанный слот изменяемых данных. В связи с этим можно рассматривать таблицу символов как ассоциативный контейнер (или карту) пар ключ-значение, где ключи являются строками.

Класс символов ожидает два параметра шаблона. Первый параметр указывает тип символа символов. Второй указывает тип данных, связанный с каждым символом: его атрибут.

Вот парсер для римских сотен (100..900), использующий таблицу символов. Помните, что данные, связанные с каждым слотом, являются атрибутом синтаксического анализатора (который передается приложенным семантическим действиям).

struct сотни_: qi :: symbols <char, unsigned> {сотни_ () {add ("C", 100) ("CC", 200) ("CCC", 300) ("CD", 400) ("D" 500) («DC», 600) («DCC», 700) («DCCC», 800) («CM», 900); }} сотни;

Вот парсер для римских десятков (10..90):

struct ten_: qi :: symbols <char, unsigned> {ten_ () {add ("X", 10) ("XX", 20) ("XXX", 30) ("XL", 40) ("L" , 50) ("LX", 60) ("LXX", 70) ("LXXX", 80) ("XC", 90); }} десятки;

и, наконец, для тех (1..9):

struct ones_: qi :: symbols <char, unsigned> {ones_ () {add ("I", 1) ("II", 2) ("III", 3) ("IV", 4) ("V" , 5) («VI», 6) («VII», 7) («VIII», 8) («IX», 9); }} из них;

Теперь мы можем использовать сотни, десятки и единицы где угодно в наших выражениях парсера. Все они парсеры.

правила

До сих пор мы вставляли выражения парсера, передавая их непосредственно в функцию фразу_парса. Выражение превращается во временный безымянный синтаксический анализатор, который передается в функцию фразу_parse, используется, а затем уничтожается. Это хорошо для небольших парсеров. Когда выражения усложняются, вы хотите разбить выражения на более мелкие, более простые для понимания части, назвать их и ссылаться на них из других выражений синтаксического анализатора по имени.

Выражение синтаксического анализатора может быть назначено так называемому «правилу». Существуют различные способы объявления правил. Самая простая форма:

rule <Iterator> r;

Как минимум, правилу нужно знать тип итератора, с которым оно будет работать. Это правило нельзя использовать с фразу_parse. Он может использоваться только с функцией разбора - версия, которая не пропускает пробелы (не имеет аргумента шкипера). Если вы хотите, чтобы он пропускал пробелы, вам нужно передать парсер пропуска типа, как в следующей форме:

правило <Iterator, Skipper> r;

Пример:

rule <std :: string :: iterator, space_type> r;

Этот тип правила может использоваться как для фразы_парсета, так и для анализа.

Для нашего следующего примера есть еще одна форма правила, о которой вы должны знать:

rule <Итератор, Подпись> r;

или же

rule <Итератор, Подпись, Шкипер> r; Совет

Все аргументы шаблона правила после Iterator могут быть предоставлены в любом порядке.

Подпись определяет атрибуты правила. Вы видели, что наши парсеры могут иметь атрибут. Напомним, что парсер double_ имеет атрибут double. Чтобы быть точным, это синтезированные атрибуты. Парсер "синтезирует" значение атрибута. Думайте о них как о функциях, возвращающих значения.

Есть еще один тип атрибута, называемый «унаследованным» атрибутом. Пока они нам не понадобятся, но хорошо, что вы знаете о таких атрибутах. Вы можете думать о них как о аргументах функции. И, правильно, подпись правила является сигнатурой функции вида:

результат (argN, argN, ..., argN)

После объявления правила вы можете назначить ему любое выражение синтаксического анализатора. Пример:

r = double_ >> * (',' >> double_);
грамматики

Грамматика инкапсулирует одно или несколько правил. Он имеет те же параметры шаблона, что и правило. Вы объявляете грамматику:

  1. получение структуры (или класса) из шаблона класса грамматики
  2. объявить одно или несколько правил в качестве переменных-членов
  3. инициализировать базовый класс грамматики, задав ему правило запуска (первое правило, которое вызывается, когда грамматика начинает анализ)
  4. инициализировать ваши правила в вашем конструкторе

Римская цифровая грамматика - очень хороший и простой пример грамматики:

template <typename Iterator> struct roman: qi :: grammar <Iterator, unsigned ()> {roman (): roman :: base_type (start) {using qi :: eps; используя qi :: lit; используя qi :: _val; используя qi :: _1; используя ascii :: char_; start = eps [_val = 0] >> (+ горит ('M') [_val + = 1000] || сотни [_val + = _1] || десятки [_val + = _1] || единицы [_val + = _1 ]); } qi :: rule <Iterator, unsigned ()> start; };

На что обратить внимание:

  • Подпись грамматики и правила запуска - unsigned (). Он имеет синтезированный атрибут (возвращаемое значение) типа unsigned без унаследованных атрибутов (аргументов).
  • Мы не указали скип-парсер. Мы не хотим переходить между цифрами.
  • roman :: base_type - это typedef для грамматики <Iterator, unsigned ()>. Если роман не был шаблоном, вы можете просто написать: base_type (start)
  • Но лучше всего создавать шаблоны грамматики, чтобы их можно было повторно использовать для разных типов итераторов.
  • _val другой Феникс заполнитель, представляющий синтезированный атрибут правила.
  • eps - это специальный анализатор духа, который не потребляет ввода, но всегда успешен. Мы используем его для инициализации _val, синтезированного атрибута правила, равным нулю, прежде чем что-либо еще. Фактический парсер начинается с + char_ ('M'), анализируя римские тысячи. Использование eps таким образом хорошо для предварительной и последующей инициализации.
  • Выражение a || b читает: соответствует a или b и в последовательности. То есть, если и a, и b совпадают, он должен быть в последовательности; это эквивалентно >> - b | б, но более эффективно.
Давайте разберемся!
bool r = parse (iter, end, roman_parser, result); if (r && iter == end) {std :: cout << "------------------------- \ n"; std :: cout << "Синтаксический анализ завершен успешно \ n"; std :: cout << "result =" << result << std :: endl; std :: cout << "------------------------- \ n"; } else {std :: string rest (iter, end); std :: cout << "------------------------- \ n"; std :: cout << "Сбой синтаксического анализа \ n"; std :: cout << "остановился на: \": "<< rest <<" \ "\ n"; std :: cout << "------------------------- \ n"; }

roman_parser - это объект типа roman, наш анализатор римских цифр. На этот раз мы используем не пропускаемую версию функций разбора. Мы не хотим пропускать пробелы! Мы также передаем атрибут unsigned result, который получит проанализированное значение.

Полный файл cpp для этого примера можно найти здесь: ../../example/qi/roman.cpp

Похожие

12 месяцев обучения бесплатно с картой Ok System
BGŻ PARIBAS предлагает всем, кто хочет создать Оптимальную учетную запись, возможность бесплатно получить карту OK System на 12 месяцев и получить до 300 злотых в виде возврата денег. Дополнительным преимуществом акции является возврат денег до 300 злотых за участие в акции «Mobilna premia 2» В форме с Оптимальным Аккаунтом Если вы ищете личный
Европейская электронная коммерция и НДС: основное руководство
Это сообщение Клэр Тейлор, генеральный директор SIMPLYVAT.com - компания, которая помогает предприятиям электронной коммерции совершать сделки через границы в соответствии
App Mockup Tools Отзывы Часть 1
Макеты и прототипы невероятно важны на ранних стадиях разработки приложений. Это тот этап, когда приложение действительно дешевое и легко переделать, поэтому вы должны максимально использовать его, чтобы избежать переписывания дорогого кода позже! Использование макетов приложений в процессе проектирования дает массу преимуществ: Макеты легко создавать. Это снижает затраты и время производства, если обратная связь с клиентом вызывает структурные или другие
Как успешно написать блог? Изучите правила и плодотворные правила.
У вас уже есть блог, но вы его не посещаете, за исключением небольшого круга друзей? Или, может быть, вы просто планируете кормить свою блогосферу своим талантом? Несмотря на это, стоит изучить некоторые приемы, используемые авторами самых читаемых блогов. Что хорошо для них, могут помочь и ваши публикации. Кроме того, узнайте точно, что заставляет некоторые блоги компании создавать ценность, в то время как другие только создают затраты. Почему компании ведут блог
Правописание: правильно написать дату и время
Вряд ли есть тема правописания, которая озадачивает столько же, сколько и о датах и ​​времени. «Во вторник этот» или «тот»? Какой штрих заменяет слово «до», и в штрихе есть пробел или нет? Вы должны установить ноль перед однозначными числами?
У вас уже есть блог, но вы его не посещаете, за исключением небольшого круга друзей?
Или, может быть, вы просто планируете кормить свою блогосферу своим талантом?
«Во вторник этот» или «тот»?
Какой штрих заменяет слово «до», и в штрихе есть пробел или нет?
Вы должны установить ноль перед однозначными числами?

Добро пожаловать , Гость !

Мы настоятельно рекомендуем Вам зарегистрироваться, если вы ещё этого не сделали. регистрация откроет Вам новые функции.

Войти или Зарегистрироваться

www.silvio-berluskoni.ru © Все права защищены © 2016.