添加新令牌(重写)以创建不在输入流上的AST节点的正确方法是什么

| 我在这里有一个适用于ANTLR的非常基本的数学表达式语法,并且感兴趣的是处理括号之间的隐式
*
运算符,例如
(2-3)(4+5)(6*7)
实际上应该是
(2-3)*(4+5)*(6*7)
。 给定输入
(2-3)(4+5)(6*7)
,我试图在解析时将丢失的add0 missing运算符添加到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;};
该语法似乎在ANTLRworks中输出正确的AST树: 我只是刚开始接触解析和ANTLR,没有太多经验,因此非常感谢您提供反馈! 提前致谢!卡尔     
已邀请:
        首先,鉴于您以前从未使用过ANTLR,因此您做得很好。 您可以省略默认值
language=Java
ASTLabelType=CommonTree
。因此,您可以执行以下操作:
options {
  output=AST;
}
同样,您不必为每个运算符分别指定根节点。因此您不必做:
(ADD^ | SUB^)
但以下内容:
(ADD | SUB)^
就足够了。仅使用两个运算符就没有太大区别,但是在实现关系运算符(
>=
<=
>
<
)时,后者要容易一些。 现在,对您来说AST:您可能要创建一个二叉树:这样,所有内部节点都是运算符,而叶子将是操作数,这使表达式的实际求值变得容易得多。要获得二叉树,您必须稍微更改
atom
规则:
atom
   : INTEGER
   | (
       OPARN  expression CPARN -> expression
     )
     (
       OPARN  e=expression CPARN -> ^(MUL $atom $e)
     )*  
   ;
给定输入
\"(2-3)(4+5)(6*7)\"
,它将产生以下AST: (图像产生:graphviz-dev.appspot.com) DOT文件是使用以下测试类生成的:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;

public class Main {
  public static void main(String[] args) throws Exception {
    GLexer lexer = new GLexer(new ANTLRStringStream(\"(2-3)(4+5)(6*7)\"));
    GParser parser = new GParser(new CommonTokenStream(lexer));
    CommonTree tree = (CommonTree)parser.start().getTree();
    DOTTreeGenerator gen = new DOTTreeGenerator();
    StringTemplate st = gen.toDOT(tree);
    System.out.println(st);
  }
}
    

要回复问题请先登录注册