Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Warming up

Boost , Spirit 2.5.2 , Tutorials

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Начнем с того, что покажем примеры выражений парсера, чтобы дать вам представление о том, как создавать парсеры из простейшего парсера. При сравнении EBNF сSpiritвыражения могут показаться неудобными.Духиспользует перегрузку оператора для достижения своей магии.

Trivial Example #1 Parsing a number

Создайте парсер, который будет разбирать число с плавающей точкой.

double_

(Вы должны признать, что это тривиально!) Приведенный выше код фактически генерирует парсер с плавающей точкой Spirit (встроенный парсер). У Spirit есть много заранее определенных парсеров, и постоянные соглашения об именах помогут вам не сойти с ума!

Trivial Example #2 Parsing two numbers

Создайте парсер, который примет линию, состоящую из двух чисел с плавающей точкой.

double_ >> double_

Здесь вы видите знакомый цифровой парсер с плавающей точкой<double_>, используемый дважды, один раз для каждого числа. Что там делает оператор<>>>? Ну, их нужно было чем-то отделить, и это было выбрано оператором последовательности «следует». Вышеупомянутая программа создает парсер из двух более простых парсеров, склеивая их вместе с оператором последовательности. Результатом является парсер, который представляет собой композицию меньших парсеров. Белое пространство между числами может неявно потребляться в зависимости от того, как используется парсер (см. ниже).

[Note]Note

Когда мы объединяем парсеры, мы в конечном итоге получаем «большой» парсер, но это все еще парсер. Парсеры могут становиться все больше и больше, гнездясь все больше и больше, но когда вы склеиваете два парсера вместе, вы в конечном итоге получаете один больший парсер. Это важная концепция.

Trivial Example #3 Parsing zero or more numbers

Создайте парсер, который будет принимать нулевые или более числа с плавающей точкой.

*double_

Это похоже на Kleene Star с регулярным выражением, хотя синтаксис может показаться немного странным для программиста C++, который не привык видеть перегруженного оператора<*>. На самом деле, если вы знаете регулярные выражения, это может выглядеть странно, так как звезда находится перед выражением, которое она изменяет. С'ест ла Ви. Обвиняем его в том, что мы должны работать с синтаксическими правилами C++.

Любое выражение, которое оценивается парсером, может быть использовано со звездой Клин. Имейте в виду, что правила приоритета оператора C++ могут потребовать, чтобы вы помещали выражения в скобки для сложных выражений. Звезда Клин также известна как закрытие Клин, но мы называем ее звездой в большинстве мест.

Trivial Example #4 Parsing a comma-delimited list of numbers

Этот пример создаст парсер, который принимает список чисел, ограниченный запятой.

double_ >> *(char_(',') >> double_)

Уведомление<char_(',')>. Это буквальный парсер символов, который может распознать запятую<','>. В этом случае звезда Клин изменяет более сложный парсер, а именно тот, который генерируется выражением:

(char_(',') >> double_)

Обратите внимание, что это тот случай, когда скобки необходимы. Звезда Клин содержит полное выражение выше.

Let's Parse!

Мы закончили с определением парсера. Итак, следующий шаг теперь заключается в том, чтобы использовать этот парсер для выполнения своей работы. Есть несколько способов сделать это. Сейчас мы используем функцию<phrase_parse>. Одна перегрузка этой функции принимает четыре аргумента:

  1. Итератор, указывающий на начало ввода
  2. Итератор, указывающий на один прошедший конец входа
  3. Объект парсера
  4. Еще один парсер называется скип парсер

В нашем примере мы хотим пропустить пробелы и вкладки. Другой парсер, названный<space>, включен в репертуар Духа предопределенных парсеров. Это очень простой парсер, который просто распознает белое пространство. Мы будем использовать<space>как наш пропуск парсер. Пропуск парсера - это тот, кто отвечает за пропуск символов между парсерными элементами, такими как<double_>и<char_>.

Хорошо, теперь давайте разберемся!

template <typename Iterator>
bool parse_numbers(Iterator first, Iterator last)
{
    using qi::double_;
    using qi::phrase_parse;
    using ascii::space;
    bool r = phrase_parse(
        first,                          1
        last,                           2
        double_ >> *(',' >> double_),   3
        space                           4
    );
    if (first != last) // fail if we did not get a full match
        return false;
    return r;
}

1

стартовый итератор

2

конечный итератор

3

парсер

4

скип-парсер

Функция парса возвращается<true>или<false>в зависимости от результата парса. Первый итератор передается по ссылке. При успешном анализе этот итератор переставляется в правильную позицию, потребляемую парсером. Если это будет равно<last>, то у нас будет полный матч. Если нет, то у нас частичный матч. Частичное совпадение происходит, когда парсер способен анализировать только часть входа.

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

Здесь мы решили сделать парсер общим, сделав его шаблоном, параметризованным по типу итератора. При этом он может принимать данные, поступающие из любой последовательности, соответствующей STL, до тех пор, пока итераторы соответствуют переднему итератору.

You can find the full cpp file here: ../../example/qi/num_list1.cpp

[Note]Note

<char>и<wchar_t>операнды

Внимательный читатель может заметить, что выражение парсера имеет<','>вместо<char_(',')>, как это было в предыдущих примерах. Это хорошо благодаря синтаксическим правилам конверсии C++. Есть<>>>операторы, которые перегружены, чтобы принять аргумент<char>или<wchar_t>слева или справа (но не оба). Оператор может быть перегружен, если по меньшей мере один из его параметров является определяемым пользователем типом. В этом случае<double_>является 2-м аргументом<operator>>>, и поэтому используется правильная перегрузка<>>>, превращая<','>в буквальный парсер символа.

Проблема с пропуском<char_>должна быть очевидной:<'a'>> 'b'>не является парсером духа, это числовое выражение, сдвигающее значение ASCII (или другого кодирующего)<'a'>на значение ASCII<'b'>. Однако и<char_('a')>> 'b'>, и<'a' >>char_('b')>являются парсерами последовательности Духа для буквы<'a'>, за которой следует<'b'>. Рано или поздно к этому привыкнешь.

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


PrevUpHomeNext

Статья Warming up раздела Spirit 2.5.2 Tutorials может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Tutorials ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 05:48:56/0.009660005569458/1