QapDSLv2 — это язык который транслируется в обычный C++ код. Он позволяет удобно и компактно задавать грамматики/правила разбора кода программ, значительно упрощая разработку компиляторов/анализаторов/трансляторов.
QapGen — это генератор дерева_лексеров/парсеров описанных на QapDSLv2. Сама грамматика QapDSLv2 описана на QapDSLv2 на 100%. Поэтому QapGen как основной читатель этой грамматики сам генерирует часть своего кода(весь парсер QapDSLv2).
Основные фишки QapDSLv2 + QapGen — это:
1) Отсутствие этапа токенизации — дерево лексеров разбивает входной поток на лексемы и сохраняет их в строго типизированных древовидных С++ структурах пропуская этап токенизации.
2) Генерация оптимизированного кода полиморфных лексеров.
3) Полное сохранение всех лексем(даже разделители сохраняются, такие как пробелы/переходы на новую строку и комментарии) в результирующем дереве.
4) Возможность сохранить как оригинальное дерево, так и модифицированное обратно в код/текст без потери разделителей/комментариев.
5) Автоматическая генерация кода посетителей(это такой паттерн проектирования).
А теперь пример самой сочной части(рекурсивно самоописывающийся код):
struct
t_target_struct:i_target_item{
struct
t_keyword{
string
kw=any_str_from_vec(split("struct,class",","));
" "? // optional separator
};
struct
t_body_semicolon:i_struct_impl{";"};
struct
t_body_impl:i_struct_impl{
"{" // жрём скобочку
vector<TAutoPtr<i_target_item>>
nested?; //
рекурсия!
" "?
vector<TAutoPtr<i_struct_field>>
arr?; // парсим поля
" "?
TAutoPtr<t_cpp_code>
c?; // остальной С++ код
" "?
"}"
};
struct
t_parent{
string
a_or_c=any_str_from_vec(split("=>,:",","));
" "?
t_name
name;
};
//точка входа в парсер:
TAutoPtr<t_keyword>
kw?; //парсим
struct/class
t_name
name; //парсим имя
" "?
TAutoPtr<t_parent>
parent?;
" "?
TAutoPtr<i_struct_impl>
body;
};