Задача. Есть биллинг, который аккумулирует данные по операциям. Нужно предоставить интерфейс (программный) для получения отчетов. Каждый отчет может быть параметризирован. Например, получить определенный отчет (скажем начисления за месяц) для какого-то конкретного клиента. Список отчетов будет изменятся, будут разрабатываться новые. Учитывая требования, пришел к выводу, что наилучший вариант предоставить клиенту декларативный язык для получения данных. Что-то вроде:
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.
Вот тут есть обзор из чего состоит ANTLR и какие есть средства для него http://gocha.org/drupal/?q=node/112
ОтветитьУдалитьи есть немного о том как написать парсер математических выражений