2011-06-15 31 views
3

我在这里有一个非常基本的ANTLR数学表达式语法,并且感兴趣的是在括号内处理隐含的*运算符,例如, (2-3)(4+5)(6*7)实际上应该是(2-3)*(4+5)*(6*7)什么是添加新标记(重写)以创建不在输入蒸汽上的AST节点的正确方法

鉴于输入(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;}; 

此语法似乎输出ANTLRworks正确的AST树:

AST Output

我才刚刚开始得到与解析和ANTLR交手,没有太多的经验,反馈真的很感激!

在此先感谢!卡尔

回答

3

首先,你做了伟大的工作给你以前从未使用过ANTLR的事实。

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

options { 
    output=AST; 
} 

而且,你不必为每个运营商分别指定根节点。所以,你不必做的事:

(ADD^ | SUB^) 

,但以下几点:

(ADD | SUB)^ 

就足够了。只有两个运营商,有没有太大的区别,但实现关系运算符(>=<=><)时,后者就简单得多了。

现在,你AST:你可能会想创建一个二叉树:这样一来,所有的内部节点是运营商,和叶子将是操作数,这使得实际的评估你的表现的更加容易。为了得到一个二叉树,你就必须稍微改变你的​​规则:

atom 
    : INTEGER 
    | (
     OPARN expression CPARN -> expression 
    ) 
    (
     OPARN e=expression CPARN -> ^(MUL $atom $e) 
    )* 
    ; 

产生以下AST给出的输入"(2-3)(4+5)(6*7)"

enter image description here

(由产生的图像: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); 
    } 
} 
+0

哇,感谢您的帮助巴特,这是超级!我必须先研究一下,让它消化! – 2011-06-15 18:08:45

+0

@EraserHead IRL,是的,我可以想象得到。重写规则' - > ^(MUL $ atom $ e)'可能会导致一些头痛。认识到'$ atom'指的是匹配的整个规则,因此包含了第一个'OPARN表达式CPARN'。 – 2011-06-15 18:44:52

+0

现在明白!我认为ANTLRworks和ANTLR IDE让我感动,因为我注意到有些语法不会在那些IDE中运行,但在Java中工作正常,猜测他们自己并不完全支持ANTLR的语法,或者有一点儿车。 – 2011-06-17 08:45:13

相关问题