2013-05-08 63 views
0

我需要一些关于尝试解决使用树语法时遇到的问题的指导。基本上,我希望能够做到的是替换/复制可能在树中发现的声明。最好通过一个例子来解释。使用ANTLR树语法复制树的节点

下面是一个示例输入:

int a = 10; 
new function A; 

function A { 
    int x; 
    int y; 
    new function B; 
} 

function B { 
    float b = 20; 
} 

求购输出(后):

int a = 10; 
int x; 
int y; 
float b = 20; 

它是一个简单的搜索和功能块内的语句的替代。我的问题是ANTLR提供了一种通过树语法来实现的方法吗?

下面是应该解析上述输入语法:

Test.g

grammar Test; 
options { 
    language = Java; 
    output = AST; 
} 
tokens { 
    VARDECL; 
    FUNDEF; 
    FUNCALL; 
    BLOCK; 
    ASSIGN; 

    Assign = '='; 
    EqT = '=='; 
    NEq = '!='; 
    LT  = '<'; 
    LTEq = '<='; 
    GT  = '>'; 
    GTEq = '>='; 
    NOT = '!'; 
    PLUS = '+'; 
    MINUS = '-'; 
    MULT = '*'; 
    DIV = '/'; 
} 

parse: statements+ 
    ; 

statements : varDeclare 
      | funcDefinition 
      | funcCall 
      ; 

funcDefinition : 'function' id '{' funcBlock* '}' -> ^(FUNDEF id ^(BLOCK funcBlock*)) 
       ; 

funcBlock : varDeclare 
      | funcCall 
      ; 

funcCall : 'new' 'function' id ';' -> ^(FUNCALL id) 
     ; 

varDeclare : type id equalExp? ';' -> ^(VARDECL type id equalExp?) 
      ; 

equalExp : (Assign^ (expression | '...')) 
     ; 

expression : binaryExpression 
      ; 

binaryExpression : addingExpression ((EqT|NEq|LTEq|GTEq|LT|GT)^ addingExpression)* 
       ; 

addingExpression : multiplyingExpression ((PLUS|MINUS)^ multiplyingExpression)* 
       ; 

multiplyingExpression : unaryExpression 
         ((MULT|DIV)^ unaryExpression)* 
         ; 

unaryExpression: ((NOT|MINUS))^ primitiveElement 
       | primitiveElement 
       ; 

primitiveElement : literalExpression 
       | id 
       | '(' expression ')' -> expression 
       ; 

literalExpression : INT 
        ;    

id : IDENTIFIER 
    ; 

type : 'int'  
    | 'float' 
    ; 

// L E X I C A L R U L E S  

INT : DIGITS ; 

IDENTIFIER : LETTER (LETTER | DIGIT)*; 

WS : (' ' 
     | '\t' 
     | '\r' 
     | '\n' 
     ) {$channel=HIDDEN;} 
    ; 

fragment LETTER : ('a'..'z' | 'A'..'Z' | '_') ; 
fragment DIGITS: DIGIT+; 
fragment DIGIT : '0'..'9'; 

Test.java

import java.io.FileWriter; 
import java.io.IOException; 
import java.io.PrintWriter; 

import org.antlr.runtime.ANTLRStringStream; 
import org.antlr.runtime.CommonTokenStream; 
import org.antlr.runtime.RuleReturnScope; 
import org.antlr.runtime.tree.CommonTree; 
import org.antlr.runtime.tree.DOTTreeGenerator; 
import org.antlr.stringtemplate.StringTemplate; 

public class Test { 
    public static void main(String[] args) throws Exception { 
     String src = "int a = 10;\r\n" + 
       "new function A;\r\n" + 
       "\r\n" + 
       "function A {\r\n" + 
       " int x;\r\n" + 
       " int y;\r\n" + 
       " new function B;\r\n" + 
       "}\r\n" + 
       "\r\n" + 
       "function B{\r\n" + 
       " float b = 20;\r\n" + 
       "}"; 
     TestLexer lexer = new TestLexer(new ANTLRStringStream(src)); 
     CommonTokenStream tokenStream = new CommonTokenStream(lexer); 
     TestParser parser = new TestParser(tokenStream); 
     RuleReturnScope r = parser.parse(); 
     System.out.println("Tree:" + ((CommonTree) r.getTree()).toStringTree() + "\n"); 


     CommonTree t = (CommonTree)r.getTree(); 
     generateGraph(t, "Tree.dot"); 
    } 

    private static void generateGraph(CommonTree t, String file) throws IOException { 
     DOTTreeGenerator gen = new DOTTreeGenerator(); 
     StringTemplate st = gen.toDOT(t); 
     String output = file; 
     PrintWriter out = new PrintWriter(new FileWriter(output)); 
     out.println(st); 
     out.close(); 
    } 
} 

Tree.dot AST graph

如何使用树语法在每个FUNCALL中进行搜索并将其替换为BLOCK的内容?

在此先感谢!

回答

1

在您的语法中,您将创建一个以ID为关键字的FUNDEF BLOCK的表blockMap

然后在你的树语法这样的东西,虽然它可能需要一些调整。你会做出funcCall规则:

funcCall : ^(FUNCALL id) -> {input.getTreeAdaptor().dupTree(blockMap.get(id)} 
    ; 

这是什么使地图中的块的副本: input.getTreeAdaptor()dupTree(...)

你需要让一个副本,因为节点跟踪他们的父母,所以你只能在树中的一个地方使用它们。

+0

谢谢,你知道ANTLR是否有关于这方面的更多文档? – 2013-05-09 01:46:55

+0

p。最终的ANTLR参考文献http://pragprog.com/book/tpantlr/the-definitive-antlr-reference有一个类似于上面的例子。事实上,我看到我已经忘记了我的树木建筑行动的大括号,并且刚刚纠正了我的答案。 – monty0 2013-05-09 04:41:52

+0

不幸的是http://www.antlr.org/wiki/display/ANTLR3/Tree+construction没有这方面的例子。这似乎只在书中提到。如果你会做严肃的ANTLR工作,这本书是非常值得的。我强烈推荐这本书。 dupTree()我通过搜索源代码发现,只是因为我知道它应该在那里。 – monty0 2013-05-09 04:50:39