2013-08-05 131 views
1

我試圖做乘法運算符以下改寫爲重複添加:ANTLR重寫樹節點作爲可變深度樹

(* a t=INT) -> (+ a (+ a (+ a (+ ... + a) ...)) (t times) 

有沒有辦法用在ANTLR爲此在單通樹重寫規則?

如果沒有,最好的方法是什麼?

我必須多次重寫,每次出現'*',並且對應的t被解析。因此,在t上沒有固定的界限。

回答

1

我設法解決了多遍的問題。我在分析表達式時計算最大傳遞次數,並多次應用樹重寫規則。我甚至不需要回歸真實。見下面的代碼。

Expr.g - >詞法,語法分析器語法

grammar Expr; 
options { 
    output=AST; 
    ASTLabelType=CommonTree; 
} 

tokens { 
    MULT='*'; 
    ADD='+'; 
} 

@header{ 
import java.lang.Math; 
} 

@members { 
public int limit=0; 
} 

prog : expr {limit=$expr.value;} ; 

expr returns [int value] 
    : a=multExpr {$value=$a.value;} (ADD^ b=multExpr {$value=Math.max($value, $b.value);})* ; 

multExpr returns [int value] 
    : primary {$value=$primary.value;} (MULT^ c=INT {$value=Math.max($value, $c.int);})? ; 

primary returns[int value] 
    : ID    {$value = 0;} 
    | '('! expr ')'! {$value = $expr.value;} 
    ; 

ID : 'a'..'z'+ ; 
INT : '0'..'9'+ ; 
WS : (' '|'\r'|'\n')+ {skip();} ; 

Eval.g - >樹重寫文法與主程序

tree grammar Eval; 

options { 
    tokenVocab=Expr; 
    ASTLabelType=CommonTree; 
    output=AST; 
} 

@members { 

    public static void main(String[] args) throws Exception { 
     ANTLRInputStream input = new ANTLRInputStream(System.in); 
     ExprLexer lexer = new ExprLexer(input); 
     CommonTokenStream tokens = new CommonTokenStream(lexer); 
     ExprParser parser = new ExprParser(tokens); 

     CommonTree t = null; 
     try { 
      t = (CommonTree) parser.prog().getTree(); 
     } catch(RecognitionException re){ 
      re.printStackTrace(); 
     } 

     System.out.println("Tree: " + t.toStringTree()); 
     System.out.println(); 

     int loops = parser.limit; 
     System.out.println("Number of loops:" + loops); 
     System.out.println(); 

     for(int i=0; i<loops; i++) { 
      System.out.println("Loop:" + (i+1)); 
      CommonTreeNodeStream nodes = new CommonTreeNodeStream(t); 
      Eval s = new Eval(nodes); 
      t = (CommonTree)s.prog().getTree(); 
      System.out.println("Simplified tree: "+t.toStringTree()); 
      System.out.println(); 
     } 
    } 
} 

prog : expr ; 

expr 
    : ^(ADD a=expr b=expr) 
    | ^(MULT a=expr t=INT) ({$t.int>1}?=> -> ^(ADD["+"] $a ^(MULT["*"] $a INT[String.valueOf($t.int - 1)])) 
          | {$t.int==1}?=> -> $a) 
    | INT 
    | ID 
    ;