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

Getting started with Boost.Metaparse

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 22. Boost.Metaparse

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

Это руководство показывает вам, как построить парсер для небольшого языка калькулятора с нуля. Цель состоит не в том, чтобы иметь полный калькулятор, а в том, чтобы показать вам наиболее распространенные ситуации, с которыми можно столкнуться при создании парсера с помощью Metaparse. Это руководство предполагает, что у вас есть некоторый опыт метапрограммирования шаблона.

Пока вы используете Metaparse, вы будете писать парсеры, превращая входной текст в тип. Эти типы могут быть позже обработаны дальнейшими шаблонными метапрограммами. Пока вы работаете над парсерами, вы, вероятно, захотите посмотреть на результат анализа тестового ввода. Этот учебник предполагает, что вы можете использоватьMetashell. Поскольку онлайн-демонстрацияделает заголовки Boost доступными, вы также можете использовать это в учебнике.

Если вы установите Metashell на свой компьютер, убедитесь, что у вас есть библиотеки Boost и пример<getting_started>Metaparse на пути включения. Например, вы можете начать Metashell со следующих аргументов:

$ metashell -I$BOOST_ROOT -I$BOOST_ROOT/libs/metaparse/example/getting_started

<$BOOST_ROOT>относится ккаталогу корней повышения(где вы проверили исходный код Boost).

Этот учебник длинный, и поэтому вы можете сделать более короткие или длинные перерывы во время чтения. Чтобы вам было легко остановиться в определенный момент и продолжить позже (или начать в середине, если вы уже знакомы с основами) Метапарс имеет<getting_started>каталог в<example>с. Это содержит определения для каждого раздела этого учебника.

Если вы собираетесь начать (или продолжить) это руководство из раздела 5.2.1, вы можете включить<5_2_1.hpp>. Это определит все, что вам нужно начать с этого раздела.

[Note] Note

У вас также есть доступ к этим заголовкам в онлайн-демо Metashell. Например, вы можете включить заголовок<<boost/metaparse/getting_started/5_2_1.hpp>>, чтобы начать с раздела 5.2.1.

Если у вас нет доступа к Metashell или вы предпочитаете использовать обычную среду разработки C++ при обработке этого руководства, это также возможно.

Учебник (и, как правило, эксперименты с Metaparse) требует, чтобы вы оценили различные выражения метапрограммирования шаблонов и проверили их результат. Таким образом, чтобы попробовать примеры этого учебника, вам нужен способ отображения результата оценки метапрограммы шаблона. Этот раздел показывает вам два варианта.

Вы можете использовать<boost::mpl::print>или<mpllibs::metamonad::fail_with_type>для обеспечения выполнения предупреждения или сообщения об ошибке, содержащего результат оценки метапрограммы. Например, чтобы увидеть, что<BOOST_METAPARSE_STRING><("11 + 2")>относится, вы можете создать<test.cpp>со следующим содержанием:

#include <boost/metaparse/string.hpp>
#include <boost/mpl/print.hpp>
boost::mpl::print<BOOST_METAPARSE_STRING("11 + 2")> x;

Если вы попытаетесь собрать его, компилятор будет отображать предупреждения, содержащие тип конструкции выражения<BOOST_METAPARSE_STRING><("11 + 2")>. Чтобы использовать эту технику для этого учебника, вам нужно добавить все включения и определения, которые учебник предлагает ввести в оболочку, в ваш<test.cpp>файл. Когда оболочка предлагает попытаться назвать какую-то метафункцию (или вы хотели бы что-то попробовать), вам нужно заменить аргумент шаблона<boost::mpl::print>соответствующим выражением и перекомпилировать код.

Вы также можете отображать результат метапрограмм во время выполнения. Для этого можно использовать библиотекуBoost.TypeIndex. Например, чтобы увидеть, что<BOOST_METAPARSE_STRING><("11 + 2")>относится, вы можете создать<test.cpp>со следующим содержанием:

#include <boost/metaparse/string.hpp>
#include <boost/type_index.hpp>
#include <iostream>
int main()
{
  std::cout
    << boost::typeindex::type_id_with_cvr<BOOST_METAPARSE_STRING("11 + 2")>()
    << std::endl;
}

Если вы компилируете и запустите этот код, он будет отображать тип на стандартном выходе.

С помощью Metaparse вы можете создавать шаблонные метапрограммы, анализирующие входной текст. Для передачи входного текста в метапрограммы нужно представлять их в виде типов. Например, представим текст<"Hello world">как тип. Самый простой способ сделать это — создать класс шаблонов, принимающий символы текста в качестве аргументов шаблона:

template <char... Cs>
struct string;

Текст<"11 + 2">может быть представлен следующим образом:

string<'1', '1', ' ', '+', ' ', '2'>

Metaparse предлагает этот тип. Запустите следующую команду в Metashell:

> #include <boost/metaparse/string.hpp>
[Note] Note

Обратите внимание, что символ<>>в начале приведенного выше примера кода является подсказкой Metashell. Он добавляется в примеры кода в качестве подсказки к тому, что вы должны запустить в Metashell (или добавить в свой тестовый<cpp>файл, если вы используете обычную среду разработки).

[Note] Note

Обратите внимание, что вонлайн-демоMetashell вы можете вставить код в оболочку, щелкнув правой кнопкой мыши где-то и выбрав.Вставить из браузерав контекстное меню.

Это сделает этот тип доступным для вас. Теперь вы можете попробовать выполнить следующую команду:

> boost::metaparse::string<'1', '1', ' ', '+', ' ', '2'>

Оболочка будет повторять (почти) тот же тип обратно к вам. Разница лишь в том, что он находится в подименном пространстве с указанием используемой версии Metaparse.

Хорошая вещь в этом представлении заключается в том, что метапрограммы могут легко получить доступ к отдельным символам текста. Не очень хорошая вещь в этом представлении заключается в том, что если вы хотите написать текст<"Hello world">в исходном коде, вам нужно много печатать.

Метапарс предоставляет макрос, который может превратить строку в буквальный экземпляр<boost::metaparse::string>. Это<BOOST_METAPARSE_STRING>макрос. Вы получаете его, включая<<boost/metaparse/string.hpp>>. Давайте попробуем выполнить следующую команду в Metashell:

> BOOST_METAPARSE_STRING("11 + 2")

Ты получишь тот же результат, что и получил, если ты сам получишь<boost::metaparse::string>.

[Note] Note

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

Попробуем создать парсер. Мы начнем с создания парсера для чего-то простого: мы будем разбирать целые числа, такие как текст<"13">. Вы можете думать об этом первом упражнении парсинга как ошаблонном преобразовании строки в строку, потому что мы ожидаем получить значение<13>в результате парсинга.

[Note] Note

Вы знаете разницу между<"13">и<13>в C++. Один из них — это массив символов, другой — интегральное значение. Но в чем разница между ними в шаблонном метапрограммировании? Они представлены разными типами. Например,<"13">представлен<string><<'1', '3'>>, а<13>представлен<std::integral_constant<int,13>>.

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

> #include <boost/metaparse/int_.hpp>

Наша грамматика проста:<int_>. (Не волнуйтесь, мы разберем более сложные языки позже).

Парсер — этокласс метафункций шаблона. Его можно использовать напрямую, но его интерфейс рассчитан на полноту, а не на простоту использования. Metaparse предоставляет<build_parser>метафункцию, которая добавляет обертку к парсерам с простым интерфейсом.

[Note] Note

В этом уроке мы всегда будем заворачивать наши парсеры этим. Мы также будем называть эти завернутые парсеры парсерами. Если вы заинтересованы в этом, вы можете узнать о полном интерфейсе парсеровздесь.

Давайте создадим парсер, используя<int_>и<build_parser>:

> #include <boost/metaparse/build_parser.hpp>
> using namespace boost::metaparse;
> using exp_parser1 = build_parser<int_>;

копипастный дружественный вариант

Во-первых, мы должны включить<build_parser.hpp>, чтобы сделать<build_parser>доступными. Мы облегчаем себе жизнь (97). Третья команда определяет парсер: нам нужно создать.<build_parser>класс шаблонов с нашим парсером<int_>в этом случае в качестве аргумента.

Теперь, когда у нас есть парсер, давайте разберем с ним какой-нибудь текст (если вы еще этого не сделали, включите<boost/metaparse/string.hpp>):

> exp_parser1::apply<BOOST_METAPARSE_STRING("13")>::type
mpl_::integral_c<int, 13>

<exp_parser1>— этокласс метафункций шаблона, принимающий входной текст в качестве аргумента и возвращающий интегральное представление числа в строке. Попробуйте использовать разные цифры и посмотрите, как они преобразуются.

[Note] Note

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

Вы пробовали анализировать недействительный вход? То, что не является числом, например:

> exp_parser1::apply<BOOST_METAPARSE_STRING("thirteen")>::type
<< compilation error >>

Ну,<"thirteen">— эточисло, но наш парсер не говорит по-английски, поэтому он считается недействительным вводом. В результате этого компиляция терпит неудачу, и вы получаете ошибку компиляции от Metashell.

В разделеОбработка недействительных входных данныхмы рассмотрим более подробную информацию об обработке ошибок.

[Note] Note

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

Попробуем дать парсеру два числа вместо одного:

> exp_parser1::apply<BOOST_METAPARSE_STRING("11 13")>::type
mpl_::integral_c<int, 11>

Вы можете быть удивлены: парсер не вернул ошибку. Первое число<11>и проигнорировано<13>. Способ работы<int_>заключается в том, что он анализирует число в начале входного текста и игнорирует остальную часть входа.

Так<exp_parser1>имеет ошибку: наш маленький язык состоит изодногочисла, а несписка чисел. Давайте исправим наш парсер, чтобы рассматривать более одного числа как недействительный вход:

> #include <boost/metaparse/entire_input.hpp>

Это дает нам класс шаблонов<entire_input>. Мы можем обернуть<int_><entire_input>, указав, что число, которое мы анализируем<int_>, должно быть всем входом. Все, что происходит после этого, является ошибкой. Так что наш парсер<entire_input><<><int_><>>сейчас. Давайте завернем его<build_parser>:

> using exp_parser2 = build_parser<entire_input<int_>>;

Давайте попробуем новый парсер:

> exp_parser2::apply<BOOST_METAPARSE_STRING("13")>::type
mpl_::integral_c<int, 13>

Он все еще может анализировать числа. Попробуем дать ему два числа:

> exp_parser2::apply<BOOST_METAPARSE_STRING("11 13")>::type
<< compilation error >>

Это порождает ошибку компиляции, так как парсер не справился.

[Note] Note

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

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

> exp_parser2::apply<BOOST_METAPARSE_STRING("11 ")>::type
<< compilation error >>

Допустим белые пространства после номера:

> #include <boost/metaparse/token.hpp>

Это делает его<token>Класс шаблонов доступен. Он принимает парсер в качестве аргумента и допускает дополнительные белые пространства после этого. Давайте создадим третий парсер, разрешающий белые пространства после числа:

> using exp_parser3 = build_parser<entire_input<token<int_>>>;

Мы ожидаем, что<token><<><int_><>>в этом случае будет весь вход. После<int_>мы допускаем дополнительные белые пространства, но не более того:

> exp_parser3::apply<BOOST_METAPARSE_STRING("11 ")>::type
mpl_::integral_c<int, 11>
[Note] Note

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

Мы можем разобрать числа. Давайте попробуем разобрать что-то более сложное, например<"11 + 2">. Это число, за которым следует символ<+>, за которым следует другое число.<int_>(или<token><<><int_><>>) реализует парсер для одного числа.

Сначала напишем парсер для символа<+>. Мы можем использовать следующее:

> #include <boost/metaparse/lit_c.hpp>

Это дает нам<lit_c>, которые мы можем использовать для разбора конкретных символов, таких как<+>. Грамматический разбор символа<+>может быть представлен<lit_c><<'+'>>. Чтобы разрешить дополнительные белые пространства после него, мы должны использовать<token><<><lit_c><<'+'>>>.

Для анализа<"11 + 2">нам нужна следующая последовательность парсеров:

token<int_>    token<lit_c<'+'>>    token<int_>

Метапарс дает<sequence>для разбора последовательности вещей:

> #include <boost/metaparse/sequence.hpp>

Мы можем реализовать парсер для наших выражений, используя<sequence>:

sequence<token<int_>, token<lit_c<'+'>>, token<int_>>

Давайте создадим парсер, используя его:

> using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;

Попробуйте разобрать простое выражение, используя его:

> exp_parser4::apply<BOOST_METAPARSE_STRING("11 + 2")>::type
boost::mpl::v_item<mpl_::integral_c<int, 2>, boost::mpl::v_item<mpl_::char_<'+'>
, boost::mpl::v_item<mpl_::integral_c<int, 11>, boost::mpl::vector0<mpl_::na>, 0
>, 0>, 0>

То, что вы получаете, может показаться вам странным. Это<vector>от [Boost.MPL] (http://boost.org/libs/mpl). То, что вы видите в оболочке, — это способ представления этого вектора. Metashell предлагает [красивую печать] https://github.com/sabel83/metashell#data-structures-of-boostmpl) для контейнеровBoost.MPL:

> #include <metashell/formatter.hpp>

После включения этого заголовка попробуйте снова разобрать:

> exp_parser4::apply<BOOST_METAPARSE_STRING("11 + 2")>::type
boost_::mpl::vector<mpl_::integral_c<int, 11>, mpl_::char_<'+'>, mpl_::integral_c<int, 2> >

То, что вы сейчас получаете, выглядит проще: это вектор из трех элементов:

  • <mpl_::integral_c<int,11>>Это результат разбора<token><<><int_><>>.
  • <mpl_::char_<'+'>>Это результат разбора с<token><<><lit_c><<'+'>>>.
  • <mpl_::integral_c<int,2>>>Это результат разбора<token><<><int_><>>.

Результатом парсинга с<sequence>является<vector>отдельных парсинговых результатов.

[Note] Note

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

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

  • число (например,<13>)
  • Символ<+>

В нашем последнем решении мы разобрали их, используя<token><<><int_><><token><<><lit_c><<'+'>>>парсеров. Вы заметили какой-то шаблон? Мы заворачиваем парсеры токенов<token><<...>>. Это не просто синтаксический сахар. Наши токены могут быть разделены белыми пространствами, которые можно игнорировать. Это то, что<token><<...>>реализует.

Итак, давайте сделаем реализацию<exp_parser>более чистой, отделив токенизацию от остальной части парсера:

> using int_token = token<int_>;
> using plus_token = token<lit_c<'+'>>;

копипаст-дружественная версия

Эти два определения создают псевдонимы типов для парсеров наших токенов. Для компилятора не имеет значения, используем ли мы<plus_token>или<token><<><lit_c><<'+'>>>, поскольку они относятся к одному и тому же типу. Но это облегчает понимание кода парсера.

Теперь мы можем определить наш парсер выражений, используя эти токены:

> using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;

Мы можем использовать его так же, как<exp_parser4>:

> exp_parser5::apply<BOOST_METAPARSE_STRING("11 + 2")>::type
boost_::mpl::vector<mpl_::integral_c<int, 11>, mpl_::char_<'+'>, mpl_::integral_c<int, 2> >
[Note] Note

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

Было бы неплохо, если бы мы также могли оценить выражение. Вместо того, чтобы возвращать а<vector>в результате разбора, мы должны возвращать оцениваемое выражение. Например, результат разбора<"11 + 2">должен быть<mpl_::integral_c<int,13>>.

Metaparse предоставляет<transform>, которые мы можем использовать для реализации этого:

> #include <boost/metaparse/transform.hpp>

Это можно использовать для преобразования результата парсера. Например, у нас есть парсер<sequence><<int_token,plus_token,int_token>>, который возвращает<vector>. Мы хотим превратить это<vector>в число, которое является результатом оценки выражения. Нам нужно передать<transform><sequence><<...>>парсер и функцию, которая превращает<vector>в нужный нам результат. Для начала давайте создадим этуметафункцию:

> #include <boost/mpl/plus.hpp>
> #include <boost/mpl/at.hpp>
> template <class Vector> \
...> struct eval_plus : \
...>   boost::mpl::plus< \
...>     typename boost::mpl::at_c<Vector, 0>::type, \
...>     typename boost::mpl::at_c<Vector, 2>::type \
...>   > {};

копипастная версия

[Note] Note

Обратите внимание, что если последним персонажем вашей команды является персонаж<\>в Metashell, то оболочка предполагает, что вы продолжите вводить ту же команду и ждете этого, прежде чем оценивать свою команду. Когда Metashell ждет вторую (или третью, или четвертую и т.д.) строку команды, она использует специальную подсказку<...>>.

Используя<boost::mpl::at_c>, он берет первый (индекс 0) и третий (индекс 2) элементы<vector>, что является результатом разбора с<sequence><<...>>и добавляет их. Примером может служить<vector>:

> eval_plus< \
...>  boost::mpl::vector< \
...>    mpl_::integral_c<int, 11>, \
...>    mpl_::char_<'+'>, \
...>    mpl_::integral_c<int, 2> \
...>  >>::type
mpl_::integral_c<int, 13>

копипастная версия

Мы можем использовать<eval_plus>для построения парсера, который оценивает выражение, которое он парсирует:

> #include <boost/mpl/quote.hpp>
> using exp_parser6 = \
...> build_parser< \
...>   transform< \
...>     sequence<int_token, plus_token, int_token>, \
...>     boost::mpl::quote1<eval_plus> \
...>   > \
...> >;

копипастный дружественный вариант

[Note] Note

Обратите внимание, что мы должны использовать<boost::mpl::quote1>, чтобы превратить нашу<eval_plus>метафункциювкласс метафункций.

<transform>анализирует вход с использованием<sequence><<int_token,plus_token,int_token>>и преобразует результат этого с использованием<eval_plus>. Давайте попробуем:

> exp_parser6::apply<BOOST_METAPARSE_STRING("11 + 2")>::type
mpl_::integral_c<int, 13>

Мы создали простое выражение parser. Следующая диаграмма показывает, как это работает:

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

Он использует<sequence>для разбора различных элементов (первое число, символ<+>и второе число) и строит<vector>. Окончательный результат рассчитывается из этого<vector>парсером<transform>.

[Note] Note

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

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

[Note] Note

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

Мы не можем решить эту проблему с<sequence>, поскольку мы не знаем, сколько чисел будет иметь вход. Нам нужен парсер, который:

  • Уравнивает первое число
  • сохраняет разбор<+<number>>элементов до конца ввода

Парсирование первого числа — это то, что мы уже можем сделать: парсер<int_token>делает это за нас. Сравнение<+<number>>элементов более сложное. Metaparse предлагает различные инструменты для этого. Самый простой из них<repeated>:

> #include <boost/metaparse/any.hpp>

<repeated>нужен парсер (который анализирует один<+ <number>>элемент), и он продолжает анализировать вход с ним, насколько это возможно. Для нас это будет означать весь вклад. Давайте создадим парсер для наших выражений, используя его:

> using exp_parser7 = \
...> build_parser< \
...>   sequence< \
...>     int_token,                                /* The first <number> */ \
...>     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */ \
...>   > \
...> >;

копипастная версия

У нас есть<sequence>с двумя элементами:

  • Первое число<int_token>
  • <+<number>>части

Вторая часть представляет собой<repeated>, который анализирует<+<number>>элементы. Один такой элемент разбирается<sequence><<plus_token, int_token>>. Это просто последовательность символа<+>и числа.

Давайте попробуем разобрать выражение, используя это:

> exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type

Вот отформатированная версия результата, которую легче прочитать:

boost_::mpl::vector<
  // The result of int_token
  mpl_::integral_c<int, 1>,
  // The result of repeated< sequence<plus_token, int_token> >
  boost_::mpl::vector<
    boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2> >,
    boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 3> >,
    boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 4> >
  >
>

В результате получается<vector>из двух элементов. Первый элемент этого<vector>является результатом разбора входа с<int_token>, второй элемент этого<vector>является результатом разбора входа с<repeated><< ><sequence><<plus_token,int_token>>>. Вторым элементом является<vector>. Каждый элемент этого<vector>является результатом разбора входа с<sequence><<plus_token,int_token>>один раз. Вот диаграмма, показывающая, как<exp_parser7>парсирует вход<1+ 2+3+4>:

Диаграмма показывает, что<+<number>>элементы парсируются<sequence><<plus_token, int_token>>элементов, и их результаты собираются<repeated>, который конструирует<vector>этих результатов. Значение первого<<number>>и этого<vector>помещаются в другое<vector>, которое является результатом разбора.

[Note] Note

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

Конечным результатом здесь является пара первого числа и<vector>остальных значений. Чтобы вычислить результат, нам нужно обработать эту структуру данных. Давайте приведем пример, который мы только что рассмотрели. Это облегчит тестирование кода, вычисляющего конечный результат из этой структуры:

> using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;

Теперь мы можем написать метафункцию шаблона, превращающую эту структуру в результат вычисления, которое представляет эта структура.

[Note] Note

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

У нас есть<vector>, содержащий еще<vector>. Поэтому нам нужно будет уметь обобщать элементы разных<vector>с. Для этого мы можем использовать<boost::mpl::fold>метафункцию:

> #include <boost/mpl/fold.hpp>

С этойметафункциеймы можем повторить<vector>парсированных чисел и суммировать их. Мы можем предоставить емуметафункцию, принимая два аргумента: сумму, которую мы имеем до сих пор, и следующий элемент<vector>. Этаметафункциябудет востребована для каждого элемента<vector>.

[Note] Note

Это очень похоже на алгоритм<std::accumulate>.Boost.MPLтакже предоставляет<boost::mpl::accumulate>, что является синонимом<boost::mpl::fold>. Этот учебник (и Metaparse) использует имя<fold>.

Начнем с простого случая:<vector>чисел. Рассмотрим, например, следующие элементы<vector>:

> using vector_of_numbers = \
...> boost::mpl::vector< \
...>   boost::mpl::int_<2>, \
...>   boost::mpl::int_<5>, \
...>   boost::mpl::int_<6> \
...> >;

дружественная к копированию версия

Мы напишемшаблон метафункции,<sum_vector>для суммирования элементов<vector>чисел:

> template <class Vector> \
...> struct sum_vector : \
...>    boost::mpl::fold< \
...>      Vector, \
...>      boost::mpl::int_<0>, \
...>      boost::mpl::lambda< \
...>        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2> \
...>      >::type \
...>    > \
...>  {};

копипастная версия

Этаметафункцияиспользует<vector>для обобщения элементов в качестве аргумента и использует<boost::mpl::fold>для вычисления суммы.<boost::mpl::fold>использует три аргумента:

  • Контейнер для подведения итогов. Это<Vector>.
  • Начальное значение длясуммы, которую мы имеем до сих пор. Использование<0>означает, что мы хотим начать сумму с<0>.
  • Функция вызова в каждой итерации при зацикливании над контейнером. В нашем примере мы используем выражениелямбда, которое является выражением, обернутым<boost::mpl::lambda>. Это выражение объединяет два аргумента<boost::mpl::plus>. Выражение лямбда относится к его аргументам<boost::mpl::_1>и<boost::mpl::_2>.

Давайте попробуем этуметафункцию:

> sum_vector<vector_of_numbers>::type
mpl_::integral_c<int, 13>

Работает, как и ожидалось. Вот диаграмма, показывающая, как это работает:

Как показано на диаграмме,<boost::mpl::fold>оценивает выражение лямбда для каждого элемента<vector>и передает результат предыдущей оценки следующему вызову выражения лямбда.

У нас естьметафункция, которая может суммировать<vector>чисел. Результатом разбора<+<number>>элементов является<vector>из<vector>с. В качестве примера можно привести<temp_result>:

boost_::mpl::vector<
  // The result of int_token
  mpl_::integral_c<int, 1>,
  // The result of repeated< sequence<plus_token, int_token> >
  boost_::mpl::vector<
    boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2> >,
    boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 3> >,
    boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 4> >
  >
>

Сначала подведем итоги<repeated><<...>>с использованием<boost::mpl::fold>. Это<vector>из<vector>, но это нормально.<boost::mpl::fold>не заботится о том, каковы элементы<vector>. Они могут быть числами<vector>или чем-то еще. Функция, которую мы используем, чтобы сложить два числа вместе (что было выражением лямбда в нашем предыдущем примере), получает эти элементы в качестве аргумента и имеет дело с ними. Таким образом, чтобы обобщить элементы<vector>s, которые мы получаем в результате разбора с<repeated><<...>>, нам нужно написатьметафункцию, которая может иметь дело с этими элементами. Одним из таких элементов является<boost_::mpl::vector<mpl_::char<'+'>, mpl_::integral_c<int,2>>>. Вотметафункция, которую можно использовать в<boost::mpl::fold>:

> template <class Sum, class Item> \
...>   struct sum_items : \
...>     boost::mpl::plus< \
...>       Sum, \
...>       typename boost::mpl::at_c<Item, 1>::type \
...>     > \
...> {};

дружественная версия

Эта функция принимает два аргумента:

  • <Sum>, что является числом. Это краткое изложение уже обработанных элементов.
  • <Item>, следующий пункт<vector>. Эти элементы имеют размер<vector>с два: результат разбора символа<+>и числа.

Метафункциядобавляет сумму, которую мы имеем до сих пор, и следующее число вместе, используя<boost::mpl::plus>.метафункция. Чтобы получить следующий номер из<Item>, он использует<boost::mpl::at_c>. Попробуем<sum_items>:

> sum_items< \
...>   mpl_::integral_c<int, 1>, \
...>   boost::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2>> \
...> >::type
mpl_::integral_c<int, 3>

дружественная версия

Мы позвонили<sum_items>со значениями<temp_result>и увидели, что он работает так, как ожидалось: он добавил частичную сумму<mpl_::integral_c<int,1>>к следующему числу<mpl_::integral_c<int,2>>.

<boost::mpl::fold>может суммировать список, который мы получаем в результате разбора<+ <number>>элементов ввода, поэтому нам нужно сначала извлечь этот список из<temp_result>:

> boost::mpl::at_c<temp_result, 1>::type

Вот отформатированная версия результата:

boost_::mpl::vector<
  boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2>>,
  boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 3>>,
  boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 4>>
>

Это второй элемент вектора<temp_result>(первый — значение первого элемента<<number>>). Давайте попробуем сложить для этого:

> \
...> boost::mpl::fold< \
...>   boost::mpl::at_c<temp_result, 1>::type, /* The vector to summarise */ \
...>   boost::mpl::int_<0>, /* The value to start the sum from */ \
...>   boost::mpl::quote2<sum_items> /* The function to call in each iteration */ \
...> >::type
mpl_::integral_c<int, 9>

копипастная версия

[Note] Note

Мы используем<sum_items>в качестве функции вызова в каждой итерации. Мы передаемметафункцию<sum_items>другомуметафункцию<boost::mpl::fold>в качестве аргумента. Чтобы сделать это, нам нужно превратить его в класс метафункцийшаблона, используя<boost::mpl::quote2><2>.

Как мы видели, результатом этого является сумма элементов, которая была<9>в нашем случае. Вот диаграмма, показывающая, как работает<boost::mpl::fold>:

Он начинается со значения<boost::mpl::int_<0>>и добавляет элементы<boost_::mpl::vector>, содержащие результаты разбора один за другим. Диаграмма показывает, как подрезультаты рассчитываются, а затем используются для дальнейших расчетов.

[Note] Note

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

Давайте использовать<sum_items>с<boost::mpl::fold>для построения парсера, который суммирует значения, исходящие от<+<number>>элементов. Мы можем расширить парсер, который мы использовали в<exp_parser7>, обернув<repeated><<...>>часть<transform>, что преобразует результат<repeated><<...>>с помощью только что созданной нами складывающейся экспрессии:

> using exp_parser8 = \
...> build_parser< \
...>   sequence< \
...>     int_token, /* parse the first <number> */ \
...>     transform< \
...>       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */ \
...> \
...>       /* lambda expression summarising the "+ <number>" elements using fold */ \
...>       boost::mpl::lambda< \
...>         /* The folding expression we have just created */ \
...>         boost::mpl::fold< \
...>           boost::mpl::_1, /* the argument of the lambda expression, the result */ \
...>                           /* of the repeated<...> parser */ \
...>           boost::mpl::int_<0>, \
...>           boost::mpl::quote2<sum_items> \
...>         > \
...>       >::type \
...>     > \
...>   > \
...> >;

дружественная версия

Он использует<transform>, чтобы превратить результат предыдущей версии нашего парсера в тот, который суммирует элементы<+<number>>. Давайте попробуем:

> exp_parser8::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type
boost_::mpl::vector<mpl_::integral_c<int, 1>, mpl_::integral_c<int, 9> >

Это возвращает пару чисел в результате разбора: первое число и сумму остальных. Чтобы получить значение всего выражения, нужно сложить эти два числа вместе. Мы можем расширить наш парсер, чтобы сделать это последнее дополнение:

> using exp_parser9 = \
...> build_parser< \
...>   transform< \
...>     /* What we had so far */ \
...>     sequence< \
...>       int_token, \
...>       transform< \
...>         repeated<sequence<plus_token, int_token>>, \
...>         boost::mpl::lambda< \
...>           boost::mpl::fold< \
...>             boost::mpl::_1, \
...>             boost::mpl::int_<0>, \
...>             boost::mpl::quote2<sum_items> \
...>           > \
...>         >::type \
...>       > \
...>     >, \
...>     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */ \
...>   > \
...> >;

дружественная версия

<exp_parser9>заворачивает парсер, который мы имели до сих пор (что дает нам два элемента<vector>в результате) с<transform>, чтобы добавить элементы этих двух элементов<vector>вместе. Поскольку два элемента<vector>являются<vector>числами, мы можем (повторно) использовать для этого<sum_vector>метафункцию. Давайте попробуем:

> exp_parser9::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type
mpl_::integral_c<int, 10>

Это дает нам правильный результат, но это очень неэффективно. Давайте посмотрим, почему:

В этом процессе есть два цикла:

  • Первый<repeated>петли над входом для разбора всех<+ <number>>элементов. В этом случае<vector>.<Loop1>на рисунке
  • <boost::mpl::fold>зацикливается на этом<vector>, чтобы суммировать элементы.<Loop2>на рисунке
[Note] Note

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

[Note] Note

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

Было бы неплохо, если бы две петли можно было слить воедино и временный<vector>не пришлось бы строить посередине (не забывайте: нет такой вещи, каксборщик мусорадля шаблонного метапрограммирования). Как только вы создадите шаблон, он будет доступен до конца ... компиляции.

Метапарс обеспечивает<foldl>парсерный комбинатор:

> #include <boost/metaparse/foldl.hpp>

Это почти то же самое, что<boost::mpl::fold>, но вместо того, чтобы принять<vector>в качестве первого аргумента, который исходил из повторного применения парсера<sequence><<plus_token,int_token>>на входе, он принимает сам парсер.<foldl>парсирует вход и вычисляет сводку на лету. Вот как мы можем написать наш парсер, используя его:

> using exp_parser10 = \
...> build_parser< \
...>   transform< \
...>     sequence< \
...>       int_token, \
...>       foldl< \
...>         sequence<plus_token, int_token>, \
...>         boost::mpl::int_<0>, \
...>         boost::mpl::quote2<sum_items> \
...>       > \
...>     >, \
...>     boost::mpl::quote1<sum_vector>> \
...> >;

копипаст-дружественная версия

Ниже представлены форматированные версии<exp_parser9>и<exp_parser10>бок о бок:

//            exp_parser9                                       exp_parser10
build_parser<                                       build_parser<
  transform<                                          transform<
    sequence<                                           sequence<
      int_token,                                          int_token,
      transform<                                          foldl<
        repeated<sequence<plus_token, int_token>>,          sequence<plus_token, int_token>,
        boost::mpl::lambda<
          boost::mpl::fold<
            boost::mpl::_1,
            boost::mpl::int_<0>,                            boost::mpl::int_<0>,
            boost::mpl::quote2<sum_items>                   boost::mpl::quote2<sum_items>
          >
        >::type
      >                                                   >
    >,                                                  >,
    boost::mpl::quote1<sum_vector>                      boost::mpl::quote1<sum_vector>
  >                                                   >
>                                                   >

копипаст-дружественная версия

В<exp_parser10>"_<repeated>, а затем<transform>с<boost::mpl::fold>_" часть (средний блок<exp_parser9>) была заменена одним<foldl>парсером, который делает то же самое, но без построения<vector>в середине. Можно использовать то же начальное значение<boost::mpl::int_<0>>и функцию обратного вызова<sum_items>.

Вот диаграмма, показывающая, как работает<exp_parser10>:

В этом случае результаты парсеров<sequence><<plus_token, int_token>>передаются непосредственно алгоритму складывания без промежуточного<vector>. Вот диаграмма, показывающая<exp_parser9>и<exp_parser10>бок о бок, чтобы было легче увидеть разницу:

[Note] Note

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

Это решение все еще можно улучшить.<foldl>суммирование элементов<+<number>>начинается с<0>, и как только это будет сделано, мы добавим значение первого<<number>>входа к нему в первой итерации. Было бы проще, если бы<foldl>могли использовать значение первого<<number>>в качестве начального значения суммы, которую мы имеем до сих пор. Метапарс предоставляет<foldl_start_with_parser>для этого:

> #include <boost/metaparse/foldl_start_with_parser.hpp>

<foldl_start_with_parser>почти то же самое, что<foldl>. Разница в том, что вместо начальногозначениядля суммы требуетсяпарсер. Сначала он парсирует вход с этим парсером и использует значение, которое он возвращает в качестве начального значения. Вот как мы можем реализовать наш парсер, используя его:

> using exp_parser11 = \
...> build_parser< \
...>   foldl_start_with_parser< \
...>     sequence<plus_token, int_token>, /* apply this parser repeatedly */ \
...>     int_token, /* use this parser to get the initial value */ \
...>     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */ \
...>   > \
...> >;

копипастная версия

Эта версия<exp_parser>использует<foldl_start_with_parser>. Эта реализация более компактна, чем предыдущие версии. В этом нет<sequence>элемента: первый<<number>>разбирается<int_token>и его значение используется в качестве начального значения для резюме. Давайте попробуем:

> exp_parser11::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type
mpl_::integral_c<int, 10>

Он возвращает тот же результат, что и предыдущая версия, но работает по-другому. Вот диаграмма, показывающая, как работает эта реализация:

[Note] Note

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

Наши парсеры теперь поддерживают выражения, слагающие числа вместе. В этом разделе мы добавим поддержку оператора<->, чтобы можно было оценить такие выражения, как<1+2- 3>.

[Note] Note

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

В настоящее время мы используем<plus_token>для разбора оператора, который должен быть<+>. Мы можем определить новый токен для разбора символа<->:

> using minus_token = token<lit_c<'-'>>;

Мы должны построить парсер, который принимает символ<+>или<->. Это может быть реализовано с помощью<one_of>:

> #include <boost/metaparse/one_of.hpp>

<one_of><<plus_token,minus_token>>является парсером, который принимает либо<+>(с использованием<plus_token>), либо<->(с использованием<minus_token>) символ. Результатом анализа является результат успешного парсера.

[Note] Note

Вы можете дать любой парсер<one_of>, поэтому возможно, что более одного из них может разобрать вход. В этих случаях порядок имеет значение:<one_of>пытается сравнять вход с парсерами слева направо, и первый, который преуспевает, выигрывает.

Используя это, мы можем заставить наш парсер принимать вычитания:

> using exp_parser12 = \
...> build_parser< \
...>   foldl_start_with_parser< \
...>     sequence<one_of<plus_token, minus_token>, int_token>, \
...>     int_token, \
...>     boost::mpl::quote2<sum_items> \
...>   > \
...> >;

копипаст-дружественная версия

Он использует<one_of><<plus_token,minus_token>>в качестве разделителя для чисел. Давайте попробуем:

> exp_parser12::apply<BOOST_METAPARSE_STRING("1 + 2 - 3")>::type
mpl_::integral_c<int, 6>

Результат неправильный. Причина этого в том, что<sum_items>функция, которую мы суммируем, игнорирует, какой оператор использовался, и предполагает, что он всегда<+>.

[Note] Note

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

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

Прежде всего нам понадобится<boost::mpl::minus>метафункциядля осуществления вычитания:

> #include <boost/mpl/minus.hpp>

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

> template <class L, char Op, class R> struct eval_binary_op;
> template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
> template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};

копипаст-дружественная версия

Первая команда объявляет метафункцию<eval_binary_op>. Первый и третий аргументы — это левый и правый операнды, а второй — оператор.

[Note] Note

Обратите внимание, что он не удовлетворяет ожиданиям метафункции шаблона, поскольку он принимает оператора как<char>, а не как<class>(или<typename>) аргумент. Для простоты мы все равно назовем его метафункцией.

Вторая и третья команды определяют операцию для случаев, когда оператором является<+>и<->. Когда называется метафункция<eval_binary_op>, компилятор C++ выбирает одно из определений на основе оператора. Если у вас есть опыт функционального программирования, этот подход может быть вам знаком. Попробуем<eval_binary_op>:

> eval_binary_op<boost::mpl::int_<11>, '+', boost::mpl::int_<2>>::type
mpl_::integral_c<int, 13>
> eval_binary_op<boost::mpl::int_<13>, '-', boost::mpl::int_<2>>::type
mpl_::integral_c<int, 11>

копипаст-дружественная версия

Вы также можете попробовать использовать его с оператором, которого он не ожидает. Например,<'*'>. Вы увидите, что компилятор C++ жалуется на то, что запрошенная версия шаблона<eval_binary_op>не была определена. Это решение может быть расширено, и поддержка оператора<'*'>всегда может быть добавлена позже.

Давайте напишем метафункцию, которую мы можем использовать из парсера складывания для оценки выражений с помощью операторов<+>и<->. Это требует двух аргументов:

  • Частичный результат мы уже оценили. (Это было резюме, которое мы оценивали до сих пор, но сейчас мы делаем его более общей оценкой). Это левый операнд, число.
  • Результат разбора<(+|-) <number>>. Это a<vector>, содержащий два элемента: символ, представляющий оператора<+>или<->и значение<<number>>. Номер является правильным операндом.

Давайте напишем метафункцию<binary_op>, которая принимает эти аргументы и вызывает<eval_binary_op>:

> template <class S, class Item> \
...> struct binary_op : \
...>   eval_binary_op< \
...>     S, \
...>     boost::mpl::at_c<Item, 0>::type::value, \
...>     typename boost::mpl::at_c<Item, 1>::type \
...>   > \
...>   {};

копипаст-дружественная версия

Этаметафункцияберет оператор (первый элемент) и правый операнд (второй элемент) из<Item>. Оператор — класс, представляющий символ, такой как<mpl_::char_<'+'>>. Чтобы получить значение символа, нужно получить доступ к его<::value>. Например,<mpl_::char<'+'>::value>—<'+'>. Поскольку<eval_binary_op>принимает это значение символа в качестве второго аргумента, мы должны были передать<boost::mpl::at_c<Item,0>::type::value>ему. Давайте попробуем:

> binary_op<boost::mpl::int_<11>, boost::mpl::vector<boost::mpl::char_<'+'>, boost::mpl::int_<2>>>::type
mpl_::integral_c<int, 13>

Мы передали ему число (805) и<vector>символа (807) и другое число (808). Они добавили две цифры, как и ожидалось. Давайте использовать эту функцию в качестве третьего аргумента<foldl_start_with_parser>:

> using exp_parser13 = \
...> build_parser< \
...>   foldl_start_with_parser< \
...>     sequence<one_of<plus_token, minus_token>, int_token>, \
...>     int_token, \
...>     boost::mpl::quote2<binary_op> \
...>   > \
...> >;

копипаст-дружественная версия

Вместо<binary_op>используется<sum_items>. Давайте попробуем:

> exp_parser13::apply<BOOST_METAPARSE_STRING("1 + 2 - 3")>::type
mpl_::integral_c<int, 0>

Это возвращает правильный результат.

[Note] Note

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

Мы поддерживаем сложение и вычитание. Давайте также поддержим умножение.

[Note] Note

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

Мы можем расширить решение, которое мы создали для сложения и вычитания. Для этого нужно добавить поддержку умножения<eval_binary_op>:

> #include <boost/mpl/times.hpp>
> template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};

копипаст-дружественная версия

Мы должны были включить<<boost/mpl/times.hpp>>, чтобы получить<boost::mpl::times>метафункцию, а затем мы могли бы расширить<eval_binary_op>, чтобы поддержать<*>оператора. Мы можем попробовать:

> eval_binary_op<boost::mpl::int_<3>, '*', boost::mpl::int_<4>>::type
mpl_::integral_c<int, 12>

Это работает, как и ожидалось. Давайте создадим токен для разбора символа<*>:

> using times_token = token<lit_c<'*'>>;

Теперь мы можем расширить наш парсер, чтобы принять символ<*>в качестве оператора:

> using exp_parser14 = \
...> build_parser< \
...>   foldl_start_with_parser< \
...>     sequence<one_of<plus_token, minus_token, times_token>, int_token>, \
...>     int_token, \
...>     boost::mpl::quote2<binary_op> \
...>   > \
...> >;

копипаст-дружественная версия

Эта версия принимает в качестве оператора символ<+>,<->или<*>. Давайте попробуем это:

> exp_parser14::apply<BOOST_METAPARSE_STRING("2 * 3")>::type
mpl_::integral_c<int, 6>

Это работает, как и ожидалось. Давайте попробуем другое, чуть более сложное выражение:

> exp_parser14::apply<BOOST_METAPARSE_STRING("1 + 2 * 3")>::type
mpl_::integral_c<int, 9>

Это возвращает неправильный результат. Значение этого выражения должно быть<7>, а не<9>. Проблема в том, что наша текущая реализация не учитывает приоритет оператора. Оно рассматривает это выражение как<(1+ 2)*3>, тогда как мы ожидаем, что оно будет<1+ (2*3)>, поскольку сложение имеет более высокий приоритет, чем умножение.

[Note] Note

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

Давайте сделаем так, чтобы у разных операторов был разный приоритет. Для этого мы определяем новый парсер для разбора выражений, содержащих только операторы<*>(то есть оператор с наименьшим приоритетом):

> using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;

<mult_exp1>может анализировать выражения, содержащие только<*>оператора. Например,<3* 2>или<6 *7*8>. Теперь мы можем создать парсер, поддерживающий только операторов<+>и<->, но вместо разделения чиселс этими операторами мы разделим выражения, содержащие только операторов<*>. Это означает, что выражение<1 *2+3* 4>интерпретируется как выражения<1* 2>и<3 *4>, разделенные оператором<+>. Число (например,<13>) является особым случаем выражения, содержащего только<*>операторов.

Вот парсер, реализующий это:

> using exp_parser15 = \
...> build_parser< \
...>   foldl_start_with_parser< \
...>     sequence<one_of<plus_token, minus_token>, mult_exp1>, \
...>     mult_exp1, \
...>     boost::mpl::quote2<binary_op> \
...>   > \
...> >;

дружественная к копированию версия

Это почти то же самое, что<exp_parser13>. Разница лишь в том, что он использует<mult_exp1>везде, где<exp_parser13>использовал<int_token>. Давайте попробуем:

> exp_parser15::apply<BOOST_METAPARSE_STRING("1 + 2 * 3")>::type
mpl_::integral_c<int, 7>

При этом учитываются правила приоритета. Следующая диаграмма показывает, как это работает:

Субэкспрессии, использующие только операторы<*>, оцениваются<mult_exp1>и рассматриваются как единичные единицы при интерпретации выражений с использованием операторов<+>и<->. Номера, не окруженные операторами<*>, также рассматриваются как операторы, использующие только<*>(не содержащие операций, но число).

Если вам нужно больше слоев (например, введение оператора<^>), вы можете расширить это решение с помощью дополнительных слоев. Порядок слоев определяет приоритет операторов.

[Note] Note

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

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

> #include <boost/mpl/divides.hpp>
> template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
> using divides_token = token<lit_c<'/'>>;
> using mult_exp2 = \
...> foldl_start_with_parser< \
...>   sequence<one_of<times_token, divides_token>, int_token>, \
...>   int_token, \
...>   boost::mpl::quote2<binary_op> \
...> >;
> using exp_parser16 = \
...> build_parser< \
...>   foldl_start_with_parser< \
...>     sequence<one_of<plus_token, minus_token>, mult_exp2>, \
...>     mult_exp2, \
...>     boost::mpl::quote2<binary_op> \
...>   > \
...> >;

копипаст-дружественная версия

Мы должны включить<<boost/mpl/divides.hpp>>, чтобы получитьметафункциюдля выполнения деления. Нам нужно расширить метафункцию<eval_binary_op>для поддержки деления. Нам пришлось ввести новый токен<divides_token>, который может разобрать</>символ.

Мы расширили<mult_exp1>, чтобы принять<times_token>или<divides_token>в качестве оператора. Этот расширенный парсер называется<mult_exp2>.

Мы написали новый парсер<exp_parser16>, который является таким же, как<exp_parser15>, но использует<mult_exp2>вместо<mult_exp1>. Это позволяет также анализировать выражения с помощью деления (и этот новый оператор имеет правильный приоритет). Давайте попробуем:

> exp_parser16::apply<BOOST_METAPARSE_STRING("8 / 4")>::type
mpl_::integral_c<int, 2>

Это работает, как и ожидалось. Но какова должна быть стоимость<8 /4/2>? Ответ может быть либо<1>, либо<4>в зависимости от ассоциативности оператора деления. Если он остается ассоциативным, то это выражение интерпретируется как<(8 /4)/2>, а результат —<1>. Если оно правильно ассоциативно, то это выражение интерпретируется как<8 /(4/2)>, а результат —<4>.

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

[Note] Note

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

Вот диаграмма, показывающая, как наш текущий парсер обрабатывает выражение<8/ 4/2>:

Он берет первое число<8>, делит его на второе<4>, а затем делит результат на третье<2>. Это означает, что в нашей нынешней реализации разделение остается ассоциативным:<8/ 4/2>означает<(8/4)/2>.

Следует также отметить, что начальное значение<8>и список значений<foldl>итерирует значение</4>,</ 2>.

[Note] Note

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

<foldl>многократно применяет парсер и повторяет результаты разбораслевасправа. (Вот откуда взялось имя<l>). Метапарза обеспечивает другой складывающийся парсерный комбинатор<foldr>. Он также применяет парсер на входе, но он повторяется отсправаслева по результатам.

Подобно<foldl_start_with_parser>, Метапарс также предоставляет<foldr_start_with_parser>. Основное различие между этими двумя решениями<foldl_start_with_parser>и<foldr_start_with-parser>заключается в том, что, хотя<foldl_start_with_parser>рассматриваетпервоечисло как особое,<foldr_start_with_parser>рассматриваетпоследнеечисло как особое. Это может показаться странным, но подумайте об этом: если вы хотите суммировать элементы справа налево, ваше начальное значение должно быть последним элементом, а не первым.

Из-за вышеупомянутой разницы<foldr_start_with_parser>не является заменой<foldl_start_with_parser>. В то время как список значений<foldl>повторяется над «<8>», «</4>», «</2>», список значений<foldlr>должен повторяться над «<2>», «<4/>», «<8/>».

Это означает, что функция, которую мы используем для«добавить»новое значение к уже оцененной части выражения (это было<binary_op>до сих пор), должна быть подготовлена для взятия следующего оператора и операнда в обратном порядке (например, путем взятия «<4/>» вместо «</4>». Для этого мы пишем другуюметафункцию:

> template <class S, class Item> \
...> struct reverse_binary_op : \
...>   eval_binary_op< \
...>     typename boost::mpl::at_c<Item, 0>::type, \
...>     boost::mpl::at_c<Item, 1>::type::value, \
...>     S \
...>   > \
...>   {};

дружественная к копированию версия

Существует несколько различий между<binary_op>и<reverse_binary_op>:

  • <Item>, который является<vector>, как ожидается, будет<[operator,operand]>в<binary_op>и<[operand,operator]>в<reverse_binary_op>.
  • Обе версии используют<eval_binary_op>для оценки субэкспрессии, но<binary_op>рассматривает<S>, значение, представляющее уже оцененную часть выражения как левый операнд, в то время как<reverse_binary_op>рассматривает его как правый операнд. Это потому, что в первом случае мы идем слева направо, а во втором случае мы идем справа налево.

Мы должны включить<foldr_start_with_parser>:

> #include <boost/metaparse/foldr_start_with_parser.hpp>

Мы можем переписать<mult_exp>, используя<foldr_start_with_parser>:

> using mult_exp3 = \
...> foldr_start_with_parser< \
...>   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */ \
...>   int_token, /* The parser parsing the last number */ \
...>   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */ \
...>                                         /* of applying the above parser */ \
...> >;

копипастный дружественный вариант

Это почти то же самое, что<mult_exp2>, но...

  • ... парсер применял многократные парсеры<<number> <operator>>элементов вместо<<operator><number>>элементов<mult_exp2>.
  • Эта версия использует<reverse_binary_op>вместо<binary_op>в качестве функции, которая называется для каждого результата применения вышеупомянутого парсера.

Мы можем создать новую версию<exp_parser>, которая использует<mult_exp3>вместо<mult_exp2>:

> using exp_parser17 = \
...> build_parser< \
...>   foldl_start_with_parser< \
...>     sequence<one_of<plus_token, minus_token>, mult_exp3>, \
...>     mult_exp3, \
...>     boost::mpl::quote2<binary_op> \
...>   > \
...> >;

копипастный дружественный вариант

Единственное различие между<exp_parser17>и предыдущей версией<exp_parser16>заключается в том, что она использует обновленную версию<mult_exp>. Давайте попробуем этот парсер:

> exp_parser17::apply<BOOST_METAPARSE_STRING("8 / 4 / 2")>::type
mpl_::integral_c<int, 4>

Эта версия парсера даетдругойвозможный результат. Тот, который вы получаете, когда деление является правильным ассоциативным, что означает, что вышеупомянутое выражение оценивается как<8 /(4/2)>. Вот диаграмма, показывающая, как работает решение на основе<foldr_start_with_parser>:

Чтобы упростить сравнение двух решений, вот диаграмма, показывающая два подхода бок о бок:

Как мы видели, ассоциативность операторов можно контролировать, выбирая между складными решениями. Складные решения, идущие слева направо, реализуют левую ассоциативность, в то время как решения, идущие справа налево, реализуют правую ассоциативность.

[Note] Note

Обратите внимание, что складные решения, идущие слева направо, реализованы более эффективным способом, чем складывание справа налево. Поэтому, когда оба решения могут быть использованы, вы должны предпочесть складывание слева направо.

[Note] Note

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

Наш язык калькуляторов не поддерживает отрицательные числа. Чтобы получить отрицательное число, нужно сделать вычитание. Например, чтобы получить число<-13>, нужно оценить выражение<0 -13>.

Мы будем осуществлять<->в качестве унарного оператора. Поэтому выражение<-13>не будетотрицательным числом. Это будет унарный<->оператор, применяемый по номеру<13>.

Поскольку<->является оператором, он может использоваться несколько раз. Таким образом, выражение<---13>также является действительным и дает тот же результат, что и<-13>. Это означает, что любое число символов<->действительно перед числом.

Наш парсер может быть расширен для поддержки унарного оператора<->путем добавления нового слоя в список уровней приоритета. Это должно иметь наименьший приоритет, а это значит, что мы должны использовать этот новый слой там, где мы использовали<int_token>. Напишем новый парсер:

> #include <boost/mpl/negate.hpp>
> using unary_exp1 = \
...> foldr_start_with_parser< \
...>   minus_token, \
...>   int_token, \
...>   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type \
...> >;

копипаст-дружественная версия

Мы должны были включить<<boost/mpl/negate.hpp>>, чтобы получитьметафункцию.

<unary_exp1>реализуется с правой на левую складку: она начинается с числа (парсируется<int_token>) и обрабатывает<->символы по одному. Функция для каждого символа<->является лямбда-выражением, которое отрицает число. Таким образом, число отрицается для каждого символа<->.

Мы можем реализовать новую версию<mult_exp>и<exp_parser>. Они такие же, как<mult_exp2>и<exp_parser16>. Разница лишь в том, что они (непосредственно только<exp_parser18>) используют<unary_exp1>вместо<int_token>.

> using mult_exp4 = \
...> foldl_start_with_parser< \
...>   sequence<one_of<times_token, divides_token>, unary_exp1>, \
...>   unary_exp1, \
...>   boost::mpl::quote2<binary_op> \
...> >;
> using exp_parser18 = \
...> build_parser< \
...>   foldl_start_with_parser< \
...>     sequence<one_of<plus_token, minus_token>, mult_exp4>, \
...>     mult_exp4, \
...>     boost::mpl::quote2<binary_op> \
...>   > \
...> >;

копипаст-дружественная версия

Давайте попробуем эти новые парсеры:

> exp_parser18::apply<BOOST_METAPARSE_STRING("---13")>::type
mpl_::integral_c<int, -13>
> exp_parser18::apply<BOOST_METAPARSE_STRING("13")>::type
mpl_::integral_c<int, 13>

копипаст-дружественная версия

Он может правильно обращаться с отрицательными числами.

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

Можно добавить новый парсер для разбора (и оценки) выражений в паренах. Сначала мы вводим токены для разбора символов<(>и<)>:

> using lparen_token = token<lit_c<'('>>;
> using rparen_token = token<lit_c<')'>>;

копипаст-дружественная версия

Парен может содержать выражение с любыми операторами в нем, поэтому мы добавляем парсер для разбора (и оценки) выражения, содержащего операторов высшего приоритета:

> using plus_exp1 = \
...> foldl_start_with_parser< \
...>   sequence<one_of<plus_token, minus_token>, mult_exp4>, \
...>   mult_exp4, \
...>   boost::mpl::quote2<binary_op> \
...> >;

копипастная версия

Это было просто рефакторингом нашего последнего парсера для языка калькулятора. Мы можем построить парсер для нашего языка калькулятора, используя<build_parser><<plus_exp1>>сейчас. Напишем парсер для выражения paren:

> using paren_exp1 = sequence<lparen_token, plus_exp1, rparen_token>;

Это определение парсирует левый парен, затем полное выражение, за которым следует правый парен. Результатом разбора выражения paren является<vector>из трех элементов:<(>символ, значение выражения и<)>символ. Нам нужно только значение выражения, которое является средним элементом. Мы могли бы обернуть все это с помощью<transform>, который получает средний элемент и выбрасывает остальное, но нам не нужно. Это такая общая закономерность, что Метапарс предоставляет<middle_of>для этого:

> #include <boost/metaparse/middle_of.hpp>
> using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;

копипастная версия

Это почти то же самое, что и<paren_exp1>. Разница заключается в том, что результатом разбора будет значение обернутого выражения (результат парсера<plus_exp1>).

Определим парсер для первичного выражения, которое является числом или выражением в паренсе:

> using primary_exp1 = one_of<int_token, paren_exp2>;

Этот парсер принимает либо число, использующее<int_token>, либо выражение в паренах, использующее<paren_exp1>.

Повсюду, где можно написать число (парс 1113), можно написать и полное выражение в парен. Наша текущая реализация парсера парсирует<int_token>в<unary_exp>, поэтому нам нужно изменить это, чтобы использовать<primary_exp>вместо<int_token>.

Здесь есть проблема: это делает определения наших парсероврекурсивными. Подумайте об этом:

  • <plus_exp>использует<mult_exp>
  • <mult_exp>использует<unary_exp>
  • <unary_exp>использует<primary_exp>
  • <primary_exp>использует<paren_exp>
  • <paren_exp>использует<plus_exp>
[Note] Note

Поскольку мы редактируем различные реализации парсера в Metashell<paren_exp1>,<paren_exp2>и т. Д., Вы можете попытаться определить эти рекурсивные парсеры. В этом случае, когда вы позже попытаетесь создать парсер как часть библиотеки (сохранить среду Metashell в файле или повторно внедрить важные / успешные элементы), вы столкнетесь с этой проблемой.

Мы использовали псевдонимы типов<typedef>и<using>для определения парсеров. Мы можем делать это до тех пор, пока их определение не является рекурсивным. Мы не можем ссылаться на псевдоним типа, пока не определим его, и псевдонимы типа не могут быть объявлены вперед, поэтому мы не можем найти точку в рекурсивном цикле, где мы могли бы начать определять вещи.

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

Давайте сделаем<plus_exp>класс. Итак, в качестве первого шага давайте объявим это:

> struct plus_exp2;

Теперь мы можем написать остальные парсеры, и они могут ссылаться на<plus_exp2>:

> using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
> using primary_exp2 = one_of<int_token, paren_exp2>;
> using unary_exp2 = \
...> foldr_start_with_parser< \
...>   minus_token, \
...>   primary_exp2, \
...>   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type \
...> >;
> using mult_exp5 = \
...> foldl_start_with_parser< \
...>   sequence<one_of<times_token, divides_token>, unary_exp2>, \
...>   unary_exp2, \
...>   boost::mpl::quote2<binary_op> \
...> >;

копипастная версия

В определении этих парсеров нет ничего нового. Они создают иерархию, которую мы разработали в предыдущих разделах этого учебника. Единственное, чего не хватает<plus_exp2>:

> struct plus_exp2 : \
...> foldl_start_with_parser< \
...>   sequence<one_of<plus_token, minus_token>, mult_exp5>, \
...>   mult_exp5, \
...>   boost::mpl::quote2<binary_op> \
...> > {};

копипастный дружественный вариант

Это определение использует наследование вместо псевдонима типа. Теперь мы можем написать парсер для калькулятора, который также поддерживает парен:

> using exp_parser19 = build_parser<plus_exp2>;

Давайте попробуем этот парсер:

> exp_parser19::apply<BOOST_METAPARSE_STRING("(1 + 2) * 3")>::type
mpl_::integral_c<int, 9>

Наш парсер принимает и может иметь дело с паренами в выражениях.

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

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

Итак, давайте попробуем разобрать некоторые недействительные выражения и посмотрим, что произойдет:

> exp_parser19::apply<BOOST_METAPARSE_STRING("hello")>::type
<< compilation error >>

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

x__________________PARSING_FAILED__________________x<
  1, 1,
  boost::metaparse::v1::error::literal_expected<'('>
>

Вы можете увидеть форматированную версию выше. В реальном выходе нет разрывов линий. Это относительно легко обнаружить (благодаря части<____________>) и содержит ответы на основные вопросы, которые возникают при неудачном разборе:

  • гдеошибка? Это столбец<1>в линии<1>(внутри<BOOST_METAPARSE_STRING>). Это<1, 1>часть.
  • Что такое проблема?<literal_expected<'('>>Это немного вводит в заблуждение, так как содержит только часть проблемы. Открытый парен не единственный приемлемый токен здесь, число также было бы хорошо. Это вводящее в заблуждение сообщение об ошибке являетсянашейошибкой:мы(авторы парсера) должны сделать ошибки парсинга более описательными.

Как улучшить сообщения об ошибках? Давайте посмотрим, что пошло не так в предыдущем случае:

  • Это было<hello>.
  • <plus_exp2>пытался разобрать его.
  • <plus_exp2>попытался разобрать его, используя<mult_exp5>(при условии, что это начальное<mult_exp>в списке<+>/<->разделенных<mult_exp>с).
  • В 1179 г. он попытался его разобрать.
  • <mult_exp5>попытался разобрать его, используя<unary_exp2>(при условии, что это начальное<unary_exp>в списке<*>/</>разделенных<unary_exp>с).
  • В 1186 г. он попытался его разобрать.
  • <unary_exp2>разобрали все<->символы, используя<minus_token>. Не было ни одного из них (ввод начался с символа<h>).
  • <unary_exp2>пытался разобрать его, используя<primary_exp2>.
  • <primary_exp2>это:<one_of><<int_token,paren_exp2>>. Он попытался разобрать вход с<int_token>(который потерпел неудачу), а затем с<paren_exp2>(который также потерпел неудачу). Так что<one_of>не смог разобрать вход ни с одним из вариантов, и поэтому он также потерпел неудачу. В таких ситуациях<one_of>проверяет, какой парсер сделал наибольший прогресс (потребил большинство символов ввода), прежде чем выйти из строя, и предполагает, что это парсер, который пользователь намеревался использовать, таким образом, он возвращает сообщение об ошибке, исходящее от этого парсера. В этом примере ни один из парсеров не мог добиться какого-либо прогресса, и в этом случае<one_of>возвращает ошибку, исходящую от последнего парсера в списке. Это было<paren_exp2>, и оно ожидает, что выражение начнется с открытого парена. Вот откуда пришло сообщение об ошибке. Остальные слои не меняли и не улучшали это сообщение об ошибке, поэтому это было сообщение об ошибке, отображаемое пользователю.

Мы, авторы парсера, знаем: мы ожидаем там первичного выражения. Когда<one_of>терпит неудачу, это означает, что никто не был найден.

Чтобы вернуть пользовательские сообщения об ошибках (например,<missing_primary_expression>) пользователю, мы должны сначала определить эти сообщения об ошибках. Сообщения об ошибках представлены классами с некоторыми требованиями:

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

> #include <boost/metaparse/define_error.hpp>

Давайте определимсообщение об ошибке парсинга:

> BOOST_METAPARSE_DEFINE_ERROR(missing_primary_expression, "Missing primary expression");

Это определяет класс, называемый<missing_primary_expression>, представляющий это сообщение об ошибке. Нам нужно сделать так, чтобы наш парсер вернул это сообщение об ошибке, когда<one_of>выйдет из строя.

Давайте сначала определим<plus_exp>и<paren_exp>. Их определение не меняется:

> struct plus_exp3;
> using paren_exp4 = middle_of<lparen_token, plus_exp3, rparen_token>;

копипастная версия

Когда ввод не содержит числа (парсируется<int_token>) и выражения paren (парсируется<paren_exp4>), мы должны вернуть сообщение об ошибке<missing_primary_expression>. Мы можем сделать это, добавив третий парсер к<one_of<int_token,paren_exp4,...>>, который всегда терпит неудачу с этим сообщением об ошибке. Метапарс предоставляет<fail>для этого:

> #include <boost/metaparse/fail.hpp>

Теперь мы можем определить парсер<primary_exp>, используя его:

> using primary_exp3 = one_of<int_token, paren_exp4, fail<missing_primary_expression>>;

Он добавляет<fail><<missing_primary_expression>>к<one_of>в качестве последнего элемента. Поэтому, если ни один из «реальных» случаев не анализирует вводи, ни один из них не делает никакого прогресса до отказа, сообщение об ошибке будет<missing_primary_expression>.

Нам нужно определить остальные парсеры. Их определение такое же, как и раньше:

> using unary_exp3 = \
...> foldr_start_with_parser< \
...>   minus_token, \
...>   primary_exp3, \
...>   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type \
...> >;
> using mult_exp6 = \
...> foldl_start_with_parser< \
...>   sequence<one_of<times_token, divides_token>, unary_exp3>, \
...>   unary_exp3, \
...>   boost::mpl::quote2<binary_op> \
...> >;
> struct plus_exp3 : \
...> foldl_start_with_parser< \
...>   sequence<one_of<plus_token, minus_token>, mult_exp6>, \
...>   mult_exp6, \
...>   boost::mpl::quote2<binary_op> \
...> > {};
> using exp_parser20 = build_parser<plus_exp3>;

копипастная версия

Мы можем попытаться дать нашему новому парсеру недействительный вход:

> exp_parser20::apply<BOOST_METAPARSE_STRING("hello")>::type
<< compilation error >>
..... x__________________PARSING_FAILED__________________x<1, 1, missing_primary_expression> ....
<< compilation error >>

Сообщение об ошибке теперь более специфично для языка калькулятора. Это касается только одного случая, когда сообщения об ошибках могут быть улучшены. Другие случаи (например, отсутствие закрывающих зон, отсутствие операторов и т.д.) могут быть рассмотрены аналогичным образом.

Недостающие парены закрытия являются распространенными ошибками. Давайте посмотрим, как наши парсеры сообщают о них:

> exp_parser20::apply<BOOST_METAPARSE_STRING("(1+2")>::type
<< compilation error >>
..... x__________________PARSING_FAILED__________________x<1, 5, unpaired<1, 1, literal_expected<')'>>> ....
<< compilation error >>

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

> exp_parser20::apply<BOOST_METAPARSE_STRING("0+(1+2")>::type
mpl_::integral_c<int, 0>

Сейчас это становится странным. Мы анализируем<+ <mult_exp>>элементы, используя<foldl_start_with_parser>(см. определение<plus_exp3>).<foldl_start_with_parser>парсирует вход, насколько это возможно, и останавливается, когда он не может его разобрать. В приведенном выше вводе он анализирует<0>в качестве начального элемента, а затем пытается разобрать первый<+<mult_exp>>элемент. Но разбор<<mult_exp>>части терпит неудачу из-за отсутствующего закрывающего парена. Так<foldl_start_with_parser>останавливает и игнорирует эту неудачную часть входа.

Результатом вышесказанного является то, что мы анализируем только часть входа<0>, игнорируем «мусор» в конце и предполагаем, что значение выражения<0>. Это можно исправить, используя<entire_input>. Наш парсер отклонит ввод (из-за «мусора» в конце), но сообщение об ошибке не будет полезным. Поэтому мы используем другой подход.

Когда<foldl_start_with_parser>останавливается, мы должны проверить, есть ли там дополнительный сломанный<+ <mult_exp>>или нет. Когда это произойдет, мы должны сообщить, что не так с этим сломанным<+ <mult_exp>>(например, недостающий закрывающий парен). Metaparse предоставляет<fail_at_first_char_expected>для реализации таких валидаций.<fail_at_first_char_expected><<parser>>проверяет, как<parser>не может разобрать вход: когда он выходит из строя прямо при первом символе,<fail_at_first_char_expected>предполагает, что нет мусора и принимает вход. Когда<parser>потребляет символы из ввода до отказа,<fail_at_first_char_expected>предполагает, что существует нарушенное выражение и распространяет ошибку. Его можно использовать следующим образом:

> #include <boost/metaparse/fail_at_first_char_expected.hpp>
> #include <boost/metaparse/first_of.hpp>
> struct plus_exp4 : \
...> first_of< \
...>   foldl_start_with_parser< \
...>     sequence<one_of<plus_token, minus_token>, mult_exp6>, \
...>     mult_exp6, \
...>     boost::mpl::quote2<binary_op> \
...>   >, \
...>   fail_at_first_char_expected< \
...>     sequence<one_of<plus_token, minus_token>, mult_exp6> \
...>   > \
...> > {};
> using exp_parser21 = build_parser<plus_exp4>;

копипастная версия

<first_of>похож на<middle_of>, но сохраняет результат первого элемента, а не среднего. Мы используем его, чтобы сохранить «реальный» результат (результат<foldl_start_with_parser>) и отбросить фиктивный результат, идущий от<fail_at_first_char_expected>, когда в конце нет нарушенного выражения.<first_of>распространяет любую ошибку, исходящую от<fail_at_first_char_expected>.

Давайте попробуем это новое выражение парсер с отсутствующим закрывающим парен:

> exp_parser21::apply<BOOST_METAPARSE_STRING("0+(1+2")>::type
<< compilation error >>
..... x__________________PARSING_FAILED__________________x<1, 7, unpaired<1, 3, literal_expected<')'>>> ....
<< compilation error >>

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

Наш парсер предоставляет полезные сообщения об ошибках для отсутствующих паренсов закрытия, однако реализация парсера<plus_exp4>является длинной и повторяющейся: он содержит парсер для повторяющегося элемента<sequence><<><one_of><<plus_token, minus_token>, mult_exp6>>дважды, и это не идеально.

<plus_exp4>использует<foldl_start_with_parser>для осуществления повторения. Метапарс дает<foldl_reject_incomplete_start_with_parser>, который делает то же самое, что мы сделали с<first_of>,<foldl_start_with_parser>и<fail_at_first_char_expected>вместе:

> #include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp>
> struct plus_exp5 : \
...> foldl_reject_incomplete_start_with_parser< \
...>   sequence<one_of<plus_token, minus_token>, mult_exp6>, \
...>   mult_exp6, \
...>   boost::mpl::quote2<binary_op> \
...> > {};
> using exp_parser22 = build_parser<plus_exp5>;

копипастная версия

Он многократно анализирует вход, используя<sequence><<><one_of><<plus_token, minus_token>, mult_exp6>>. Когда он терпит неудачу,<foldl_reject_incomplete_start_with_parser>проверяет, использовал ли он какой-либо символ до отказа (то же, что делает<fail_at_first_char_expected>), и если да, то<foldl_reject_incomplete_start_with_parser>терпит неудачу.

Это упрощает реализацию повторения с расширенным сообщением об ошибках. Давайте попробуем:

> exp_parser22::apply<BOOST_METAPARSE_STRING("0+(1+2")>::type
<< compilation error >>
..... x__________________PARSING_FAILED__________________x<1, 7, unpaired<1, 3, literal_expected<')'>>> ....
<< compilation error >>

Обратите внимание, что другие складные парсеры также имеют свои версии<f>(например,<foldr_reject_incomplete>,<foldl_reject_incomplete1>и т. Д.).

Мы заменили один<foldl_start_with_parser>на<foldl_reject_incomplete_start_with_parser>. Другие слои (<mult_exp>,<unary_exp>и т. д.) также используют складывание. Давайте использовать его на всех уровнях:

> struct plus_exp6;
> using paren_exp5 = middle_of<lparen_token, plus_exp6, rparen_token>;
> using primary_exp4 = one_of<int_token, paren_exp5, fail<missing_primary_expression>>;
> using unary_exp4 = \
...> foldr_start_with_parser< \
...>   minus_token, \
...>   primary_exp4, \
...>   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type \
...> >;
> using mult_exp7 = \
...> foldl_reject_incomplete_start_with_parser< \
...>   sequence<one_of<times_token, divides_token>, unary_exp4>, \
...>   unary_exp4, \
...>   boost::mpl::quote2<binary_op> \
...> >;
> struct plus_exp6 : \
...> foldl_reject_incomplete_start_with_parser< \
...>   sequence<one_of<plus_token, minus_token>, mult_exp7>, \
...>   mult_exp7, \
...>   boost::mpl::quote2<binary_op> \
...> > {};
> using exp_parser23 = build_parser<plus_exp6>;

копипастная версия

[Note] Note

Обратите внимание, что<unary_exp4>использует<foldr_start_with_parser>вместо<foldr_reject_incomplete_start_with_parser>. Причина этого в том, что нет<foldr_reject_incomplete_start_with_parser>.<foldr_start_with_parser>применяет парсер<primary_exp4>, когда<minus_token>больше не принимает вход. Поэтому предполагается улавливать ошибки неполных выражений после повторения.

Давайте попробуем разные некорректные выражения:

> exp_parser23::apply<BOOST_METAPARSE_STRING("1+(2*")>::type
<< compilation error >>
..... x__________________PARSING_FAILED__________________x<1, 6, missing_primary_expression> ....
<< compilation error >>
> exp_parser23::apply<BOOST_METAPARSE_STRING("1+(2*3")>::type
<< compilation error >>
..... x__________________PARSING_FAILED__________________x<1, 7, unpaired<1, 3, literal_expected<')'>>> ....
<< compilation error >>

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

#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector> struct eval_plus : boost::mpl::plus< typename boost::mpl::at_c<Vector, 0>::type, typename boost::mpl::at_c<Vector, 2>::type > {};
eval_plus< boost::mpl::vector< mpl_::integral_c<int, 11>, mpl_::char_<'+'>, mpl_::integral_c<int, 2> >>::type
#include <boost/mpl/quote.hpp>
using exp_parser6 = build_parser< transform< sequence<int_token, plus_token, int_token>, boost::mpl::quote1<eval_plus> > >;
using exp_parser7 = build_parser< sequence< int_token,                                /* The first <number> */ repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */ > >;
using vector_of_numbers = boost::mpl::vector< boost::mpl::int_<2>, boost::mpl::int_<5>, boost::mpl::int_<6> >;
template <class Vector> struct sum_vector : boost::mpl::fold< Vector, boost::mpl::int_<0>, boost::mpl::lambda< boost::mpl::plus<boost::mpl::_1, boost::mpl::_2> >::type > {};
template <class Sum, class Item> struct sum_items : boost::mpl::plus< Sum, typename boost::mpl::at_c<Item, 1>::type > {};
sum_items< mpl_::integral_c<int, 1>, boost::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2>> >::type
boost::mpl::fold< boost::mpl::at_c<temp_result, 1>::type, /* The vector to summarise */ boost::mpl::int_<0>, /* The value to start the sum from */ boost::mpl::quote2<sum_items> /* The function to call in each iteration */ >::type
using exp_parser8 = build_parser< sequence< int_token, /* parse the first <number> */ transform< repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */ /* lambda expression summarising the "+ <number>" elements using fold */ boost::mpl::lambda< /* The folding expression we have just created */ boost::mpl::fold< boost::mpl::_1, /* the argument of the lambda expression, the result */ /* of the repeated<...> parser */ boost::mpl::int_<0>, boost::mpl::quote2<sum_items> > >::type > > >;
using exp_parser9 = build_parser< transform< /* What we had so far */ sequence< int_token, transform< repeated<sequence<plus_token, int_token>>, boost::mpl::lambda< boost::mpl::fold< boost::mpl::_1, boost::mpl::int_<0>, boost::mpl::quote2<sum_items> > >::type > >, boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */ > >;
using exp_parser10 = build_parser< transform< sequence< int_token, foldl< sequence<plus_token, int_token>, boost::mpl::int_<0>, boost::mpl::quote2<sum_items> > >, boost::mpl::quote1<sum_vector>> >;
>
using exp_parser11 = build_parser< foldl_start_with_parser< sequence<plus_token, int_token>, /* apply this parser repeatedly */ int_token, /* use this parser to get the initial value */ boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */ > >;
using exp_parser12 = build_parser< foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, int_token>, int_token, boost::mpl::quote2<sum_items> > >;
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
eval_binary_op<boost::mpl::int_<11>, '+', boost::mpl::int_<2>>::type
eval_binary_op<boost::mpl::int_<13>, '-', boost::mpl::int_<2>>::type
template <class S, class Item> struct binary_op : eval_binary_op< S, boost::mpl::at_c<Item, 0>::type::value, typename boost::mpl::at_c<Item, 1>::type > {};
using exp_parser13 = build_parser< foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, int_token>, int_token, boost::mpl::quote2<binary_op> > >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using exp_parser14 = build_parser< foldl_start_with_parser< sequence<one_of<plus_token, minus_token, times_token>, int_token>, int_token, boost::mpl::quote2<binary_op> > >;
using exp_parser15 = build_parser< foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp1>, mult_exp1, boost::mpl::quote2<binary_op> > >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 = foldl_start_with_parser< sequence<one_of<times_token, divides_token>, int_token>, int_token, boost::mpl::quote2<binary_op> >;
using exp_parser16 = build_parser< foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp2>, mult_exp2, boost::mpl::quote2<binary_op> > >;
template <class S, class Item> struct reverse_binary_op : eval_binary_op< typename boost::mpl::at_c<Item, 0>::type, boost::mpl::at_c<Item, 1>::type::value, S > {};
using mult_exp3 = foldr_start_with_parser< sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */ int_token, /* The parser parsing the last number */ boost::mpl::quote2<reverse_binary_op> /* The function called for every result */ /* of applying the above parser */ >;
using exp_parser17 = build_parser< foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp3>, mult_exp3, boost::mpl::quote2<binary_op> > >;
#include <boost/mpl/negate.hpp>
using unary_exp1 = foldr_start_with_parser< minus_token, int_token, boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type >;
using mult_exp4 = foldl_start_with_parser< sequence<one_of<times_token, divides_token>, unary_exp1>, unary_exp1, boost::mpl::quote2<binary_op> >;
using exp_parser18 = build_parser< foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp4>, mult_exp4, boost::mpl::quote2<binary_op> > >;
exp_parser18::apply<BOOST_METAPARSE_STRING("---13")>::type
exp_parser18::apply<BOOST_METAPARSE_STRING("13")>::type
using lparen_token = token<lit_c<'('>>;
using rparen_token = token<lit_c<')'>>;
using plus_exp1 = foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp4>, mult_exp4, boost::mpl::quote2<binary_op> >;
#include <boost/metaparse/middle_of.hpp>
using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;
using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
using primary_exp2 = one_of<int_token, paren_exp2>;
using unary_exp2 = foldr_start_with_parser< minus_token, primary_exp2, boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type >;
using mult_exp5 = foldl_start_with_parser< sequence<one_of<times_token, divides_token>, unary_exp2>, unary_exp2, boost::mpl::quote2<binary_op> >;
struct plus_exp2 : foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp5>, mult_exp5, boost::mpl::quote2<binary_op> > {};
struct plus_exp3;
using paren_exp4 = middle_of<lparen_token, plus_exp3, rparen_token>;
using unary_exp3 = foldr_start_with_parser< minus_token, primary_exp3, boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type >;
using mult_exp6 = foldl_start_with_parser< sequence<one_of<times_token, divides_token>, unary_exp3>, unary_exp3, boost::mpl::quote2<binary_op> >;
struct plus_exp3 : foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp6>, mult_exp6, boost::mpl::quote2<binary_op> > {};
using exp_parser20 = build_parser<plus_exp3>;
#include <boost/metaparse/fail_at_first_char_expected.hpp>
#include <boost/metaparse/first_of.hpp>
struct plus_exp4 : first_of< foldl_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp6>, mult_exp6, boost::mpl::quote2<binary_op> >, fail_at_first_char_expected< sequence<one_of<plus_token, minus_token>, mult_exp6> > > {};
using exp_parser21 = build_parser<plus_exp4>;
#include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp>
struct plus_exp5 : foldl_reject_incomplete_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp6>, mult_exp6, boost::mpl::quote2<binary_op> > {};
using exp_parser22 = build_parser<plus_exp5>;
struct plus_exp6;
using paren_exp5 = middle_of<lparen_token, plus_exp6, rparen_token>;
using primary_exp4 = one_of<int_token, paren_exp5, fail<missing_primary_expression>>;
using unary_exp4 = foldr_start_with_parser< minus_token, primary_exp4, boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type >;
using mult_exp7 = foldl_reject_incomplete_start_with_parser< sequence<one_of<times_token, divides_token>, unary_exp4>, unary_exp4, boost::mpl::quote2<binary_op> >;
struct plus_exp6 : foldl_reject_incomplete_start_with_parser< sequence<one_of<plus_token, minus_token>, mult_exp7>, mult_exp7, boost::mpl::quote2<binary_op> > {};
using exp_parser23 = build_parser<plus_exp6>;

Определения перед разделом 3.

#include <boost/metaparse/string.hpp>

Определения перед разделом 3.1.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;

Определения перед разделом 3.2.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;

Определения перед разделом 3.3.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;

Определения перед разделом 4.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;

Определения перед разделом 4.1.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>

Определения перед разделом 4.2.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;

Определения перед разделом 5.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;

Определения перед разделом 5.1.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;

Определения перед разделом 5.2.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;

Определения перед разделом 5.2.1.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;

Определения перед разделом 5.2.2.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};

Определения перед разделом 5.2.3

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;

Определения перед разделом 5.2.4.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;

Определения перед разделом 6.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;

Определения перед разделом 6.1.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;

Определения перед разделом 6.2.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;

Определения перед разделом 7.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;

Определения перед разделом 7.1.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;

Определения перед разделом 7.2.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;

Определения перед разделом 8.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;

Определения перед разделом 8.1.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;

Определения перед разделом 8.2.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;

Определения перед разделом 9.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;
template <class S, class Item>
 struct reverse_binary_op :
   eval_binary_op<
     typename boost::mpl::at_c<Item, 0>::type,
     boost::mpl::at_c<Item, 1>::type::value,
     S
   >
   {};
#include <boost/metaparse/foldr_start_with_parser.hpp>
using mult_exp3 =
 foldr_start_with_parser<
   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */
   int_token, /* The parser parsing the last number */
   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */
                                         /* of applying the above parser */
 >;
using exp_parser17 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp3>,
     mult_exp3,
     boost::mpl::quote2<binary_op>
   >
 >;

Определения перед разделом 10.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;
template <class S, class Item>
 struct reverse_binary_op :
   eval_binary_op<
     typename boost::mpl::at_c<Item, 0>::type,
     boost::mpl::at_c<Item, 1>::type::value,
     S
   >
   {};
#include <boost/metaparse/foldr_start_with_parser.hpp>
using mult_exp3 =
 foldr_start_with_parser<
   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */
   int_token, /* The parser parsing the last number */
   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */
                                         /* of applying the above parser */
 >;
using exp_parser17 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp3>,
     mult_exp3,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/negate.hpp>
using unary_exp1 =
 foldr_start_with_parser<
   minus_token,
   int_token,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp4 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp1>,
   unary_exp1,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser18 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp4>,
     mult_exp4,
     boost::mpl::quote2<binary_op>
   >
 >;

Определения перед разделом 11.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;
template <class S, class Item>
 struct reverse_binary_op :
   eval_binary_op<
     typename boost::mpl::at_c<Item, 0>::type,
     boost::mpl::at_c<Item, 1>::type::value,
     S
   >
   {};
#include <boost/metaparse/foldr_start_with_parser.hpp>
using mult_exp3 =
 foldr_start_with_parser<
   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */
   int_token, /* The parser parsing the last number */
   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */
                                         /* of applying the above parser */
 >;
using exp_parser17 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp3>,
     mult_exp3,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/negate.hpp>
using unary_exp1 =
 foldr_start_with_parser<
   minus_token,
   int_token,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp4 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp1>,
   unary_exp1,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser18 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp4>,
     mult_exp4,
     boost::mpl::quote2<binary_op>
   >
 >;
using lparen_token = token<lit_c<'('>>;
using rparen_token = token<lit_c<')'>>;
using plus_exp1 =
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp4>,
   mult_exp4,
   boost::mpl::quote2<binary_op>
 >;
using paren_exp1 = sequence<lparen_token, plus_exp1, rparen_token>;
#include <boost/metaparse/middle_of.hpp>
using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;
using primary_exp1 = one_of<int_token, paren_exp2>;
struct plus_exp2;
using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
using primary_exp2 = one_of<int_token, paren_exp2>;
using unary_exp2 =
 foldr_start_with_parser<
   minus_token,
   primary_exp2,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp5 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp2>,
   unary_exp2,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp2 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp5>,
   mult_exp5,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser19 = build_parser<plus_exp2>;

Определения перед разделом 11.1.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;
template <class S, class Item>
 struct reverse_binary_op :
   eval_binary_op<
     typename boost::mpl::at_c<Item, 0>::type,
     boost::mpl::at_c<Item, 1>::type::value,
     S
   >
   {};
#include <boost/metaparse/foldr_start_with_parser.hpp>
using mult_exp3 =
 foldr_start_with_parser<
   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */
   int_token, /* The parser parsing the last number */
   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */
                                         /* of applying the above parser */
 >;
using exp_parser17 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp3>,
     mult_exp3,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/negate.hpp>
using unary_exp1 =
 foldr_start_with_parser<
   minus_token,
   int_token,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp4 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp1>,
   unary_exp1,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser18 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp4>,
     mult_exp4,
     boost::mpl::quote2<binary_op>
   >
 >;
using lparen_token = token<lit_c<'('>>;
using rparen_token = token<lit_c<')'>>;
using plus_exp1 =
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp4>,
   mult_exp4,
   boost::mpl::quote2<binary_op>
 >;
using paren_exp1 = sequence<lparen_token, plus_exp1, rparen_token>;
#include <boost/metaparse/middle_of.hpp>
using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;
using primary_exp1 = one_of<int_token, paren_exp2>;
struct plus_exp2;
using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
using primary_exp2 = one_of<int_token, paren_exp2>;
using unary_exp2 =
 foldr_start_with_parser<
   minus_token,
   primary_exp2,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp5 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp2>,
   unary_exp2,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp2 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp5>,
   mult_exp5,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser19 = build_parser<plus_exp2>;

Определения перед разделом 11.2.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;
template <class S, class Item>
 struct reverse_binary_op :
   eval_binary_op<
     typename boost::mpl::at_c<Item, 0>::type,
     boost::mpl::at_c<Item, 1>::type::value,
     S
   >
   {};
#include <boost/metaparse/foldr_start_with_parser.hpp>
using mult_exp3 =
 foldr_start_with_parser<
   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */
   int_token, /* The parser parsing the last number */
   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */
                                         /* of applying the above parser */
 >;
using exp_parser17 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp3>,
     mult_exp3,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/negate.hpp>
using unary_exp1 =
 foldr_start_with_parser<
   minus_token,
   int_token,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp4 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp1>,
   unary_exp1,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser18 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp4>,
     mult_exp4,
     boost::mpl::quote2<binary_op>
   >
 >;
using lparen_token = token<lit_c<'('>>;
using rparen_token = token<lit_c<')'>>;
using plus_exp1 =
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp4>,
   mult_exp4,
   boost::mpl::quote2<binary_op>
 >;
using paren_exp1 = sequence<lparen_token, plus_exp1, rparen_token>;
#include <boost/metaparse/middle_of.hpp>
using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;
using primary_exp1 = one_of<int_token, paren_exp2>;
struct plus_exp2;
using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
using primary_exp2 = one_of<int_token, paren_exp2>;
using unary_exp2 =
 foldr_start_with_parser<
   minus_token,
   primary_exp2,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp5 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp2>,
   unary_exp2,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp2 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp5>,
   mult_exp5,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser19 = build_parser<plus_exp2>;

Определения перед разделом 11.3.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;
template <class S, class Item>
 struct reverse_binary_op :
   eval_binary_op<
     typename boost::mpl::at_c<Item, 0>::type,
     boost::mpl::at_c<Item, 1>::type::value,
     S
   >
   {};
#include <boost/metaparse/foldr_start_with_parser.hpp>
using mult_exp3 =
 foldr_start_with_parser<
   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */
   int_token, /* The parser parsing the last number */
   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */
                                         /* of applying the above parser */
 >;
using exp_parser17 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp3>,
     mult_exp3,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/negate.hpp>
using unary_exp1 =
 foldr_start_with_parser<
   minus_token,
   int_token,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp4 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp1>,
   unary_exp1,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser18 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp4>,
     mult_exp4,
     boost::mpl::quote2<binary_op>
   >
 >;
using lparen_token = token<lit_c<'('>>;
using rparen_token = token<lit_c<')'>>;
using plus_exp1 =
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp4>,
   mult_exp4,
   boost::mpl::quote2<binary_op>
 >;
using paren_exp1 = sequence<lparen_token, plus_exp1, rparen_token>;
#include <boost/metaparse/middle_of.hpp>
using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;
using primary_exp1 = one_of<int_token, paren_exp2>;
struct plus_exp2;
using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
using primary_exp2 = one_of<int_token, paren_exp2>;
using unary_exp2 =
 foldr_start_with_parser<
   minus_token,
   primary_exp2,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp5 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp2>,
   unary_exp2,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp2 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp5>,
   mult_exp5,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser19 = build_parser<plus_exp2>;
#include <boost/metaparse/define_error.hpp>
BOOST_METAPARSE_DEFINE_ERROR(missing_primary_expression, "Missing primary expression");
struct plus_exp3;
using paren_exp4 = middle_of<lparen_token, plus_exp3, rparen_token>;
#include <boost/metaparse/fail.hpp>
using primary_exp3 = one_of<int_token, paren_exp4, fail<missing_primary_expression>>;
using unary_exp3 =
 foldr_start_with_parser<
   minus_token,
   primary_exp3,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp6 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp3>,
   unary_exp3,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp3 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp6>,
   mult_exp6,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser20 = build_parser<plus_exp3>;

Определения перед разделом 11.3.1.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;
template <class S, class Item>
 struct reverse_binary_op :
   eval_binary_op<
     typename boost::mpl::at_c<Item, 0>::type,
     boost::mpl::at_c<Item, 1>::type::value,
     S
   >
   {};
#include <boost/metaparse/foldr_start_with_parser.hpp>
using mult_exp3 =
 foldr_start_with_parser<
   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */
   int_token, /* The parser parsing the last number */
   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */
                                         /* of applying the above parser */
 >;
using exp_parser17 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp3>,
     mult_exp3,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/negate.hpp>
using unary_exp1 =
 foldr_start_with_parser<
   minus_token,
   int_token,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp4 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp1>,
   unary_exp1,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser18 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp4>,
     mult_exp4,
     boost::mpl::quote2<binary_op>
   >
 >;
using lparen_token = token<lit_c<'('>>;
using rparen_token = token<lit_c<')'>>;
using plus_exp1 =
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp4>,
   mult_exp4,
   boost::mpl::quote2<binary_op>
 >;
using paren_exp1 = sequence<lparen_token, plus_exp1, rparen_token>;
#include <boost/metaparse/middle_of.hpp>
using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;
using primary_exp1 = one_of<int_token, paren_exp2>;
struct plus_exp2;
using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
using primary_exp2 = one_of<int_token, paren_exp2>;
using unary_exp2 =
 foldr_start_with_parser<
   minus_token,
   primary_exp2,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp5 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp2>,
   unary_exp2,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp2 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp5>,
   mult_exp5,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser19 = build_parser<plus_exp2>;
#include <boost/metaparse/define_error.hpp>
BOOST_METAPARSE_DEFINE_ERROR(missing_primary_expression, "Missing primary expression");
struct plus_exp3;
using paren_exp4 = middle_of<lparen_token, plus_exp3, rparen_token>;
#include <boost/metaparse/fail.hpp>
using primary_exp3 = one_of<int_token, paren_exp4, fail<missing_primary_expression>>;
using unary_exp3 =
 foldr_start_with_parser<
   minus_token,
   primary_exp3,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp6 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp3>,
   unary_exp3,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp3 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp6>,
   mult_exp6,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser20 = build_parser<plus_exp3>;
#include <boost/metaparse/fail_at_first_char_expected.hpp>
#include <boost/metaparse/first_of.hpp>
struct plus_exp4 :
 first_of<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp6>,
     mult_exp6,
     boost::mpl::quote2<binary_op>
   >,
   fail_at_first_char_expected<
     sequence<one_of<plus_token, minus_token>, mult_exp6>
   >
 > {};
using exp_parser21 = build_parser<plus_exp4>;

Определения перед разделом 11.3.2.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;
template <class S, class Item>
 struct reverse_binary_op :
   eval_binary_op<
     typename boost::mpl::at_c<Item, 0>::type,
     boost::mpl::at_c<Item, 1>::type::value,
     S
   >
   {};
#include <boost/metaparse/foldr_start_with_parser.hpp>
using mult_exp3 =
 foldr_start_with_parser<
   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */
   int_token, /* The parser parsing the last number */
   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */
                                         /* of applying the above parser */
 >;
using exp_parser17 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp3>,
     mult_exp3,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/negate.hpp>
using unary_exp1 =
 foldr_start_with_parser<
   minus_token,
   int_token,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp4 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp1>,
   unary_exp1,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser18 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp4>,
     mult_exp4,
     boost::mpl::quote2<binary_op>
   >
 >;
using lparen_token = token<lit_c<'('>>;
using rparen_token = token<lit_c<')'>>;
using plus_exp1 =
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp4>,
   mult_exp4,
   boost::mpl::quote2<binary_op>
 >;
using paren_exp1 = sequence<lparen_token, plus_exp1, rparen_token>;
#include <boost/metaparse/middle_of.hpp>
using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;
using primary_exp1 = one_of<int_token, paren_exp2>;
struct plus_exp2;
using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
using primary_exp2 = one_of<int_token, paren_exp2>;
using unary_exp2 =
 foldr_start_with_parser<
   minus_token,
   primary_exp2,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp5 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp2>,
   unary_exp2,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp2 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp5>,
   mult_exp5,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser19 = build_parser<plus_exp2>;
#include <boost/metaparse/define_error.hpp>
BOOST_METAPARSE_DEFINE_ERROR(missing_primary_expression, "Missing primary expression");
struct plus_exp3;
using paren_exp4 = middle_of<lparen_token, plus_exp3, rparen_token>;
#include <boost/metaparse/fail.hpp>
using primary_exp3 = one_of<int_token, paren_exp4, fail<missing_primary_expression>>;
using unary_exp3 =
 foldr_start_with_parser<
   minus_token,
   primary_exp3,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp6 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp3>,
   unary_exp3,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp3 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp6>,
   mult_exp6,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser20 = build_parser<plus_exp3>;
#include <boost/metaparse/fail_at_first_char_expected.hpp>
#include <boost/metaparse/first_of.hpp>
struct plus_exp4 :
 first_of<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp6>,
     mult_exp6,
     boost::mpl::quote2<binary_op>
   >,
   fail_at_first_char_expected<
     sequence<one_of<plus_token, minus_token>, mult_exp6>
   >
 > {};
using exp_parser21 = build_parser<plus_exp4>;
#include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp>
struct plus_exp5 :
 foldl_reject_incomplete_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp6>,
   mult_exp6,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser22 = build_parser<plus_exp5>;

Определения перед разделом 12.

#include <boost/metaparse/string.hpp>
#include <boost/metaparse/int_.hpp>
#include <boost/metaparse/build_parser.hpp>
using namespace boost::metaparse;
using exp_parser1 = build_parser<int_>;
#include <boost/metaparse/entire_input.hpp>
using exp_parser2 = build_parser<entire_input<int_>>;
#include <boost/metaparse/token.hpp>
using exp_parser3 = build_parser<entire_input<token<int_>>>;
#include <boost/metaparse/lit_c.hpp>
#include <boost/metaparse/sequence.hpp>
using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
#include <metashell/formatter.hpp>
using int_token = token<int_>;
using plus_token = token<lit_c<'+'>>;
using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
#include <boost/metaparse/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/at.hpp>
template <class Vector>
 struct eval_plus :
   boost::mpl::plus<
     typename boost::mpl::at_c<Vector, 0>::type,
     typename boost::mpl::at_c<Vector, 2>::type
   > {};
#include <boost/mpl/quote.hpp>
using exp_parser6 =
 build_parser<
   transform<
     sequence<int_token, plus_token, int_token>,
     boost::mpl::quote1<eval_plus>
   >
 >;
#include <boost/metaparse/any.hpp>
using exp_parser7 =
 build_parser<
   sequence<
     int_token,                                /* The first <number> */
     repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */
   >
 >;
using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
#include <boost/mpl/fold.hpp>
using vector_of_numbers =
 boost::mpl::vector<
   boost::mpl::int_<2>,
   boost::mpl::int_<5>,
   boost::mpl::int_<6>
 >;
template <class Vector>
 struct sum_vector :
    boost::mpl::fold<
      Vector,
      boost::mpl::int_<0>,
      boost::mpl::lambda<
        boost::mpl::plus<boost::mpl::_1, boost::mpl::_2>
      >::type
    >
  {};
template <class Sum, class Item>
   struct sum_items :
     boost::mpl::plus<
       Sum,
       typename boost::mpl::at_c<Item, 1>::type
     >
 {};
using exp_parser8 =
 build_parser<
   sequence<
     int_token, /* parse the first <number> */
     transform<
       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */
       /* lambda expression summarising the "+ <number>" elements using fold */
       boost::mpl::lambda<
         /* The folding expression we have just created */
         boost::mpl::fold<
           boost::mpl::_1, /* the argument of the lambda expression, the result */
                           /* of the repeated<...> parser */
           boost::mpl::int_<0>,
           boost::mpl::quote2<sum_items>
         >
       >::type
     >
   >
 >;
using exp_parser9 =
 build_parser<
   transform<
     /* What we had so far */
     sequence<
       int_token,
       transform<
         repeated<sequence<plus_token, int_token>>,
         boost::mpl::lambda<
           boost::mpl::fold<
             boost::mpl::_1,
             boost::mpl::int_<0>,
             boost::mpl::quote2<sum_items>
           >
         >::type
       >
     >,
     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */
   >
 >;
#include <boost/metaparse/foldl.hpp>
using exp_parser10 =
 build_parser<
   transform<
     sequence<
       int_token,
       foldl<
         sequence<plus_token, int_token>,
         boost::mpl::int_<0>,
         boost::mpl::quote2<sum_items>
       >
     >,
     boost::mpl::quote1<sum_vector>>
 >;
#include <boost/metaparse/foldl_start_with_parser.hpp>
using exp_parser11 =
 build_parser<
   foldl_start_with_parser<
     sequence<plus_token, int_token>, /* apply this parser repeatedly */
     int_token, /* use this parser to get the initial value */
     boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */
   >
 >;
using minus_token = token<lit_c<'-'>>;
#include <boost/metaparse/one_of.hpp>
using exp_parser12 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<sum_items>
   >
 >;
#include <boost/mpl/minus.hpp>
template <class L, char Op, class R> struct eval_binary_op;
template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
template <class S, class Item>
 struct binary_op :
   eval_binary_op<
     S,
     boost::mpl::at_c<Item, 0>::type::value,
     typename boost::mpl::at_c<Item, 1>::type
   >
   {};
using exp_parser13 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/times.hpp>
template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
using times_token = token<lit_c<'*'>>;
using exp_parser14 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token, times_token>, int_token>,
     int_token,
     boost::mpl::quote2<binary_op>
   >
 >;
using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
using exp_parser15 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp1>,
     mult_exp1,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/divides.hpp>
template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
using divides_token = token<lit_c<'/'>>;
using mult_exp2 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, int_token>,
   int_token,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser16 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp2>,
     mult_exp2,
     boost::mpl::quote2<binary_op>
   >
 >;
template <class S, class Item>
 struct reverse_binary_op :
   eval_binary_op<
     typename boost::mpl::at_c<Item, 0>::type,
     boost::mpl::at_c<Item, 1>::type::value,
     S
   >
   {};
#include <boost/metaparse/foldr_start_with_parser.hpp>
using mult_exp3 =
 foldr_start_with_parser<
   sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */
   int_token, /* The parser parsing the last number */
   boost::mpl::quote2<reverse_binary_op> /* The function called for every result */
                                         /* of applying the above parser */
 >;
using exp_parser17 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp3>,
     mult_exp3,
     boost::mpl::quote2<binary_op>
   >
 >;
#include <boost/mpl/negate.hpp>
using unary_exp1 =
 foldr_start_with_parser<
   minus_token,
   int_token,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp4 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp1>,
   unary_exp1,
   boost::mpl::quote2<binary_op>
 >;
using exp_parser18 =
 build_parser<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp4>,
     mult_exp4,
     boost::mpl::quote2<binary_op>
   >
 >;
using lparen_token = token<lit_c<'('>>;
using rparen_token = token<lit_c<')'>>;
using plus_exp1 =
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp4>,
   mult_exp4,
   boost::mpl::quote2<binary_op>
 >;
using paren_exp1 = sequence<lparen_token, plus_exp1, rparen_token>;
#include <boost/metaparse/middle_of.hpp>
using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;
using primary_exp1 = one_of<int_token, paren_exp2>;
struct plus_exp2;
using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
using primary_exp2 = one_of<int_token, paren_exp2>;
using unary_exp2 =
 foldr_start_with_parser<
   minus_token,
   primary_exp2,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp5 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp2>,
   unary_exp2,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp2 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp5>,
   mult_exp5,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser19 = build_parser<plus_exp2>;
#include <boost/metaparse/define_error.hpp>
BOOST_METAPARSE_DEFINE_ERROR(missing_primary_expression, "Missing primary expression");
struct plus_exp3;
using paren_exp4 = middle_of<lparen_token, plus_exp3, rparen_token>;
#include <boost/metaparse/fail.hpp>
using primary_exp3 = one_of<int_token, paren_exp4, fail<missing_primary_expression>>;
using unary_exp3 =
 foldr_start_with_parser<
   minus_token,
   primary_exp3,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp6 =
 foldl_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp3>,
   unary_exp3,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp3 :
 foldl_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp6>,
   mult_exp6,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser20 = build_parser<plus_exp3>;
#include <boost/metaparse/fail_at_first_char_expected.hpp>
#include <boost/metaparse/first_of.hpp>
struct plus_exp4 :
 first_of<
   foldl_start_with_parser<
     sequence<one_of<plus_token, minus_token>, mult_exp6>,
     mult_exp6,
     boost::mpl::quote2<binary_op>
   >,
   fail_at_first_char_expected<
     sequence<one_of<plus_token, minus_token>, mult_exp6>
   >
 > {};
using exp_parser21 = build_parser<plus_exp4>;
#include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp>
struct plus_exp5 :
 foldl_reject_incomplete_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp6>,
   mult_exp6,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser22 = build_parser<plus_exp5>;
struct plus_exp6;
using paren_exp5 = middle_of<lparen_token, plus_exp6, rparen_token>;
using primary_exp4 = one_of<int_token, paren_exp5, fail<missing_primary_expression>>;
using unary_exp4 =
 foldr_start_with_parser<
   minus_token,
   primary_exp4,
   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type
 >;
using mult_exp7 =
 foldl_reject_incomplete_start_with_parser<
   sequence<one_of<times_token, divides_token>, unary_exp4>,
   unary_exp4,
   boost::mpl::quote2<binary_op>
 >;
struct plus_exp6 :
 foldl_reject_incomplete_start_with_parser<
   sequence<one_of<plus_token, minus_token>, mult_exp7>,
   mult_exp7,
   boost::mpl::quote2<binary_op>
 > {};
using exp_parser23 = build_parser<plus_exp6>;

PrevUpHomeNext

Статья Getting started with Boost.Metaparse раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 22. Boost.Metaparse может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Chapter 22. Boost.Metaparse ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:26:22/0.093179941177368/1