Expression rewriting

The com.singularsys.extensions.rewrite package allows symbolic expression rewriting rules to be created and applied.

The package defines an interface RewriteRuleI which any rule should implement, and a visitor RewriteVisitor which recursively applies the rule.

A rule should define two methods

/** Returns true if node needs to be rewritten, according to this rule. **/
public boolean test(ASTFunNode node,Node children[]) throws ParseException;

/** Rewrites the node **/
public Node apply(ASTFunNode node,Node children[]) throws ParseException;

The first tests if rewriting needs to be performed on a node and if so the second returns a new node to replace the current node.

Examples of rules include ExpandBrackets which performs the rewriting (a+b) * (c+d) -> a*c+a*d+b*c+b*d, ExpandPower which performs the rewriting (a+b)^2 -> a^2+ 2*a*b+b^2, CollectPowers which collects like powers. Some more complex rules include RewriteLog which applies the rule log(a*b) -> log(a) + log(b) which can be found in com.singularsys.exttests.RewriteTest.

The RewriteVistor takes a set of rules added using the add() method. To set up Jep must have the DeepCopyVisitor, TreeUtils and ExpressionCleaner component added. After all the rules are added jep.reinitializeComponents() should be called.

Jep jep = new Jep();
jep.setComponent(new DeepCopyVisitor());
jep.setComponent(new TreeUtils());
jep.setComponent(new ExpressionCleaner());
RewriteVisitor ev = new RewriteVisitor();
jep.setComponent(ev);
RewriteRuleI expand = new ExpandBrackets();
ev.add(expand);                 // Add the rule
jep.reinitializeComponents();   // reinitialize Jep
    
Node node = jep.parse("(a+b)*(c+d)");
Node expanded = ev.rewrite(node,false); // perform the rewriting
jep.println(expanded);

Examples