Связующее звено между представлениями одних и тех же сущностей
AST — abstract syntax tree
EBNF (Extended Backus-Naur Form — язык описания грамматики
Рекурсивность, как полнота грамматики
PEG (Parsing Expression Grammar) — Domain Specific Embedded Language
Почитать про boost::spirit::x3.
x3::rule<ID, Attribute>
Правила составляются из парсеров, которые захватывают атрибуты
Synthesized attribute — атрибут по умолчанию
Compatible attribute — совместимый (конвертируемый) атрибут (
std::string
иstd::vector<char>
)
Грамматика — набор правил и специальных атрибутов для построения AST
link:images/rule.dot[role=include]
int_
,short_
,long_
,int_(42)
, … — парсеры целых чиселdouble_
,float_
,double_(42.2)
, … — парсеры действительных чиселbool_
,true_
,false_
— булевы парсерыlit("abc")
,char_
,char_("A-Za-z")
, … — литеральные парсеры (точное соответствие строке)alnum
,blank
,space
,lower
, … — классификаторыparse
— разбор выраженияphrase_parse
— более "тонкий" разбор выражения
namespacex3= boost::spirit::x3; std::string_view text{"123546"}; bool parsed = x3::parse(text.begin(), text.end(), x3::int_);
Description | PEG | Spirit X3 | Example |
---|---|---|---|
Sequence | a b | a >> b |
|
Alternative | a | b | a | b |
|
Zero or more (Kleene) | a* | *a |
|
One or more (Plus) | a+ | +a |
|
Optional | a? | -a |
|
And-predicate | &a | &a |
|
Not-predicate | !a | ~a |
|
Difference | a - b |
| |
Expectation | a > b |
| |
List | a % b |
|
Именованные парсеры
Можно указать тип атрибута
Позволяет использовать рекурсивность парсеров
Предоставляет обработчик ошибок (
on_error
)Использование пользовательских функций для определения успешного парсинга (
on_success
)
AST — удобное представление через ассоциативный рекурсивный массив
Атрибут — результат, который предоставляет конкретный парсер
Литералы не имеют атрибутов
Примитивные парсеры (
int_
,double_
, …) имеют примитивные по типу атрибуты (int
,double
, …)Нетерминалы вида
x3::rule<ID, A>
имеют атрибутA
Оператор | Его синтезируемый атрибут |
---|---|
|
|
|
|
|
|
|
|
| нет атрибута |
|
|
std::string_view text{R"(foo: bar, gorp : smart , falcou : "crazy frenchman", name:sam)"}; auto name = x3::alpha >> *x3::alnum; auto qoute = '"' >> x3::lexeme[*(~x3::char_('"'))] >> '"'; auto item = x3::rule<classitem, std::pair<std::string, std::string>>>{} = name >> ':' >> (quote | name); std::map<std::string, std::string> dict; x3::phrase_parse(text.begin(), text.end(), item % ',', x3::space, dict);
a: char, b: vector<char> → (a >> b): tuple<char, vector<char>> → vector<char> → string a: unused, b: vector<char>, c: unused → (a >> b >> c): vector<char> → string a: string, b: string → (a | b): variant<string, string> → string a: string, b: unused, c: string → (a >> b >> c): tuple<string, string> a: pair<string, string>, b: unused → (a % b): vector<pair<string, string>> → map<string, string>
Тип атрибута
Идентификатор правила
Тип правила
Определение правила
Само правило
structmy_type { ... }; structmy_rule_class; const x3::rule<my_rule_class, my_type> my_rule_type = "my_rule"; constauto my_rule_def = x3::lexeme[(x3::alpha | '_') >> *(x3::alnum | '_')]; BOOST_SPIRIT_DEFINE(my_rule)
CSV — Comma Separated Values (значения, разделённые запятыми)
Элементарная таблица/база данных
Ещё бывает TSV (tabulated)
Формат хранения — текстовый, с расширение
csv
CSV состоит из строк (первая строка считается заголовком)
Каждая строка заканчивается символом новая строка
Ячейки CSV разделяются запятой
Каждая ячейка может иметь пробелы и быть заключена в кавычки
Если нужно поставить запятую внутри ячейки, нужно обязательно использовать кавычки
link:csv.cpp[role=include]
Пропуск всех пробельных символов
Использование
x3::phrase_parse
Детектирование некорректного синтаксиса и наличие полного парсинга
link:csv.cpp[role=include]
Ячейка CSV — это строка
std::string
Каждая строка — это массив ячеек ⇒
std::vector<std::string>
Полное CSV — это массив массива ячеек ⇒
std::vector<std::vector<std::string>>
/*link:csv.cpp[role=include]*/ link:csv.cpp[role=include]
Просто переписываем EBNF для CSV
Там, где компилятор не справляется с автовыведением типа, прописываем явно
x3::rule
Добавляем дополнительную логику для экранирования символа двойной кавычки
/* EBNF:link:csv.cpp[role=include]*/ link:csv.cpp[role=include]