我正在编写一个语法来处理标量和向量表达式。下面的语法被简化以显示我所遇到的问题,其中标量表达式可以从向量导出,并且向量可以从标量导出。例如,矢量可以是文字[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
,反之亦然,但同时它应该是确定性的。
我如何重构这个语法以避免相互(间接)左递归?我可以expand one of the terms inplace,但这会在完整的语法中引入很多重复,其中有更多的矢量和标量替代品。我也可以refactor the grammar to have a primary expression,但我不想允许scalar '*' scalar
作为有效的vector
替代方案。还有其他选择吗?
答案 0 :(得分:4)
AFAIK,没有办法解决它,而是扩展以消除间接递归规则:
expression
: scalar
| vector
;
scalar
: '[' Integer ',' Integer ',' Integer ']' '[' Integer ']'
| scalar '*' vector '[' Integer ']'
| Integer
;
vector
: '[' Integer ',' Integer ',' Integer ']'
| scalar '*' vector
;
答案 1 :(得分:-1)
scalar
: Integer
| vector '[' Integer ']'
;
vector
: '[' Integer ',' Integer ',' Integer ']'
| scalar '*' vector
;
表示你可以写一个表达式
[i,i,i][i] * [i,i,i][i] * ... * [i,i,i]
这将为Java和其他具有有限堆栈深度的语言呈现解析器的堆栈溢出。
我认为你应该为矢量查找创建一个不同的语法规则,它不是标量,它只是标量中的结果,但这应该在解析器树处理中处理,而不是在ANTLR中处理