1
我試圖做乘法運算符以下改寫爲重複添加:ANTLR重寫樹節點作爲可變深度樹
(* a t=INT) -> (+ a (+ a (+ a (+ ... + a) ...)) (t times)
有沒有辦法用在ANTLR爲此在單通樹重寫規則?
如果沒有,最好的方法是什麼?
我必須多次重寫,每次出現'*',並且對應的t被解析。因此,在t上沒有固定的界限。
我試圖做乘法運算符以下改寫爲重複添加:ANTLR重寫樹節點作爲可變深度樹
(* a t=INT) -> (+ a (+ a (+ a (+ ... + a) ...)) (t times)
有沒有辦法用在ANTLR爲此在單通樹重寫規則?
如果沒有,最好的方法是什麼?
我必須多次重寫,每次出現'*',並且對應的t被解析。因此,在t上沒有固定的界限。
我設法解決了多遍的問題。我在分析表達式時計算最大傳遞次數,並多次應用樹重寫規則。我甚至不需要回歸真實。見下面的代碼。
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
;