我有以下Antlr语法规则:
expression1
: e=expression2 (BINOR^ e2=expression2)*
;
但是,如果我有“3 | 1 | 2 | 6
”,则会生成一棵平面树,其中{B}成员的所有子节点都为3, 1, 2, 6
。我真正想要的是能够在
expression2
or
^(BINOR expression2 expression2)
如何更改重写以使这些是2种模式?
编辑:
如果我使用自定义重写,我正在考虑
expression1
: e=expression2 (BINOR e2=expression2)*
-> {$BINOR != null}? ^(BINOR $e $e2*)
-> $e
但是当我使用'1 | 2 | 3'执行此操作时,生成的树只有一个BINOR节点,其中有两个子节点,分别为1和3,因此缺少2个。
非常感谢
答案 0 :(得分:1)
你很接近,这会奏效:
expression1
@init{boolean or = false;}
: e=expression2 (BINOR {or=true;} expression2)* -> {or}? ^(BINOR expression2+)
-> $e
;
但这是首选,因为它不使用任何自定义代码:
grammar T;
options {
output=AST;
}
expression1
: (e=expression2 -> $e) ((BINOR expression2)+ -> ^(BINOR expression2+))?
;
expression2
: NUMBER
;
NUMBER
: '0'..'9'+
;
BINOR
: '|'
;
从上面的语法生成的解析器将输入"3|1|2|6"
解析为AST:
和输入"3"
进入AST:
但你原来的尝试:
expression1
: e=expression2 (BINOR^ e2=expression2)*
;
不生成一棵平面树(假设您的选项中有output=AST;
)。它为"3|1|2|6"
生成以下AST:
如果你“看到”一棵平面树,我想你正在使用ANTLRWorks中的解释器,它不会显示AST,而是显示解析的解析树。解释器也很麻烦(不处理谓词而不评估自定义代码),所以最好不要使用它。使用ANTLRWorks调试器,它就像一个魅力(我的答案中的图像来自调试器)!