Antlr 添加新标记(重写)以创建不在输入steam上的AST节点的正确方法是什么

Antlr 添加新标记(重写)以创建不在输入steam上的AST节点的正确方法是什么,antlr,antlr3,Antlr,Antlr3,我这里有一个关于ANTLR的非常基本的数学表达式语法,感兴趣的是处理括号之间隐含的*运算符,例如(2-3)(4+5)(6*7)实际上应该是(2-3)*(4+5)*(6*7) 给定输入(2-3)(4+5)(6*7)我试图在解析时将缺少的*操作符添加到AST树中,在下面的语法中,我想我已经成功地实现了这一点,但我想这是否是正确的、最优雅的方法 grammar G; options { language = Java; output=AST; ASTLabelType=Common

我这里有一个关于ANTLR的非常基本的数学表达式语法,感兴趣的是处理括号之间隐含的
*
运算符,例如
(2-3)(4+5)(6*7)
实际上应该是
(2-3)*(4+5)*(6*7)

给定输入
(2-3)(4+5)(6*7)
我试图在解析时将缺少的
*
操作符添加到AST树中,在下面的语法中,我想我已经成功地实现了这一点,但我想这是否是正确的、最优雅的方法

grammar G; 

options {
    language = Java;
    output=AST;
ASTLabelType=CommonTree;
}

tokens {
  ADD = '+' ;
  SUB = '-' ;
  MUL = '*' ;
  DIV = '/' ;
  OPARN = '(' ;
  CPARN = ')' ;
}

start
    : expression EOF!
    ;

expression
    : mult (( ADD^ | SUB^ ) mult)*
    ;

mult
   : atom (( MUL^ | DIV^) atom)*    
   ;

atom
   : INTEGER
   | (
       OPARN  expression CPARN -> expression
     )

     (
       OPARN  expression CPARN -> ^(MUL expression)+
     )*  
   ;


INTEGER : ('0'..'9')+ ;
WS  : (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel = HIDDEN;};
此语法在AntlWorks中输出正确的AST树:

我只是刚刚开始掌握解析和ANTLR,没有太多经验,所以非常感谢您的反馈


提前谢谢!卡尔

首先,考虑到您以前从未使用过ANTLR,您做得非常出色

您可以省略默认值
language=Java
ASTLabelType=CommonTree
。所以你可以做:

options {
  output=AST;
}
此外,不必分别为每个操作符指定根节点。所以你不必做:

(ADD^ | SUB^)
但以下几点:

(ADD | SUB)^

就够了。由于只有两个操作符,没有太大区别,但是在实现关系操作符(
=
哇,谢谢你的帮助,巴特,太棒了!我必须先研究一下,让它消化一下!@橡皮擦头IRL,是的,我可以想象。重写规则
->^(MUL$atom$e)
可能会引起一些头痛。要知道,
$atom
引用的是匹配的整个规则,所以第一个
OPARN表达式CPARN
就是因为它才被包含在内的。现在明白了!我想AntlWorks和ANTLR IDE让我大吃一惊,因为我注意到有些语法不会在那些IDE中运行,但在Java中运行得很好,我猜是这样的他们自己并不完全支持ANTLR的语法,或者有一点错误。@EraserHead IRL,是的,我只使用ANTLRWorks编辑语法,而不是测试解析器,因为解释器有很多错误。最好使用单独的类IMO来完成。
atom
   : INTEGER
   | (
       OPARN  expression CPARN -> expression
     )
     (
       OPARN  e=expression CPARN -> ^(MUL $atom $e)
     )*  
   ;