...
Code Block |
---|
public Object downup(Object t, boolean showTransformations) { this.showTransformations = showTransformations; TreeVisitor v = new TreeVisitor(new CommonTreeAdaptor()); TreeVisitorAction actions = new TreeVisitorAction() { public Object pre(Object t) { return applyOnce(t, topdown_fptr); } public Object post(Object t) { return applyRepeatedly(t, bottomup_ftpr); } }; t = v.visit(t, actions); return t; } |
If you don't like the strategy that I've implemented by default, you can trivially make your own by cutting and pasting from downup().
Tree patterns
First, remember that we are not specify entire tree grammar. We are primarily looking for subtrees of interest. Tree grammars specify not only the patterns but how to visit the tree. With patterns, we use the dot (wildcard) a lot. The following pattern matches an add subtree anywhere in the tree:
...
Code Block |
---|
exitMethod : METHOD_DECL { System.out.println("args: "+currentScope); currentScope = currentScope.getEnclosingScope(); // pop arg scope } ; |
Tree rewriting
The rule speciļ¬es a Think of the tree rewriting patterns as tree pattern to tree pattern mapping.mappings. For example, here is how we would do some Boolean simplifications:
Code Block |
---|
e : ^('!' 'true') -> 'false' // !true -> false | ^('!' 'false') -> 'true' // !false -> true | ^('&&' 'true' x=.) -> $x // true && x -> x | ^('&&' x=. 'true') -> $x // x && true -> x ; |
With predicates, we can check for multiply by zeroes:
Code Block |
---|
zeroX : ^('*' a=INT b=INT {$a.int==0}?) -> $a ; // 0*x -> 0 xZero : ^('*' a=INT b=INT {$b.int==0}?) -> $b ; // x*0 -> 0 |
...