Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

And now, let's distribute scalar-vector multiplies. 4*[1,2] -> [4*1,4*2].

Code Block
tree grammar Simplify;
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
}

topdown
    :   ^('*' INT ^(VEC (e+=.)+)) -> ^(VEC ^('*' INT $e)+)
    ;

bottomup
    :  ^('*' a=. b=INT {$b.int==0}?) -> $b // x*0 -> 0
    ;

...

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 to 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.