首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >添加新令牌(重写)以创建不在输入流上的AST节点的正确方法是什么

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

Stack Overflow用户
提问于 2011-06-15 23:53:32
回答 1查看 982关注 0票数 3

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

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

代码语言:javascript
运行
复制
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,没有太多的经验,所以我很欣赏!

提前感谢!卡尔

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-06-16 01:41:06

首先,考虑到您以前从未使用过ANTLR,您做得很好。

您可以省略默认值language=JavaASTLabelType=CommonTree。所以你可以这样做:

代码语言:javascript
运行
复制
options {
  output=AST;
}

而且,您不必为每个运算符单独指定根节点。所以你不需要这样做:

代码语言:javascript
运行
复制
(ADD^ | SUB^)

但以下内容:

代码语言:javascript
运行
复制
(ADD | SUB)^

就足够了。只有两个运算符,没有太大区别,但在实现关系运算符(>=<=><)时,后者更容易一些。

现在,对于AST:您可能想要创建一棵二叉树:这样,所有内部节点都是运算符,而leafs将是操作数,这使得表达式的实际计算变得更容易。要获得二叉树,您必须稍微更改atom规则:

代码语言:javascript
运行
复制
atom
   : INTEGER
   | (
       OPARN  expression CPARN -> expression
     )
     (
       OPARN  e=expression CPARN -> ^(MUL $atom $e)
     )*  
   ;

在给定输入"(2-3)(4+5)(6*7)"的情况下,它会生成以下AST

(图片出自:)

DOT文件是使用以下测试类生成的:

代码语言:javascript
运行
复制
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);
  }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6360621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档