...
Code Block |
---|
VecMathLexer lex = new VecMathLexer(input); CommonTokenStream tokens = new CommonTokenStream(lex); VecMathParser g = new VecMathParser(tokens); RuleReturnScope r = g.prog(); // launch parser by calling start rule CommonTree t = (CommonTree)r.getTree(); // get tree result System.out.println("Original tree: "+t.toStringTree()); CommonTreeNodeStream nodes = new CommonTreeNodeStream(t); Simplify s = new Simplify(nodes); t = (CommonTree)s.downup(t); System.out.println("Simplified tree: "+t.toStringTree()); |
Output:
Code Block |
---|
$ cat t1
x = 4 * [0, 5*0, 3]
$ java Test < t1
Original tree: (= x (* 4 (VEC 0 (* 5 0) 3)))
(* 4 (VEC 0 (* 5 0) 3)) -> (VEC (* 4 0) (* 4 (* 5 0)) (* 4 3))
(* 4 0) -> 0
(* 5 0) -> 0
(* 4 0) -> 0
Simplified tree: (= x (VEC 0 0 (* 4 3)))
$
|
Now for stuff that needs repeatedly get applied to subtrees.
Code Block |
---|
tree grammar Reduce;
options {
tokenVocab=VecMath; // use tokens from VecMath.g
ASTLabelType=CommonTree; // we're using CommonTree nodes
output=AST; // build ASTs from input AST
filter=true; // tree pattern matching, rewrited mode
}
/** Rewrite: x+x to be 2*x, 2*x to be x<<1, x<<n<<m to be x<<(n+m) */
bottomup
: ^('+' i=INT j=INT {$i.int==$j.int}?) -> ^(MULT["*"] INT["2"] $j)
| ^('*' x=INT {$x.int==2}? y=.) -> ^(SHIFT["<<"] $y INT["1"])
| ^(SHIFT ^(SHIFT e=. n=INT) m=INT)
-> ^(SHIFT["<<"] $e INT[String.valueOf($n.int+$m.int)])
;
|
Test code:
Code Block |
---|
CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
Reduce red = new Reduce(nodes);
t = (CommonTree)red.downup(t);
|
Running:
Code Block |
---|
$ cat t2
x = 2*(3+3)
$ java Test2 < t2
Original tree: (= x (* 2 (+ 3 3)))
(+ 3 3) -> (* 2 3)
(* 2 3) -> (<< 3 1)
(* 2 (<< 3 1)) -> (<< (<< 3 1) 1)
(<< (<< 3 1) 1) -> (<< 3 2)
Simplified tree: (= x (<< 3 2))
$
|
I'm replacing multiply with shift left by 1 and then combining shifts.