18 июня, 2008

antlr и DSL языки

Задача. Есть биллинг, который аккумулирует данные по операциям. Нужно предоставить интерфейс (программный) для получения отчетов. Каждый отчет может быть параметризирован. Например, получить определенный отчет (скажем начисления за месяц) для какого-то конкретного клиента. Список отчетов будет изменятся, будут разрабатываться новые. Учитывая требования, пришел к выводу, что наилучший вариант предоставить клиенту декларативный язык для получения данных. Что-то вроде:
build DepositReport
 from '2008-01-01' to '2008-02-01'
 with userId = 15, depositGround = 'cash'
Решил написать грамматику для реализации парсера на antlr. К моему удивлению, справился за пол часа, а результирующая грамматика занимала 35 строчек кода. На выходе я имел следующий интерфейс.
RQLParser parser = new RQLParser()
ANTLRStringStream input = new ANTLRStringStream(
"build report "+
  "from '2005-01-15' to '2005-02-12' "+
  "with id = 25, subject = 'text'");
RQLLexer lexer = new RQLLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
RQLParser parser = new RQLParser(tokens);
parser.query();

parser.reportName; // имя отчета
parser.dateFrom; // начало диапазона
parser.dateTo; // конец диапазона

/* Список объектов представляющий
  собой правила фильтрации */
parser.criteriaList;

Вполне удобно и легко поддается модификации. Поменял грамматику, запустил генератор, - вот тебе и новый парсер. Пожалуй пора отказываться от регулярок. Достал этот write-only.

1 комментарий:

  1. Вот тут есть обзор из чего состоит ANTLR и какие есть средства для него http://gocha.org/drupal/?q=node/112
    и есть немного о том как написать парсер математических выражений

    ОтветитьУдалить