В Antlr3 у меня есть следующая грамматика:
ruleA:
(ruleBStart) => ruleB
| ruleC
;
Для простоты предположим, что ruleB — это грамматика для оператора SELECT в SQL, но может быть вложено в произвольное количество LPAREN. Это легко представить в старой грамматике, просто сказав:
ruleBStart:
(LPAREN)* SELECT
;
В Antlr4, если бы я хотел сделать то же самое, я бы написал семантический предикат isRuleBStart()
который может выглядеть так (псевдокод):
@parser::members{
public boolean isRuleBStart(int tokenNum)
{
int token = _input.LA(tokenNum);
if (token == EOF) return false; // handling EOF probably needs more work
if (token == SELECT) return true;
if (token == LPAREN) return isRuleBStart(tokenNum++);
return false;
}
}
И тогда в моей грамматике я бы сделал:
ruleA:
{isRuleBStart(1)}? ruleB
| ruleC
;
Это кажется проблематичным для меня, так как:
ruleBStart
могло бы стать намного сложнее, если бы в правиле ruleBStart имелся произвольный набор различных токенов для проверки вместо простого повторения LPARENПоэтому я хочу спросить сообщество, существует ли правильный путь Antlr4 для достижения того же результата.
Нет необходимости в семантическом предикате с ANTLR4. Алгоритм ALL (*) будет выполнять неограниченный просмотр, если это необходимо, и, следовательно, не требует семантических предикатов или какого-либо сопоставимого взлома.
Так что, просто удалите этот предикат, и все должно работать.
Других решений пока нет …