为什么此规则中存在递归溢出?

时间:2012-05-02 15:28:17

标签: antlr

这是此问题的“跟进”:How to parse a parenthesized hierarchy root?(知道root规则现已重命名为atom)。

在我的ANTLR语法中,我现在尝试添加对强制转换的支持:

cast : '(' type ')' atom -> ^(CAST type atom);

现在,我需要将它作为值树的一部分。由于强制转换本身就是原子,可以作为层次结构的基础,并且可以用于任何二进制操作(因子,总和,比较),我认为它必须进入atom(以前为root }) 规则。

cast : '(' type ')' atom -> ^(CAST type atom);

atom : cast | IDENTIFIER | SELF | literal | constructor | call | indexer | '('! value ')'!;

hierarchy : atom (SUB^ (IDENTIFIER | call | indexer))*;

factor : hierarchy ((MULT^ | DIV^ | MODULO^) hierarchy)*;

sum : factor ((PLUS^ | MINUS^) factor)*;

comparison : sum (comparison_operator^ sum)*;

value : comparison;

幸运的是,这一次似乎一切都是LL(*)。但是,我从typetype获得无限递归:

type : name=IDENTIFIER (LESSER (generics+=type (SEPARATOR generics+=type)*) GREATER)? -> ^(TYPE $name ^(GENERICS $generics*));
  

[rule atom ]备选方案1 [ cast ]:匹配输入后如PAREN_OPEN IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER {LESSER,SEPARATOR}决定无法预测接下来由于递归溢出到类型

此案例反映了(x<x<x<x<x[</,]

等内容

ANTLR的错误非常难以理解。我已经重新阅读了解释这个确切错误的章节,但我仍然没有得到它。我还不明白的是,在独立的基础上,type规则从未触发任何无限递归警告。

我该如何解决?并且,为了我对ANTLR的理解,你能解释为什么它现在触发吗?

1 个答案:

答案 0 :(得分:2)

我不会说ANTLR的错误消息(全部)是不可穿透的,但是,这个错误是......

在这种情况下,ANTLR在关系表达式IDENTIFIER < atomIDENTIFIER < ...之间存在问题,该关系表达式是type的一部分。这两种选择都可以作为atom规则的开始。

您可以通过更改泛型类型的开头来验证这一点,使其与关系LT表达式的开头不同:

type
 : IDENTIFIER ('@' (type (',' type)*) '>')?
 ;

或将LT标志保留为通用类型,但要从IDENTIFIER规则中删除atom

type
 : IDENTIFIER ('<' (type (',' type)*) '>')?
 ;

atom
 : cast 
 //| IDENTIFIER
 | SELF
 | literal
 | constructor
 | call
 | indexer
 | '('! value ')'!
 ;

我知道,两者当然都不是现实的选择。

要让ANTLR对语法感到满意,您可以在cast规则中atom替代前面添加一个句法谓词(并保留当前的type规则它):

atom
 : (cast)=> cast 
 | IDENTIFIER
 | SELF
 | literal
 | constructor
 | call
 | indexer
 | '('! value ')'!
 ;

这会强制解析器首先向前看,并确保确实cast替代匹配,如果没有,则它会落到atom的后续替代中{1}}规则。

但是这里更好的选择是你不允许你的语法匹配关系表达式,如:

a < b < c

这没有多大意义:关系表达式a < b通常求值为布尔值,无法与c进行比较,对吧?此外,您现在将所有逻辑运算符,关系运算符和相等运算符组合在一个规则中,使它们 all 具有相同的优先级:而在大多数情况下,OR具有最低值,然后来{ {1}},然后是平等,然后是关系运算符。

所以,而不是:

AND

做的:

value      : comparison;
comparison : sum (comparison_operator^ sum)?;
...

comparison_operator : EQUAL | NOT_EQUAL | GREATER | LESSER
                    | GREATER_OR_EQUAL | LESSER_OR_EQUAL 
                    | AND | OR
                    ;

然后您不需要value : or; or : and (OR^ and)*; and : eq (AND^ eq)*; eq : rel ((EQUAL | NOT_EQUAL)^ rel)?; // note the '?' and no '*' rel : sum ((GREATER | LESSER | GREATER_OR_EQUAL | LESSER_OR_EQUAL)^ sum)?; // note the '?' and no '*' sum : factor ((PLUS | MINUS)^ factor)*; ... 规则中的type前面的谓词和,您的运算符优先顺序正确。