-
Связующее звено между представлениями одних и тех же сущностей
-
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
— более "тонкий" разбор выражения
namespace x3 = 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<class item, 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>
-
Тип атрибута
-
Идентификатор правила
-
Тип правила
-
Определение правила
-
Само правило
struct my_type { ... };
struct my_rule_class;
const x3::rule<my_rule_class, my_type> my_rule_type = "my_rule";
const auto 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]