Antlr 为什么这个规则中有递归溢出?
这是对这个问题的“跟进”:(知道Antlr 为什么这个规则中有递归溢出?,antlr,Antlr,这是对这个问题的“跟进”:(知道root规则现在已重命名为atom) 在我的ANTLR语法中,我现在尝试添加对强制转换的支持: cast : '(' type ')' atom -> ^(CAST type atom); 现在,我需要让它成为价值树的一部分。由于强制转换本身是原子的,可以作为层次结构的基础,并且可以用于任何二进制操作(因子、求和、比较),因此我认为它必须符合原子(以前是根)规则 幸运的是,这次一切似乎都足够了。但是,我得到了从type到type的无限递归: type :
root
规则现在已重命名为atom
)
在我的ANTLR语法中,我现在尝试添加对强制转换的支持:
cast : '(' type ')' atom -> ^(CAST type atom);
现在,我需要让它成为价值树的一部分。由于强制转换本身是原子的,可以作为层次结构的基础,并且可以用于任何二进制操作(因子、求和、比较),因此我认为它必须符合原子
(以前是根
)规则
幸运的是,这次一切似乎都足够了。但是,我得到了从type
到type
的无限递归:
type : name=IDENTIFIER (LESSER (generics+=type (SEPARATOR generics+=type)*) GREATER)? -> ^(TYPE $name ^(GENERICS $generics*));
[ruleatom]备选方案1[cast]:在匹配诸如PAREN_OPEN IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER{LESSER,SEPARATOR}之类的输入后,由于从类型到类型的递归溢出,决策无法预测接下来会发生什么
这个案例反映了一些东西,比如
(x),我甚至不想说ANTLR的错误消息(全部)是无法穿透的,但是是的,这个错误是
在这种情况下,ANTLR在区分关系表达式IDENTIFIER
和IDENTIFIER
之间存在问题,后者是类型的一部分
您可以通过更改泛型类型的开头,使其与关系LT表达式的开头不同来验证这一点:
type
: IDENTIFIER ('@' (type (',' type)*) '>')?
;
或者将LT符号保留在泛型类型中,但从atom
规则中删除标识符
:
type
: IDENTIFIER ('<' (type (',' type)*) '>')?
;
atom
: cast
//| IDENTIFIER
| SELF
| literal
| constructor
| call
| indexer
| '('! value ')'!
;
这迫使解析器首先向前看,并确保确实存在要匹配的cast
备选方案,如果没有,则在atom
规则中使用后面的备选方案
但更好的选择是不允许语法匹配关系表达式,如:
a < b < c
做:
然后,在atom
规则中,您不需要在type
前面使用谓词,而且运算符的优先级是正确的。1.4.3这里:感谢您的深入解释和建议。我没有考虑到关系运算符的优先级,像a
或a==b!=c
是允许的。你解决这些问题的理由是什么?不客气@LazloBonin。不确定我是否理解:你是说我回答关于ANTLR的问题的理由是什么,等等?
atom
: (cast)=> cast
| IDENTIFIER
| SELF
| literal
| constructor
| call
| indexer
| '('! value ')'!
;
a < b < c
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)*;
...