ANTLR и DSL

18 June 2008 antlr dsl java

Задача. Есть биллинг, который аккумулирует данные по операциям. Нужно предоставить интерфейс (программный) для получения отчетов. Каждый отчет может быть параметризирован. Например, получить определенный отчет (скажем начисления за месяц) для какого-то конкретного клиента. Список отчетов будет изменятся, будут разрабатываться новые. Учитывая требования, пришел к выводу, что наилучший вариант предоставить клиенту декларативный язык для получения данных. Что-то вроде:

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.