这是此问题的“跟进”: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(*)。但是,我从type
到type
获得无限递归:
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的理解,你能解释为什么它现在触发吗?
答案 0 :(得分:2)
我不会说ANTLR的错误消息(全部)是不可穿透的,但是,这个错误是......
在这种情况下,ANTLR在关系表达式IDENTIFIER < atom
和IDENTIFIER < ...
之间存在问题,该关系表达式是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
前面的谓词和,您的运算符优先顺序正确。