Wizard Parser, v1.0
Posted on

LL(*)-парсер на C++ с поддержкой DSL для описания грамматики в EBNF непосредственно в коде программы.
Мажорный релиз.
Возможности
- парсинг ASCII-текста;
- описание грамматики на EBNF непосредственно в коде программы (посредством DSL);
- представление результата в виде:
- дерева парсинга;
- AST;
- гибкое управление представлением нод в AST:
- задание имени ноды;
- объединение нод;
- скрытие ноды;
- сериализация AST в XML;
- поддержка полноценной грамматики в качестве разделителя для основной;
- комбинаторы:
- следование;
- альтернатива;
- повторение:
- 0 или больше раз;
- 1 или больше раз;
- опциональность;
- исключение;
- список с разделителем;
- парсеры:
- пустой (ничего не парсит);
- граница слова (правило
\bв регулярных выражениях); - конец текста;
- парсеры символов:
- парсер определённого символа;
- парсер любого символа;
- парсеры любого символа из определённого набора:
- парсер любого символа из определённого набора;
- парсер пробельных символов;
- парсер букв;
- парсер цифр;
- парсер букв, цифр и символа
_;
- парсеры определённого текста:
- парсер определённого текста;
- парсер определённого текста, ограниченного границами слова (правило
\bв регулярных выражениях).
Пример использования
#include <wizard_parser/parser/Parser.h>
#include <cstring>
#include <iostream>
using namespace thewizardplusplus::wizard_parser::parser;
/* Grammar description in EBNF:
*
* expression = disjunction;
* disjunction = conjunction, {"or", conjunction};
* conjunction = equality, {"and", equality};
* equality = comparison, {("==" | "/="), comparison};
* comparison = sum, {("<" | "<=" | ">" | ">="), sum};
* sum = product, {("+" | "-"), product};
* product = unary, {("*" | "/"), unary};
* unary = {"-" | "not"}, atom;
* atom = number | ("(", expression, ")");
* number = ? /\d+(\.\d+)?/ ?;
*/
Parser grammar(void) {
const auto expression = dummy();
WP_RULE(number)
disable_separation(lexeme(+digit() >> !('.'_s >> +digit())))
WP_END
WP_RULE(atom) number | hide('('_s) >> expression >> hide(')'_s) WP_END
WP_RULE(unary) *('-'_s | word("not"_t)) >> atom WP_END
WP_RULE(product) list(unary, '*'_s | '/'_s) WP_END
WP_RULE(sum) list(product, '+'_s | '-'_s) WP_END
WP_RULE(comparison) list(sum, '<'_s | "<="_t | '>'_s | ">="_t) WP_END
WP_RULE(equality) list(comparison, "=="_t | "/="_t) WP_END
WP_RULE(conjunction) list(equality, hide(word("and"_t))) WP_END
WP_RULE(disjunction) list(conjunction, hide(word("or"_t))) WP_END
assign(expression, disjunction);
const auto grammar = expression >> end();
const auto separator = hide(*space());
return separation(separator, grammar);
}
int main(int number_of_arguments, char* arguments[]) try {
if (number_of_arguments == 1 || std::strlen(arguments[1]) == 0) {
throw std::invalid_argument("expression not specified");
}
const auto expression = arguments[1];
const auto parser = grammar();
std::cout
<< "<?xml version = \"1.0\" encoding = \"utf-8\" ?>"
<< parse(parser, expression, SimplifyLevel::AST)
<< "\n";
} catch (std::exception& exception) {
std::cerr << "Error: \"" << exception.what() << "\".\n";
std::exit(EXIT_FAILURE);
}
Репозиторий
Ссылка: https://github.com/thewizardplusplus/wizard-parser/tree/v1.0.
Содержание: код, документация, пример использования.
Лицензия: MIT.