SlideShare a Scribd company logo
1 of 61
Опыт использования
    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 ]

More Related Content

What's hot

Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программированияAlex.Kolonitsky
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормозаAlexander Shigin
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияYandex
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf Conference
 
Functional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - finalFunctional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - finalAndrei Solntsev
 
Как написать JIT компилятор
Как написать JIT компиляторКак написать JIT компилятор
Как написать JIT компиляторAndrew Aksyonoff
 
Красота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки PythonКрасота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки PythonPython Meetup
 
Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Sergey Schetinin
 
основы программирования на языке C
основы программирования на языке Cосновы программирования на языке C
основы программирования на языке Cstudent_kai
 
Погружение в Dart
Погружение в DartПогружение в Dart
Погружение в DartSergey Penkovsky
 
Михаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияМихаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияYandex
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Alexander Granin
 
Артем Яворский "@babel/core": "7.x"
Артем Яворский "@babel/core": "7.x"Артем Яворский "@babel/core": "7.x"
Артем Яворский "@babel/core": "7.x"Fwdays
 

What's hot (15)

Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программирования
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормоза
 
Scala
ScalaScala
Scala
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знания
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
 
Functional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - finalFunctional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - final
 
Урок 7. Интерпретация и компиляция функциональных программ.
Урок 7. Интерпретация и компиляция функциональных программ.Урок 7. Интерпретация и компиляция функциональных программ.
Урок 7. Интерпретация и компиляция функциональных программ.
 
Как написать JIT компилятор
Как написать JIT компиляторКак написать JIT компилятор
Как написать JIT компилятор
 
Красота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки PythonКрасота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки Python
 
Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование
 
основы программирования на языке C
основы программирования на языке Cосновы программирования на языке C
основы программирования на языке C
 
Погружение в Dart
Погружение в DartПогружение в Dart
Погружение в Dart
 
Михаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияМихаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знания
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++
 
Артем Яворский "@babel/core": "7.x"
Артем Яворский "@babel/core": "7.x"Артем Яворский "@babel/core": "7.x"
Артем Яворский "@babel/core": "7.x"
 

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

Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиSQALab
 
Командная разработка “толстых клиентов”
Командная разработка “толстых клиентов”Командная разработка “толстых клиентов”
Командная разработка “толстых клиентов”Open-IT
 
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...CocoaHeads
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 
Мифы и легенды Java Stream API
Мифы и легенды Java Stream APIМифы и легенды Java Stream API
Мифы и легенды Java Stream APICEE-SEC(R)
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Яковенко Кирилл
 
Статический анализатор кода для InterSystems Caché Object Script
Статический анализатор кода для InterSystems Caché Object ScriptСтатический анализатор кода для InterSystems Caché Object Script
Статический анализатор кода для InterSystems Caché Object ScriptInterSystems
 
Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиZestranec
 
основы Java переменные, циклы
основы Java   переменные, циклыосновы Java   переменные, циклы
основы Java переменные, циклыSergey Nemchinsky
 
AlgoCollections (RUS)
AlgoCollections (RUS)AlgoCollections (RUS)
AlgoCollections (RUS)Anton Bukov
 
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...OdessaFrontend
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupMail.ru Group
 
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)Ontico
 

Similar to CiklumCPPSat: Ivan Romanenko "Experience of work with Boost Spirit" (20)

Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасности
 
Командная разработка “толстых клиентов”
Командная разработка “толстых клиентов”Командная разработка “толстых клиентов”
Командная разработка “толстых клиентов”
 
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
 
Java8. Innovations
Java8. InnovationsJava8. Innovations
Java8. Innovations
 
Programming c++ (begin-if-else)
Programming c++ (begin-if-else)Programming c++ (begin-if-else)
Programming c++ (begin-if-else)
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
Мифы и легенды Java Stream API
Мифы и легенды Java Stream APIМифы и легенды Java Stream API
Мифы и легенды Java Stream API
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
 
Статический анализатор кода для InterSystems Caché Object Script
Статический анализатор кода для InterSystems Caché Object ScriptСтатический анализатор кода для InterSystems Caché Object Script
Статический анализатор кода для InterSystems Caché Object Script
 
Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасности
 
Rgsu04
Rgsu04Rgsu04
Rgsu04
 
Rgsu04
Rgsu04Rgsu04
Rgsu04
 
основы Java переменные, циклы
основы Java   переменные, циклыосновы Java   переменные, циклы
основы Java переменные, циклы
 
AlgoCollections (RUS)
AlgoCollections (RUS)AlgoCollections (RUS)
AlgoCollections (RUS)
 
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
 
20110227 csseminar alvor_breslav
20110227 csseminar alvor_breslav20110227 csseminar alvor_breslav
20110227 csseminar alvor_breslav
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
 
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
 
Java 8 puzzlers
Java 8 puzzlersJava 8 puzzlers
Java 8 puzzlers
 
Step cpp0201
Step cpp0201Step cpp0201
Step cpp0201
 

More from Ciklum Ukraine

"How keep normal blood pressure using TDD" By Roman Loparev
"How keep normal blood pressure using TDD" By Roman Loparev"How keep normal blood pressure using TDD" By Roman Loparev
"How keep normal blood pressure using TDD" By Roman LoparevCiklum Ukraine
 
"Through the three circles of the it hell" by Roman Liashenko
"Through the three circles of the it hell" by Roman Liashenko"Through the three circles of the it hell" by Roman Liashenko
"Through the three circles of the it hell" by Roman LiashenkoCiklum Ukraine
 
Alex Pazhyn: Google_Material_Design
Alex Pazhyn: Google_Material_DesignAlex Pazhyn: Google_Material_Design
Alex Pazhyn: Google_Material_DesignCiklum Ukraine
 
Introduction to amazon web services for developers
Introduction to amazon web services for developersIntroduction to amazon web services for developers
Introduction to amazon web services for developersCiklum Ukraine
 
Your 1st Apple watch Application
Your 1st Apple watch ApplicationYour 1st Apple watch Application
Your 1st Apple watch ApplicationCiklum Ukraine
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven DevelopmentCiklum Ukraine
 
Back to the future: ux trends 2015
Back to the future: ux trends 2015Back to the future: ux trends 2015
Back to the future: ux trends 2015Ciklum Ukraine
 
Developing high load systems using C++
Developing high load systems using C++Developing high load systems using C++
Developing high load systems using C++Ciklum Ukraine
 
Collection view layout
Collection view layoutCollection view layout
Collection view layoutCiklum Ukraine
 
Introduction to auto layout
Introduction to auto layoutIntroduction to auto layout
Introduction to auto layoutCiklum Ukraine
 
Unit Testing: Special Cases
Unit Testing: Special CasesUnit Testing: Special Cases
Unit Testing: Special CasesCiklum Ukraine
 
Model-View-Controller: Tips&Tricks
Model-View-Controller: Tips&TricksModel-View-Controller: Tips&Tricks
Model-View-Controller: Tips&TricksCiklum Ukraine
 
Future of Outsourcing report published in The Times featuring Ciklum's CEO To...
Future of Outsourcing report published in The Times featuring Ciklum's CEO To...Future of Outsourcing report published in The Times featuring Ciklum's CEO To...
Future of Outsourcing report published in The Times featuring Ciklum's CEO To...Ciklum Ukraine
 
Михаил Попчук "Cкрытые резервы команд или 1+1=3"
Михаил Попчук "Cкрытые резервы команд или 1+1=3"Михаил Попчук "Cкрытые резервы команд или 1+1=3"
Михаил Попчук "Cкрытые резервы команд или 1+1=3"Ciklum Ukraine
 

More from Ciklum Ukraine (20)

"How keep normal blood pressure using TDD" By Roman Loparev
"How keep normal blood pressure using TDD" By Roman Loparev"How keep normal blood pressure using TDD" By Roman Loparev
"How keep normal blood pressure using TDD" By Roman Loparev
 
"Through the three circles of the it hell" by Roman Liashenko
"Through the three circles of the it hell" by Roman Liashenko"Through the three circles of the it hell" by Roman Liashenko
"Through the three circles of the it hell" by Roman Liashenko
 
Alex Pazhyn: Google_Material_Design
Alex Pazhyn: Google_Material_DesignAlex Pazhyn: Google_Material_Design
Alex Pazhyn: Google_Material_Design
 
Introduction to amazon web services for developers
Introduction to amazon web services for developersIntroduction to amazon web services for developers
Introduction to amazon web services for developers
 
Your 1st Apple watch Application
Your 1st Apple watch ApplicationYour 1st Apple watch Application
Your 1st Apple watch Application
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Back to the future: ux trends 2015
Back to the future: ux trends 2015Back to the future: ux trends 2015
Back to the future: ux trends 2015
 
Developing high load systems using C++
Developing high load systems using C++Developing high load systems using C++
Developing high load systems using C++
 
Collection view layout
Collection view layoutCollection view layout
Collection view layout
 
Introduction to auto layout
Introduction to auto layoutIntroduction to auto layout
Introduction to auto layout
 
Groovy on Android
Groovy on AndroidGroovy on Android
Groovy on Android
 
Unit Testing: Special Cases
Unit Testing: Special CasesUnit Testing: Special Cases
Unit Testing: Special Cases
 
Material design
Material designMaterial design
Material design
 
Kanban development
Kanban developmentKanban development
Kanban development
 
Mobile sketching
Mobile sketching Mobile sketching
Mobile sketching
 
More UX in our life
More UX in our lifeMore UX in our life
More UX in our life
 
Model-View-Controller: Tips&Tricks
Model-View-Controller: Tips&TricksModel-View-Controller: Tips&Tricks
Model-View-Controller: Tips&Tricks
 
Unit Tesing in iOS
Unit Tesing in iOSUnit Tesing in iOS
Unit Tesing in iOS
 
Future of Outsourcing report published in The Times featuring Ciklum's CEO To...
Future of Outsourcing report published in The Times featuring Ciklum's CEO To...Future of Outsourcing report published in The Times featuring Ciklum's CEO To...
Future of Outsourcing report published in The Times featuring Ciklum's CEO To...
 
Михаил Попчук "Cкрытые резервы команд или 1+1=3"
Михаил Попчук "Cкрытые резервы команд или 1+1=3"Михаил Попчук "Cкрытые резервы команд или 1+1=3"
Михаил Попчук "Cкрытые резервы команд или 1+1=3"
 

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 мои друзья
  • 7. Парсер в одной функции
  • 9. Области применения • Специализированные конфигурационные файлы • Коммуникация с устройствами • Поддержка произвольных форматов данных • Всё что угодно, имеющее «синтаксис»
  • 10. Что такое Boost Spirit ? • Это объектено-ориентированный нисходящий синтаксический анализатор. • Позволяет описывать формат используя синтаксис, приближённый к 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>
  • 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::string name; 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.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);
  • 37. Пользовательские правила • Новые правила создаются на базе уже существующих • Правило может иметь локальные переменные • Правило может принимать входные параметры • Правило экспортирует атрибут
  • 38. Пользовательские правила 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;
  • 39. Пример struct Record { std::string name; double value; }; qi::rule<…, std::string()> name = +char_ - ‘=’; qi::rule<…, double()> value = ‘*’ >> double_ >> ‘+’; qi::rule<…, Record()> start = name >> ‘=‘ >> value;
  • 40. Грамматика • Объединяет правила в более высокоуровневую абстракцию • Экспортирует атрибут • Может иметь локальные переменные • Предоставляет каллбеки об ошибках
  • 41. Организация грамматики 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; };
  • 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)
  • 45. Проблемы • Листинг об ошибке длиною в вечность • Время компиляции зашкаливает • Отладка в уме
  • 46. Листинг об ошибке длиною в вечность
  • 47. Листинг об ошибке длиною в вечность • Дойти до первой строки ошибки - это ваш файл. • Одной строкой выше будет файл спирита.
  • 49. Время компиляции #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 мб.
  • 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 . . .
  • 54. ANTLR • Отдельная среда разработки и наличие плагинов для Eclipse • Генерирует парсер на языках: ActionScript, C, C#, Java, JavaScript, Objective-C, Perl, Python, Ruby • Статическая проверка правил • Интерпритатор • Отладчик
  • 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.
  • 57.
  • 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 ]