Я пишу грамматику для обработки скалярных и векторных выражений. Приведенная ниже грамматика упрощена, чтобы показать мою проблему, когда скалярное выражение может быть получено из вектора, а вектор может быть получен из скаляра. Например, вектор может быть литералом [1, 2, 3]
или произведением скаляра и вектора 2 * [1, 2, 3]
(эквивалентно [2, 4, 6]
). Скаляр может быть литералом 2
или индексом вектора [1, 2, 3][1]
(эквивалентно 2
).
grammar LeftRecursion;
Integer
: [0-9]+
;
WhiteSpace
: [ \t\r\n]+ -> skip
;
input
: expression EOF;
expression
: scalar
| vector
;
scalar
: Integer
| vector '[' Integer ']'
;
vector
: '[' Integer ',' Integer ',' Integer ']'
| scalar '*' vector
;
ANTLR4 выдает ошибку: The following sets of rules are mutually left-recursive [scalar, vector]
. Это имеет смысл, поскольку scalar
ссылается на vector
и наоборот, но в то же время должно быть детерминированным.
Как мне реорганизовать эту грамматику, чтобы избежать взаимной (косвенной) левой рекурсии? Я мог бы расширить один из терминов на месте, но это привело бы к большому количеству дублирований в полной грамматике, где есть больше альтернатив для вектора и скаляра. Я также мог бы рефакторить грамматику, чтобы иметь первичное выражение, но я не хочу разрешать scalar '*' scalar
в качестве допустимой альтернативы vector
. Есть ли другие варианты?