Опыт использования
    Boost Spirit

         Иван Романенко(viva.cpp@gmail.com)
Ожидается
• Инфа о спирите и карме

• Основы синтаксиса спирта

• Примеры получения практической пользы

• Почему спирит - не то что вам нужно

• Сравнение с аналогами
Парсинг

                      Структура
   Текст
                       данных

                  struct Data
                  {
                     int a;
“123 456 678”        int b;
                     int c;
                  };
Генерация

                   Структура
   Текст
                    данных

                  struct Data
                  {
                     int a;
“123 456 678”        int b;
                     int c;
                  };
Мотивация
• Бьюсь об заклад, я могу написать простое регулярное
  выражение для разбора этого текста

• Я не хочу подключать дополнительные библиотеки

• Одной строки с использованием scanf/istream будет
  достаточно

• std::string и boost::lexical_cast мои друзья
Regexp
Парсер в одной функции
Spirit way
Области применения
• Специализированные конфигурационные
  файлы
• Коммуникация с устройствами
• Поддержка произвольных форматов данных
• Всё что угодно, имеющее «синтаксис»
Что такое Boost Spirit ?
• Это объектено-ориентированный нисходящий
  синтаксический анализатор.

• Позволяет описывать формат используя
  синтаксис, приближённый к EBNF(Расширенной
  форме Бэкуса – Наура), прямо в С++ коде.

• Позволяет связывать описание синтаксиса с
  конкретными типами данных, обеспечивая
  строгую типизацию.
Spirit состоит из:
• Qi – парсер
• Karma - генератор
• Lex – лексический анализатор
• Classic – старая версия парсера
Qi API

sscanf( …,”%d”, var)

parse(…, int_, var)
parse(…, int_)(8))
Числа
Тип            Правило
signed         short_, int_, long_, long_long
unsigned       bin, oct, hex, ushort_, ulong_, uint_
real           float_, double_, long_double
boolean        bool_
binary         byte_, word, dword, qword
big endian     big_word, big_dword, big_qword
litte endian   litte_word, litte_dword, litte_qword
Символы
Тип            Правило
character      char_, char_(’x’), char_(’a’,’z’),
               char_(“a-zA-Z”), ‘x’
string         string(“foo”), lit(“bar”), “bar”
classification alnum, alpha, blank, cntrl, digit,
               graph, lower, print, punct, space,
               upper, xdigit
Операторы
      Описание          Синтаксис
‘ИЛИ’                      a|b
Последовательно           a >> b
0 или множество раз         *a
Не меньше одного раза       +a
Опциональное                -a
Разность                   a-b
Список                    a%b
‘И’ в любом порядке        a^b
Операторы
      Описание          Синтаксис
‘ИЛИ’                      a|b      Допустимо правило
Последовательно           a >> b    а или b
0 или множество раз         *a
                                    int_ | double
Не меньше одного раза       +a
Опциональное                -a      “123” , “3.14”
Разность                   a-b
Список                    a%b
‘И’ в любом порядке        a^b
Операторы
      Описание          Синтаксис
‘ИЛИ’                      a|b      За правилом а
Последовательно           a >> b    следует b
0 или множество раз         *a
                                    int_ >> ‘_‘ >> double
Не меньше одного раза       +a
Опциональное                -a      “123_3.14”
Разность                   a-b
Список                    a%b
‘И’ в любом порядке        a^b
Операторы
      Описание        Синтаксис
‘ИЛИ’                    a|b      *char_(‘a’)
Последовательно         a >> b    “aaaaa”
0 или множество раз       *a
                                  +char_
Не меньше одного раза     +a      “name”
Опциональное              -a
Разность                 a-b      *( int_ >> -char_(‘,’) )
Список                  a%b       “1,2,3,4”
‘И’ в любом порядке      a^b
Операторы
      Описание          Синтаксис
‘ИЛИ’                      a|b    *(char_ - ‘=’) >> ‘=’ >> int_
Последовательно           a >> b
0 или множество раз         *a    “variable=123”
Не меньше одного раза       +a
Опциональное                -a
Разность                   a-b
Список                    a%b
‘И’ в любом порядке        a^b
Операторы
      Описание          Синтаксис
‘ИЛИ’                      a|b
Последовательно           a >> b    int_ % ‘,’
0 или множество раз         *a      “1,2,3,4”
Не меньше одного раза       +a
Опциональное                -a
Разность                   a-b
Список                    a%b
‘И’ в любом порядке        a^b
Операторы
      Описание          Синтаксис
‘ИЛИ’                      a|b
Последовательно           a >> b    int_ ^ alpha
0 или множество раз         *a      “12a”
Не меньше одного раза       +a      “a12”
Опциональное                -a
Разность                   a-b
Список                    a%b
‘И’ в любом порядке       a^b
Атрибуты
int varInt;
parse(…, int_, varInt)

int varInt; double varDbl;
parse(…, int_ >> “_“ >> double_, varInt, varDbl)

double varDbl;
parse(…, int_(8) >> char_(“_“) >> double_, varDbl)
Атрибуты операторов
         Описание         Синтаксис
  0 или множество раз        *a

           a: A --> *a: vector<A>
           a: Unused --> *a: Unused
правило : атрибут правила --> выражение : атрибут выражения

int_ : int --> *int_ : vector<int>
Атрибуты операторов
      Описание     Синтаксис
Последовательно      a >> b
                               std::pair<A,B>
a: A, b: B --> (a >> b): tuple<A, B>
a: A, b: Unused --> (a >> b): A
a: Unused, b: B --> (a >> b): B
a: Unused, b: Unused --> (a >> b): Unused
Атрибуты операторов
      Описание      Синтаксис
Последовательно       a >> b


a: A, b: A --> (a >> b): vector<A>
a: vector<A>, b: A --> (a >> b): vector<A>
a: A, b: vector<A> --> (a >> b): vector<A>
a: vector<A>, b: vector<A> -->
                             (a >> b): vector<A>
Управление атрибутами
              Описание                  Синтаксис
Игнорирование атрибута                    omit[]
Экспорт промежутка на котором
                                          raw[]
сработало правило [first,last]


a: A --> omit[a]: unused_type

a: A --> raw[a]: boost::iterator_range<Iter>
Profit ?
Атрибуты операторов
                перезагрузка
std::string data(“1 2 3 4 5 6");
std::list< int > numbers;
phrase_parse(data.begin(), data.end(),
             *int_,
             space, numbers);
Атрибуты операторов
               перезагрузка
std::string data(“1,2,3,4,5,6");
std::list< int > numbers;
phrase_parse(data.begin(), data.end(),
             (int_ % ‘,’),
             space, numbers);
Атрибуты операторов
                перезагрузка
std::string data("p=3.14 g=9.8");

std::list< std::pair<std::string, double> > records;

phrase_parse(data.begin(), data.end(),
             *( +alpha >> ”=“ >> double_ ),
             space, records);
Атрибуты операторов
               перезагрузка
std::string data("p=3.14 g=9.8");

std::map<std::string, double> records;

phrase_parse(data.begin(), data.end(),
             *( +alpha >> ”=“ >> double_ ),
             space, records);
Атрибуты операторов
               перезагрузка
std::string data(“n p=3.14 n g=9.8 ");

std::map<std::string, double> records;

phrase_parse(data.begin(), data.end(),
             *( +alpha >> ”=“ >> double_ ),
             space, records);
Пользовательский тип
struct Record
{
std::string name;
double value;
};

BOOST_FUSION_ADAPT_STRUCT(
  Record,
  (std::string, name)
  (double, value)
)
Атрибуты операторов
               революция
std::string data("p=3.14 g=9.8");

std::list<Record> records;

phrase_parse(data.begin(), data.end(),
             *( +alpha >> ”=“ >> double_ ),
             space, records);
Custom action
std::string data("p=3.14 g=9.8");
void SomeFnc(Record& rec)
{
  std::cout << rec.name << " " << rec.value << std::endl;
}
qi:rule<std::string::const_iterator,Record()> recRule =
                              +alpha >> ”=“ >> double_;
phrase_parse(data.begin(), data.end(),
               *(recRule [&SomeFnc] ),
                space);
Организация своих правил
Пользовательские правила
• Новые правила создаются на базе уже
  существующих
• Правило может иметь локальные переменные
• Правило может принимать входные параметры
• Правило экспортирует атрибут
Пользовательские правила
template <typename Iterator, typename Signature>
struct rule;

qi::rule<char*, std::vector<int>()> start;

qi::rule<char*, std::vector<int>(int)> start;

qi::rule<char*, …, qi::locals<int> > start;
Пример
struct Record
{
std::string name;
double value;
};

qi::rule<…, std::string()> name = +char_ - ‘=’;

qi::rule<…, double()> value = ‘*’ >> double_ >> ‘+’;

qi::rule<…, Record()> start = name >> ‘=‘ >> value;
Грамматика
• Объединяет правила в более
  высокоуровневую абстракцию
• Экспортирует атрибут
• Может иметь локальные переменные
• Предоставляет каллбеки об ошибках
Организация грамматики
template <typename Iterator>
struct my_grammar: qi::grammar<Iterator, mini_xml() >
{
    my_grammar() : my_grammar ::base_type(xml)
    {
       …
       start = name >> ‘=‘ >> value;
     }
     qi::rule<…, Record()> start;
     qi::rule<…, double()> value;
     qi::rule<…, std::string()> name;
};
Обработка ошибок
...
xml = …
…
on_error<fail>
    (
        xml
      , std::cout
          << val("Error! Expecting ")
          << _4                  // what failed?
          << val(" here: "")
          << construct<std::string>(_3, _2) // iterators to error-pos, end
          << val(""")
          << std::endl
    );
}

Input: “<foo><bar></foo></bar>”
Error! Expecting "bar" here: "foo></bar>"
Error! Expecting end_tag here: "<bar></foo></bar>"
-------------------------
Parsing failed
-------------------------
Karma API


sprintf( …,”%d”, var)

generate(…, int_, var)
Динамический спирит
Проблемы
• Листинг об ошибке длиною в вечность
• Время компиляции зашкаливает
• Отладка в уме
Листинг об ошибке длиною в
         вечность
Листинг об ошибке длиною в
              вечность
• Дойти до первой строки ошибки - это ваш файл.
• Одной строкой выше будет файл спирита.
Проверки времени компиляции
Время компиляции
#include <boost/spirit/include/qi.hpp>

std::string data("12 23 34 56");
std::list<int> numbers;
phrase_parse(data.begin(), data.end(), *int_, space, numbers);

Тестовая система: Core 2 Duo T7100 1.8 Гц
Время компиляции: ~20 сек (Release or Debug)
Размер exe файла: 180 кб (71 кб для main(),std::cout<< “Hi”;- )

Используя Precompiled Header
Время компиляции: < 1 сек (Release or Debug)
Размер PCH файла: 100 мб.
Время компиляции
Middle-size парсер из реального проекта
400 строк кода.
1 парсер и 2 генератора.
Время компиляции: ~ 5 мин.
RAM использовано: 1.5 Гб
Размер exe файла: 1.4 Мб(Release) & 3.5 Мб(Debug)
Размер (output dir) для одной конфигурации: 876 мб
Используя Precompiled Header
Время компиляции: ~ 4 мин 30 сек
Размер PCH файла: 150 мб.
Установив Debug Information Format -> Disabled
Время компиляции: ~ 3 мин 20 сек.
Экономия: 200 мб(для одного cpp) и 527 мб(для проекта)
Отладка
         BOOST_SPIRIT_DEBUG_NODE( NODE )



std::string data("12 23");
std::list<int> numbers;
rule<std::string::const_iterator,int(),space_type> testRule = int_;
BOOST_SPIRIT_DEBUG_NODE(testRule);
phrase_parse(data.begin(), data.end(), *testRule , space, numbers);
Отладка
<testRule>
 <try>12 23</try>
 <success> 23</success>           “12 23”
 <attributes>[12]</attributes>
</testRule>
<testRule>
 <try> 23</try>
 <success></success>
                                  “12 23”
 <attributes>[23]</attributes>
</testRule>
<testRule>                        “12 23”
 <try></try>
 <fail/>
</testRule>
Press any key to continue . . .
Сравнение
ANTLR
• Отдельная среда разработки и наличие плагинов для Eclipse
• Генерирует парсер на языках:
  ActionScript, C, C#, Java, JavaScript, Objective-C, Perl, Python, Ruby
• Статическая проверка правил
• Интерпритатор
• Отладчик
ANTLR Debugger
bison/yacc
                                                      Копипаста с википедии

Advantages:

1. An LALR parser is fast (if the parsing algorithm uses a matrix parser-table format).
2. An LALR parser is linear in speed (i.e. the speed is based on the size of the input text
   file only and not based on the size of the language being recognized).

Disadvantages:

1. Software engineers are required to use an LALR parser generator, which may or may not
   be user friendly and may require some learning time.
2. Implementing meaningful error messages in the parser may be very difficult or
   impossible.
3. Understanding the parsing algorithm is often quite difficult.
4. If an error occurs, it may be difficult to determine whether it's in the grammar or the
   parser code.
5. If there is an error in the parser generator, this may be very difficult to fix.
Спасибо за внимание
Приложения
Атрибуты операторов
        Описание   Синтаксис
‘ИЛИ’                a|b


a: A, b: B --> (a | b): variant<A, B>
a: A, b: Unused --> (a | b): optional<A>
a: Unused, b: B --> (a | b): optional<B>
a: Unused, b: Unused --> (a | b): Unused
a: A, b: A --> (a | b): A
Placeholders
  Placeholder       Description
  _1, _2, …         Nth attribute of the parser.
  _val              The enclosing rule’s synthesized attribute.
  _r1, _r2, ...     The enclosing rule’s Nth inherited attribute.
  _a, _b, ..., _j   The enclosing rule’s local variables.
  _pass             Assign false to force parser failure.


qi::rule<char*, int> = lit(“EnumValue") [ val_ = MyEnum::Value ]

CiklumCPPSat: Ivan Romanenko "Experience of work with Boost Spirit"

  • 1.
    Опыт использования Boost Spirit Иван Романенко(viva.cpp@gmail.com)
  • 2.
    Ожидается • Инфа оспирите и карме • Основы синтаксиса спирта • Примеры получения практической пользы • Почему спирит - не то что вам нужно • Сравнение с аналогами
  • 3.
    Парсинг Структура Текст данных struct Data { int a; “123 456 678” int b; int c; };
  • 4.
    Генерация Структура Текст данных struct Data { int a; “123 456 678” int b; int c; };
  • 5.
    Мотивация • Бьюсь обзаклад, я могу написать простое регулярное выражение для разбора этого текста • Я не хочу подключать дополнительные библиотеки • Одной строки с использованием scanf/istream будет достаточно • std::string и boost::lexical_cast мои друзья
  • 6.
  • 7.
  • 8.
  • 9.
    Области применения • Специализированныеконфигурационные файлы • Коммуникация с устройствами • Поддержка произвольных форматов данных • Всё что угодно, имеющее «синтаксис»
  • 10.
    Что такое BoostSpirit ? • Это объектено-ориентированный нисходящий синтаксический анализатор. • Позволяет описывать формат используя синтаксис, приближённый к EBNF(Расширенной форме Бэкуса – Наура), прямо в С++ коде. • Позволяет связывать описание синтаксиса с конкретными типами данных, обеспечивая строгую типизацию.
  • 11.
    Spirit состоит из: •Qi – парсер • Karma - генератор • Lex – лексический анализатор • Classic – старая версия парсера
  • 12.
    Qi API sscanf( …,”%d”,var) parse(…, int_, var) parse(…, int_)(8))
  • 13.
    Числа Тип Правило signed short_, int_, long_, long_long unsigned bin, oct, hex, ushort_, ulong_, uint_ real float_, double_, long_double boolean bool_ binary byte_, word, dword, qword big endian big_word, big_dword, big_qword litte endian litte_word, litte_dword, litte_qword
  • 14.
    Символы Тип Правило character char_, char_(’x’), char_(’a’,’z’), char_(“a-zA-Z”), ‘x’ string string(“foo”), lit(“bar”), “bar” classification alnum, alpha, blank, cntrl, digit, graph, lower, print, punct, space, upper, xdigit
  • 15.
    Операторы Описание Синтаксис ‘ИЛИ’ a|b Последовательно a >> b 0 или множество раз *a Не меньше одного раза +a Опциональное -a Разность a-b Список a%b ‘И’ в любом порядке a^b
  • 16.
    Операторы Описание Синтаксис ‘ИЛИ’ a|b Допустимо правило Последовательно a >> b а или b 0 или множество раз *a int_ | double Не меньше одного раза +a Опциональное -a “123” , “3.14” Разность a-b Список a%b ‘И’ в любом порядке a^b
  • 17.
    Операторы Описание Синтаксис ‘ИЛИ’ a|b За правилом а Последовательно a >> b следует b 0 или множество раз *a int_ >> ‘_‘ >> double Не меньше одного раза +a Опциональное -a “123_3.14” Разность a-b Список a%b ‘И’ в любом порядке a^b
  • 18.
    Операторы Описание Синтаксис ‘ИЛИ’ a|b *char_(‘a’) Последовательно a >> b “aaaaa” 0 или множество раз *a +char_ Не меньше одного раза +a “name” Опциональное -a Разность a-b *( int_ >> -char_(‘,’) ) Список a%b “1,2,3,4” ‘И’ в любом порядке a^b
  • 19.
    Операторы Описание Синтаксис ‘ИЛИ’ a|b *(char_ - ‘=’) >> ‘=’ >> int_ Последовательно a >> b 0 или множество раз *a “variable=123” Не меньше одного раза +a Опциональное -a Разность a-b Список a%b ‘И’ в любом порядке a^b
  • 20.
    Операторы Описание Синтаксис ‘ИЛИ’ a|b Последовательно a >> b int_ % ‘,’ 0 или множество раз *a “1,2,3,4” Не меньше одного раза +a Опциональное -a Разность a-b Список a%b ‘И’ в любом порядке a^b
  • 21.
    Операторы Описание Синтаксис ‘ИЛИ’ a|b Последовательно a >> b int_ ^ alpha 0 или множество раз *a “12a” Не меньше одного раза +a “a12” Опциональное -a Разность a-b Список a%b ‘И’ в любом порядке a^b
  • 22.
    Атрибуты int varInt; parse(…, int_,varInt) int varInt; double varDbl; parse(…, int_ >> “_“ >> double_, varInt, varDbl) double varDbl; parse(…, int_(8) >> char_(“_“) >> double_, varDbl)
  • 23.
    Атрибуты операторов Описание Синтаксис 0 или множество раз *a a: A --> *a: vector<A> a: Unused --> *a: Unused правило : атрибут правила --> выражение : атрибут выражения int_ : int --> *int_ : vector<int>
  • 24.
    Атрибуты операторов Описание Синтаксис Последовательно a >> b std::pair<A,B> a: A, b: B --> (a >> b): tuple<A, B> a: A, b: Unused --> (a >> b): A a: Unused, b: B --> (a >> b): B a: Unused, b: Unused --> (a >> b): Unused
  • 25.
    Атрибуты операторов Описание Синтаксис Последовательно a >> b a: A, b: A --> (a >> b): vector<A> a: vector<A>, b: A --> (a >> b): vector<A> a: A, b: vector<A> --> (a >> b): vector<A> a: vector<A>, b: vector<A> --> (a >> b): vector<A>
  • 26.
    Управление атрибутами Описание Синтаксис Игнорирование атрибута omit[] Экспорт промежутка на котором raw[] сработало правило [first,last] a: A --> omit[a]: unused_type a: A --> raw[a]: boost::iterator_range<Iter>
  • 27.
  • 28.
    Атрибуты операторов перезагрузка std::string data(“1 2 3 4 5 6"); std::list< int > numbers; phrase_parse(data.begin(), data.end(), *int_, space, numbers);
  • 29.
    Атрибуты операторов перезагрузка std::string data(“1,2,3,4,5,6"); std::list< int > numbers; phrase_parse(data.begin(), data.end(), (int_ % ‘,’), space, numbers);
  • 30.
    Атрибуты операторов перезагрузка std::string data("p=3.14 g=9.8"); std::list< std::pair<std::string, double> > records; phrase_parse(data.begin(), data.end(), *( +alpha >> ”=“ >> double_ ), space, records);
  • 31.
    Атрибуты операторов перезагрузка std::string data("p=3.14 g=9.8"); std::map<std::string, double> records; phrase_parse(data.begin(), data.end(), *( +alpha >> ”=“ >> double_ ), space, records);
  • 32.
    Атрибуты операторов перезагрузка std::string data(“n p=3.14 n g=9.8 "); std::map<std::string, double> records; phrase_parse(data.begin(), data.end(), *( +alpha >> ”=“ >> double_ ), space, records);
  • 33.
    Пользовательский тип struct Record { std::stringname; double value; }; BOOST_FUSION_ADAPT_STRUCT( Record, (std::string, name) (double, value) )
  • 34.
    Атрибуты операторов революция std::string data("p=3.14 g=9.8"); std::list<Record> records; phrase_parse(data.begin(), data.end(), *( +alpha >> ”=“ >> double_ ), space, records);
  • 35.
    Custom action std::string data("p=3.14g=9.8"); void SomeFnc(Record& rec) { std::cout << rec.name << " " << rec.value << std::endl; } qi:rule<std::string::const_iterator,Record()> recRule = +alpha >> ”=“ >> double_; phrase_parse(data.begin(), data.end(), *(recRule [&SomeFnc] ), space);
  • 36.
  • 37.
    Пользовательские правила • Новыеправила создаются на базе уже существующих • Правило может иметь локальные переменные • Правило может принимать входные параметры • Правило экспортирует атрибут
  • 38.
    Пользовательские правила template <typenameIterator, typename Signature> struct rule; qi::rule<char*, std::vector<int>()> start; qi::rule<char*, std::vector<int>(int)> start; qi::rule<char*, …, qi::locals<int> > start;
  • 39.
    Пример struct Record { std::string name; doublevalue; }; qi::rule<…, std::string()> name = +char_ - ‘=’; qi::rule<…, double()> value = ‘*’ >> double_ >> ‘+’; qi::rule<…, Record()> start = name >> ‘=‘ >> value;
  • 40.
    Грамматика • Объединяет правилав более высокоуровневую абстракцию • Экспортирует атрибут • Может иметь локальные переменные • Предоставляет каллбеки об ошибках
  • 41.
    Организация грамматики template <typenameIterator> struct my_grammar: qi::grammar<Iterator, mini_xml() > { my_grammar() : my_grammar ::base_type(xml) { … start = name >> ‘=‘ >> value; } qi::rule<…, Record()> start; qi::rule<…, double()> value; qi::rule<…, std::string()> name; };
  • 42.
    Обработка ошибок ... xml =… … on_error<fail> ( xml , std::cout << val("Error! Expecting ") << _4 // what failed? << val(" here: "") << construct<std::string>(_3, _2) // iterators to error-pos, end << val(""") << std::endl ); } Input: “<foo><bar></foo></bar>” Error! Expecting "bar" here: "foo></bar>" Error! Expecting end_tag here: "<bar></foo></bar>" ------------------------- Parsing failed -------------------------
  • 43.
    Karma API sprintf( …,”%d”,var) generate(…, int_, var)
  • 44.
  • 45.
    Проблемы • Листинг обошибке длиною в вечность • Время компиляции зашкаливает • Отладка в уме
  • 46.
    Листинг об ошибкедлиною в вечность
  • 47.
    Листинг об ошибкедлиною в вечность • Дойти до первой строки ошибки - это ваш файл. • Одной строкой выше будет файл спирита.
  • 48.
  • 49.
    Время компиляции #include <boost/spirit/include/qi.hpp> std::stringdata("12 23 34 56"); std::list<int> numbers; phrase_parse(data.begin(), data.end(), *int_, space, numbers); Тестовая система: Core 2 Duo T7100 1.8 Гц Время компиляции: ~20 сек (Release or Debug) Размер exe файла: 180 кб (71 кб для main(),std::cout<< “Hi”;- ) Используя Precompiled Header Время компиляции: < 1 сек (Release or Debug) Размер PCH файла: 100 мб.
  • 50.
    Время компиляции Middle-size парсериз реального проекта 400 строк кода. 1 парсер и 2 генератора. Время компиляции: ~ 5 мин. RAM использовано: 1.5 Гб Размер exe файла: 1.4 Мб(Release) & 3.5 Мб(Debug) Размер (output dir) для одной конфигурации: 876 мб Используя Precompiled Header Время компиляции: ~ 4 мин 30 сек Размер PCH файла: 150 мб. Установив Debug Information Format -> Disabled Время компиляции: ~ 3 мин 20 сек. Экономия: 200 мб(для одного cpp) и 527 мб(для проекта)
  • 51.
    Отладка BOOST_SPIRIT_DEBUG_NODE( NODE ) std::string data("12 23"); std::list<int> numbers; rule<std::string::const_iterator,int(),space_type> testRule = int_; BOOST_SPIRIT_DEBUG_NODE(testRule); phrase_parse(data.begin(), data.end(), *testRule , space, numbers);
  • 52.
    Отладка <testRule> <try>12 23</try> <success> 23</success> “12 23” <attributes>[12]</attributes> </testRule> <testRule> <try> 23</try> <success></success> “12 23” <attributes>[23]</attributes> </testRule> <testRule> “12 23” <try></try> <fail/> </testRule> Press any key to continue . . .
  • 53.
  • 54.
    ANTLR • Отдельная средаразработки и наличие плагинов для Eclipse • Генерирует парсер на языках: ActionScript, C, C#, Java, JavaScript, Objective-C, Perl, Python, Ruby • Статическая проверка правил • Интерпритатор • Отладчик
  • 55.
  • 56.
    bison/yacc Копипаста с википедии Advantages: 1. An LALR parser is fast (if the parsing algorithm uses a matrix parser-table format). 2. An LALR parser is linear in speed (i.e. the speed is based on the size of the input text file only and not based on the size of the language being recognized). Disadvantages: 1. Software engineers are required to use an LALR parser generator, which may or may not be user friendly and may require some learning time. 2. Implementing meaningful error messages in the parser may be very difficult or impossible. 3. Understanding the parsing algorithm is often quite difficult. 4. If an error occurs, it may be difficult to determine whether it's in the grammar or the parser code. 5. If there is an error in the parser generator, this may be very difficult to fix.
  • 58.
  • 59.
  • 60.
    Атрибуты операторов Описание Синтаксис ‘ИЛИ’ a|b a: A, b: B --> (a | b): variant<A, B> a: A, b: Unused --> (a | b): optional<A> a: Unused, b: B --> (a | b): optional<B> a: Unused, b: Unused --> (a | b): Unused a: A, b: A --> (a | b): A
  • 61.
    Placeholders Placeholder Description _1, _2, … Nth attribute of the parser. _val The enclosing rule’s synthesized attribute. _r1, _r2, ... The enclosing rule’s Nth inherited attribute. _a, _b, ..., _j The enclosing rule’s local variables. _pass Assign false to force parser failure. qi::rule<char*, int> = lit(“EnumValue") [ val_ = MyEnum::Value ]