/** A parse tree visitor that produces an SMT formula from a Ptolemy AST.
*
*/
package ptolemy.apps.interfaces;
import ptolemy.data.expr.ASTPtLeafNode;
import ptolemy.data.expr.ASTPtLogicalNode;
import ptolemy.data.expr.ASTPtProductNode;
import ptolemy.data.expr.ASTPtRelationalNode;
import ptolemy.data.expr.ASTPtRootNode;
import ptolemy.data.expr.ASTPtSumNode;
import ptolemy.data.expr.ASTPtUnaryNode;
import ptolemy.data.expr.AbstractParseTreeVisitor;
import ptolemy.kernel.util.IllegalActionException;
/** A parse tree visitor that produces an SMT formula from a Ptolemy AST.
*
* This converts Ptolemy expressions into LISP-style expressions,
* represented as strings. These can be later used in LISP-like
* languages, such as the Yices SMT solver's input language.
*
* Note: This class currently ignores the types in the Ptolemy
* expression. They may be needed in some applications.
*
* @author Ben Lickly
*
*/
public class SMTFormulaBuilder extends AbstractParseTreeVisitor {
///////////////////////////////////////////////////////////////////
//// public methods ////
/** Produce a LISP-like expression from a Ptolemy AST.
*
* @param root The root node of the Ptolemy expression.
* @return A string representation of the expression.
*/
public String parseTreeToSMTFormula(final ASTPtRootNode root) {
_smtFormula = new StringBuffer();
try {
root.visit(this);
} catch (final IllegalActionException ex) {
System.err.println(ex);
ex.printStackTrace(System.err);
}
return _smtFormula.toString();
}
@Override
public void visitLeafNode(ASTPtLeafNode node) throws IllegalActionException {
if (node.isIdentifier()) {
_smtFormula.append(node.getName());
/* FIXME: This is where we will find the types once we implement
* type checking on this AST */
//_smtDefines.put(node.getName(), node.getType().toString());
} else {
String constName = node.toString();
constName = constName.replaceAll(":null", "");
constName = constName.replaceAll(".*:", "");
_smtFormula.append(constName);
}
}
@Override
public void visitLogicalNode(ASTPtLogicalNode node)
throws IllegalActionException {
String op = node.getOperator().toString();
if (op.equals("&&")) {
op = "and";
} else if (op.equals("||")) {
op = "or";
}
_smtFormula.append("(" + op + " ");
_visitChildren(node);
_smtFormula.append(")");
}
@Override
public void visitProductNode(ASTPtProductNode node)
throws IllegalActionException {
String op = node.getLexicalTokenList().get(0).toString();
if (op.equals("%")) {
op = "mod";
}
_smtFormula.append("(" + op + " ");
_visitChildren(node);
_smtFormula.append(")");
}
@Override
public void visitRelationalNode(ASTPtRelationalNode node)
throws IllegalActionException {
String op = node.getOperator().toString();
if (op.equals("==")) {
op = "=";
} else if (op.equals("!=")) {
op = "/=";
}
_smtFormula.append("(" + op + " ");
_visitChildren(node);
_smtFormula.append(")");
}
@Override
public void visitSumNode(ASTPtSumNode node) throws IllegalActionException {
_smtFormula.append("(" + node.getLexicalTokenList().get(0) + " ");
_visitChildren(node);
_smtFormula.append(")");
}
@Override
public void visitUnaryNode(ASTPtUnaryNode node)
throws IllegalActionException {
String op = node.getOperator().toString();
if (op.equals("!")) {
op = "not";
}
_smtFormula.append("(" + op + " ");
_visitChildren(node);
_smtFormula.append(")");
}
///////////////////////////////////////////////////////////////////
//// protected methods ////
/** Recurse into the children of the given node.
*
* @param node The node to be explored.
* @throws IllegalActionException If there is a problem displaying
* the children.
*/
protected void _visitChildren(ASTPtRootNode node)
throws IllegalActionException {
if (node.jjtGetNumChildren() > 0) {
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
final ASTPtRootNode child = (ASTPtRootNode) node.jjtGetChild(i);
child.visit(this);
_smtFormula.append(" ");
}
}
}
///////////////////////////////////////////////////////////////////
//// private variables ////
/** The intermediate state of the LISP-expression.
*/
private StringBuffer _smtFormula;
}