Используя ANTLR4, я постоянно возвращаюсь к той же проблеме - как реализовать проверку алгоритмических правил в парсере.
Например, мне нужен синтаксический анализатор для проверки части «год» даты, записанной «месяц день год», перед тем, как соответствовать правилу. Я узнал, что могу сделать это с помощью следующего предиката:
date :
{isYear(_input.LT(3).getText())}?
month day=INTEGER year=INTEGER { ... }
Но это решение не является общим, поскольку оно зависит от правила month
, которое всегда имеет длину в один токен.
Я думал, что нашел способ обойти эту проблему, изменив правило на это:
date : month day=INTEGER yearInt { ... } ;
yearInt returns [int i]
: {isYear(_input.LT(1).getText())}?
yr=INTEGER { $i = $yr.int; }
;
К сожалению, эта грамматика принимает за дату «11 июля 6», хотя isYear("6")
не работает. Когда я отслеживаю сгенерированный ANTLR код в XXParser.java для yearInt()
, я вижу, что он вызывает
throw new FailedPredicateException(this, "isYear(_input.LT(1).getText())");
но затем код продолжает действовать и все равно принимает yearInt()
.
Это ошибка ANTLR или моя ошибка? Есть ли «правильный» способ написать грамматику, которая должна проверять правильность частей правила?