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 мои друзья
9. Области применения
• Специализированные конфигурационные
файлы
• Коммуникация с устройствами
• Поддержка произвольных форматов данных
• Всё что угодно, имеющее «синтаксис»
10. Что такое Boost Spirit ?
• Это объектено-ориентированный нисходящий
синтаксический анализатор.
• Позволяет описывать формат используя
синтаксис, приближённый к EBNF(Расширенной
форме Бэкуса – Наура), прямо в С++ коде.
• Позволяет связывать описание синтаксиса с
конкретными типами данных, обеспечивая
строгую типизацию.
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
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>
37. Пользовательские правила
• Новые правила создаются на базе уже
существующих
• Правило может иметь локальные переменные
• Правило может принимать входные параметры
• Правило экспортирует атрибут
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. Грамматика
• Объединяет правила в более
высокоуровневую абстракцию
• Экспортирует атрибут
• Может иметь локальные переменные
• Предоставляет каллбеки об ошибках
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 мб(для проекта)
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.
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 ]