1

这是这个问题的“后续”:如何解析带括号的层次结构根?(知道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但是,我从to得到无限递归type

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

[rule atom ] Alternative 1 [ cast ]:在匹配输入后,例如 PAREN_OPEN IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER {LESSER, SEPARATOR} 决策无法预测接下来会发生什么,因为从类型到类型的递归溢出

这种情况反映了诸如(x<x<x<x<x[</,].

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

我该如何解决?请根据我对 ANTLR 的理解,您能解释一下为什么它现在会触发吗?

4

1 回答 1

2

我不会说 ANTLR 的错误消息是(全部)难以理解的,但是,是的,这个错误是......

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

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

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

或将 LT 符号保留在泛型类型中,但从规则中IDENTIFIER删除atom

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

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

当然,我知道这两种选择都不现实。

cast为了使 ANTLR 对语法感到满意,您可以在规则中的替代项前面添加一个语法谓词atom(并保留type您当前拥有的规则):

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

这迫使解析器首先向前看,并确保确实存在匹配的cast替代方案,当没有匹配时,它会落入atom规则中的后续替代方案。

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

a < b < c

这没有多大意义:关系表达式a < b通常计算为布尔值,不能与 比较c,对吧?此外,您现在将所有逻辑运算符、关系运算符和相等运算符分组到一个规则中,使它们具有相同的优先级:而在大多数情况下,OR具有最低的优先级,然后是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的谓词,并且你有正确顺序的运算符优先级。atom

于 2012-05-03T06:50:07.043 回答