2014-02-19 103 views
2

我很抱歉要问关于相互左递归的另一个问题,我觉得我的情况对我的情况来说是独一无二的,或者至少我不能将它与其他人的语法联系起来。我对comp sci世界有点新(我自学java,这是我的目标语言,现在是ANTLR4),所以如果可能的话,请用非专业术语描述,而不是CS主要术语。相互左递归ANTLR 4

我正在写一个程序,需要代数和符号派生物,当然,这需要的东西被解析,树木操作,但我甚至不会担心,因为我认为ANTLR4支持直接左递归,但显然它不以某种方式。在输出中,它一直告诉我,我的方法[表达式]是相互左递归的,显然这是不允许的......? 我的问题:

1)有人可以解释左递归/相互和直接左递归之间的差异,如果有一个?

2)解释我的语法是什么导致了这种递归烦恼,以及如何解决它? 我不确定这是否是主题:

3)人们说有关替代品和标签替代品的事情(我认为它们的意思是#标签符号)。那个有什么用?

grammar MathProcessor; 
@header {package utils;} 
END: ';'; 
EQUALS: '='; 
SIN: 'sin('; 
COS: 'cos('; 
TAN: 'tan('; 
SEC: 'sec('; 
CSC: 'csc('; 
COT: 'cot('; 
LN: 'ln('; 
EPOW: 'pow('; 
RPAREN: '('; 
LPAREN: ')'; 
EXP: '^'; 
MULT: '*'; 
DIV: '/'; 
ADD: '+'; 
SUBT: '-'; 
VAR: ('a'..'z'|'A'..'Z'); 
INT: ('0'..'9')+; 
mathobj: ((equation|expression) END) EOF; 
equation: (expression '=' expression); 

expression: 
((RPAREN|SIN|COS|TAN|SEC|CSC|COT|LN|EPOW) expression (RPAREN)) #parenOps 
| (expression EXP expression) #exponent 
| (expression (MULT|DIV) expression) #multiplyDivide 
| (expression (ADD|SUBT) expression) #addSubtract 
| (VAR|INT) #varInt 
; 

回答

5

你的语法实际上与ANTLR 4工作,如果你简单地删除不必要的括号的几种情况下你的语法。左递归消除算法只适用于直接左递归,其将出现在下面的例子:

a 
    : B 
    | a B // the reference to 'a' here is direct left recursion 
    ; 

初级其它类型的递归是间接的左递归,其通过使用两个单独的规则典型地证明。

a 
    : B 
    | c 
    ; 

c 
    : a B // the reference back to 'a' is indirect left recursion 
    ; 

在你的语法的情况下,ANTLR是治疗(...)作为一个匿名分规则,所以像下面的代码被确定为间接左递归。如果从示例中删除括号,则表现与第一种情况类似。

a 
    : B 
    | (a B) 
    ; 

要回答你的最后一个问题,在#label语法变化所产生的解析树类,替代。例如,不是生成普通的ExpressionContext对象,则表达式3将生成VarIntContext。这允许您在自动生成的侦听器和访问者的规则中区分不同的备选方案。

+0

非常感谢!它经过一些调整后最终生成,使我的语法树在ANTLRworks中看起来不错!我可以看出是否可以弄清楚如何使用它,或者它是否保留了操作的顺序,但我会在稍后留下。 – user3326093