PragmaParser.java
package edu.udel.cis.vsl.tass.ast.impl;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.Tree;
import edu.udel.cis.vsl.tass.ast.IF.ASTNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.AbstractSyntaxTreeIF;
import edu.udel.cis.vsl.tass.ast.IF.IdentifierNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.PragmaParserIF;
import edu.udel.cis.vsl.tass.ast.IF.SequenceNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.declaration.AbstractFunctionDeclarationNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.declaration.BoundVariableDeclarationNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.declaration.FormalVariableDeclarationNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.declaration.FunctionDeclarationNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.declaration.GlobalVariableDeclarationNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.declaration.VariableDeclarationNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.expression.AssignmentNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.expression.AssignmentNodeIF.AST_ASSIGNMENT_TYPE;
import edu.udel.cis.vsl.tass.ast.IF.expression.BindingExpressionNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.expression.ExpressionNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.expression.LHSExpressionNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.expression.OperatorNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.expression.PureExpressionNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.expression.VariableReferenceNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.statement.AssertStatementNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.statement.AssumeStatementNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.statement.LoopNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.statement.PragmaNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.TypeNodeIF;
import edu.udel.cis.vsl.tass.ast.impl.pragmaParser.PragmaStringLexer;
import edu.udel.cis.vsl.tass.ast.impl.pragmaParser.PragmaStringParser;
import edu.udel.cis.vsl.tass.ast.impl.pragmaParser.PragmaStringParser.pragma_return;
import edu.udel.cis.vsl.tass.model.IF.SyntaxException;
import edu.udel.cis.vsl.tass.number.real.RealNumberFactory;
/**
* This class traverses the AST and converts all valid TASS pragmas to the
* corresponding AST nodes.
*
* @author Timothy Zirkel (zirkel)
*
*/
public class PragmaParser implements PragmaParserIF {
private boolean verbose = false;
private AbstractSyntaxTreeIF ast;
private Map<String, VariableDeclarationNodeIF> inputVariables = new HashMap<String, VariableDeclarationNodeIF>();
public PragmaParser() {
}
public PragmaParser(boolean verbose) {
this.verbose = verbose;
}
/**
* Constructor that sets the AST, for testing purposes.
*/
public PragmaParser(AbstractSyntaxTreeIF ast) {
this.ast = ast;
}
@Override
public void transform(AbstractSyntaxTreeIF ast) throws SyntaxException {
this.ast = ast;
PragmaHelper helper = new PragmaHelper();
helper.transform(ast);
processAll(ast.rootNode().globalScopeNodes());
}
public void processAll(ASTNodeIF node) {
if (node == null) {
return;
}
for (int i = 0; i < node.numChildren(); i++) {
ASTNodeIF currentChild = node.child(i);
// If the child is a pragma, parse it and we're done.
if (currentChild instanceof PragmaNodeIF)
// Check for a syntax exception
try {
node.setChild(i, parsePragma((PragmaNodeIF) currentChild));
} catch (SyntaxException e) {
if (verbose) {
System.out.println("Pragma node " + currentChild.id()
+ ":\n \"" + currentChild.toString()
+ "\"\nis not a valid TASS pragma");
}
}
// If the child is not a pragma, it needs to be recursively
// processed.
else
processAll(currentChild);
}
}
@Override
public ASTNodeIF parsePragma(PragmaNodeIF pragmaNode)
throws SyntaxException {
// TODO: The .replaceAll() calls are to deal with bugs in the XML->AST
// build. Should eventually be removed.
String pragmaString = pragmaNode.string().stringValue()
.replaceAll("\n", "").replaceAll("null", "");
CommonTree rootNode = prepareTree(pragmaString);
ASTNodeIF newNode = pragmaNode;
int rootNodeType = rootNode.getType();
if (rootNodeType == PragmaStringLexer.SYSTEM) {
/* Process a guard if one exists. */
if (rootNode.getChild(1).getType() == PragmaStringLexer.GUARD) {
ExpressionNodeIF guard;
assert pragmaNode.nextNode() instanceof FunctionDeclarationNodeIF;
guard = processExpression(rootNode.getChild(2));
assert guard instanceof PureExpressionNodeIF;
((FunctionDeclarationNodeIF) pragmaNode.nextNode())
.setGuard((PureExpressionNodeIF) guard);
}
} else if (rootNodeType == PragmaStringLexer.ABSTRACT) {
newNode = processAbstractFunctionDeclaration(rootNode);
} else if (rootNodeType == PragmaStringLexer.STATEMENT) {
newNode = processStatement(rootNode);
if (newNode.annotation("invariant") != null) {
LoopNodeIF nextNode;
SequenceNodeIF<PureExpressionNodeIF> invariants;
if (!(newNode instanceof PureExpressionNodeIF)) {
throw new SyntaxException(pragmaNode,
"Invariant must be a pure expression.");
}
if (!(pragmaNode.nextNode() instanceof LoopNodeIF)) {
throw new SyntaxException(pragmaNode,
"Invariants must come directly before loop statements.");
}
nextNode = (LoopNodeIF) pragmaNode.nextNode();
if (nextNode.invariants() != null) {
invariants = nextNode.invariants();
} else {
invariants = ast.factory().sequenceNode(PureExpressionNodeIF.class);
}
invariants.addSequenceChild((PureExpressionNodeIF) newNode);
nextNode.setInvariants(invariants);
// Since we added the invariant to the loop node, we don't
// want it sitting as just an extra expression. Replace it with
// the original pragma node.
newNode = pragmaNode;
}
} else if (rootNodeType == PragmaStringLexer.PREFIX) {
newNode = processPrefix(rootNode, pragmaNode);
// A prefix will either be before a define or
// before a global variable declaration. In the
// former case, we need to add a new node for
// a new declaration. In the latter,
// the declaration is already there.
if (newNode.equals(pragmaNode.nextNode())) {
newNode = pragmaNode;
}
}
newNode.setSource(pragmaNode.getSource());
return newNode;
}
/**
* Process pragmas representing statements. The valid pragma statements are
* assert, assume, collective assert, joint assert, invariant, collective
* invariant, joint invariant.
*
* @throws SyntaxException
* if there are any syntax problems with the
* assert/assume/invariant predicate.
*/
private ASTNodeIF processStatement(CommonTree node) throws SyntaxException {
CommonTree child = (CommonTree) (node.getChild(0));
switch (child.getType()) {
case PragmaStringLexer.ASSERT_STMT:
return processAssert(child);
case PragmaStringLexer.ASSUME_STMT:
return processAssume(child);
case PragmaStringLexer.COLLECTIVE_ASSERT_STMT:
return processCollectiveAssert(child);
case PragmaStringLexer.COLLECTIVE_INVARIANT_STMT:
return processCollectiveInvariant(child);
case PragmaStringLexer.INVARIANT_STMT:
return processInvariant(child);
case PragmaStringLexer.JOINT_ASSERT_STMT:
return processJointAssert(child);
case PragmaStringLexer.JOINT_INVARIANT_STMT:
return processJointInvariant(child);
default:
throw new SyntaxException("Unkown or unimplemented statement at "
+ node.getChild(0).getLine() + ", "
+ node.getChild(0).getCharPositionInLine() + ":"
+ node.getText());
}
}
private ASTNodeIF processAssert(CommonTree node) throws SyntaxException {
AssertStatementNodeIF result = null;
ExpressionNodeIF predicate = processExpression(node.getChild(1));
String message = null;
result = ast.factory().assertStatementNode(predicate);
if (node.getChild(2).getType() != PragmaStringLexer.SEMI) {
message = node.getChild(2).getText()
.substring(1, node.getChild(2).getText().length() - 1);
result.setAnnotation("message", message);
}
return result;
}
private ASTNodeIF processAssume(CommonTree node) throws SyntaxException {
AssumeStatementNodeIF result = null;
ExpressionNodeIF predicate = processExpression(node.getChild(1));
result = ast.factory().assumeStatementNode(predicate);
return result;
}
private ASTNodeIF processCollectiveAssert(CommonTree node)
throws SyntaxException {
AssertStatementNodeIF result = null;
ExpressionNodeIF predicate = processExpression(node.getChild(1));
String identifier = node.getChild(0).getText();
result = ast.factory().assertStatementNode(predicate);
result.setAnnotation("collective", true);
result.setAnnotation("name", identifier);
return result;
}
private ASTNodeIF processCollectiveInvariant(CommonTree node)
throws SyntaxException {
ASTNodeIF result = processInvariant(node);
result.setAnnotation("collective", true);
return result;
}
private ASTNodeIF processJointAssert(CommonTree node)
throws SyntaxException {
AssertStatementNodeIF result = null;
ExpressionNodeIF predicate = processExpression(node.getChild(1));
String identifier = node.getChild(0).getText();
result = ast.factory().assertStatementNode(predicate);
result.setAnnotation("joint", true);
result.setAnnotation("name", identifier);
return result;
}
private ASTNodeIF processInvariant(CommonTree node) throws SyntaxException {
ExpressionNodeIF result = processExpression(node.getChild(1));
String identifier = node.getChild(0).getText();
if (!(result instanceof PureExpressionNodeIF)) {
throw new SyntaxException("An invariant must be a pure expression.");
}
result.setAnnotation("invariant", true);
result.setAnnotation("name", identifier);
return result;
}
private ASTNodeIF processJointInvariant(CommonTree node)
throws SyntaxException {
ASTNodeIF result = processInvariant(node);
result.setAnnotation("joint", true);
return result;
}
private ASTNodeIF processAbstractFunctionDeclaration(CommonTree node)
throws SyntaxException {
AbstractFunctionDeclarationNodeIF result = null;
TypeNodeIF type = processType(node.getChild(2).getText());
IdentifierNodeIF identifier = ast.factory().identifierNode(
node.getChild(3).getText());
CommonTree contNode = (CommonTree) node.getChild(0);
SequenceNodeIF<FormalVariableDeclarationNodeIF> formals;
int continuity = 0;
int bounded = 0;
if (contNode.getType() != PragmaStringLexer.IGNORE) {
continuity = Integer.parseInt(contNode.getText());
}
// TODO Add boundedness to grammar, handle it
if (node.getChildCount() == 6) {
formals = processFormals((CommonTree) node.getChild(4));
} else {
formals = ast.factory().sequenceNode(
FormalVariableDeclarationNodeIF.class);
}
result = ast.factory().abstractFunctionDeclarationNode(identifier,
type, formals, continuity, bounded);
return result;
}
private SequenceNodeIF<FormalVariableDeclarationNodeIF> processFormals(
CommonTree node) {
// TODO Auto-generated method stub
return null;
}
private ASTNodeIF processPrefix(CommonTree rootNode, PragmaNodeIF pragmaNode)
throws SyntaxException {
String prefix = rootNode.getChild(0).getText();
GlobalVariableDeclarationNodeIF variable;
/*
* Either this prefix is the line preceding a variable declaration, or
* it is the line preceding a define. In the define case, we should have
* preprocessed the file to include a type and identifier in this
* pragma. In these cases, we need to take that type and identifier and
* create a new GlobalVariableDeclarationNodeIF.
*/
if (rootNode.getChildCount() > 2) {
IdentifierNodeIF name;
TypeNodeIF type;
ExpressionNodeIF inputAssumption;
int numChildren = rootNode.getChildCount();
name = ast.factory().identifierNode(
rootNode.getChild(numChildren - 1).getText());
type = processType(rootNode.getChild(numChildren - 2).getText());
variable = ast.factory().globalVariableDeclarationNode(name, type);
inputVariables.put(variable.identifier().name(), variable);
if (numChildren == 4) {
inputAssumption = processExpression(rootNode.getChild(1));
inputAssumption.setSource(pragmaNode.getSource());
variable.setInputAssumption(inputAssumption);
variable.setSource(pragmaNode.getSource());
}
} else {
variable = (GlobalVariableDeclarationNodeIF) pragmaNode.nextNode();
}
if (prefix.equals("input")) {
variable.setIsInput(true);
} else if (prefix.equals("output")) {
variable.setIsOutput(true);
} else if (prefix.equals("shared")) {
variable.setIsShared(true);
}
return variable;
}
private ExpressionNodeIF processExpression(Tree node)
throws SyntaxException {
if (node.getChild(0).getType() == PragmaStringLexer.ASSIGN_EXPR) {
// expr: assign_expr
return processAssignment(node.getChild(0));
} else if (node.getChild(0).getType() == PragmaStringLexer.CONDITIONAL_EXPR) {
return processConditional(node.getChild(0));
} else {
// expr: quantifier_expr
return processQuantifier(node.getChild(0));
}
}
private ExpressionNodeIF processQuantifier(Tree node)
throws SyntaxException {
TypeNodeIF type = null;
IdentifierNodeIF identifier = null;
BoundVariableDeclarationNodeIF variable = null;
BindingExpressionNodeIF.Quantifier quantifier = null;
PureExpressionNodeIF constraint = null;
PureExpressionNodeIF boundExpression = null;
BindingExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
return processLogicalOr(node.getChild(0));
} else {
int expressionIndex = 3;
type = processType(node.getChild(1).getText());
identifier = ast.factory().identifierNode(
node.getChild(2).getText());
switch (node.getChild(0).getChild(0).getType()) {
case PragmaStringLexer.FORALL:
quantifier = BindingExpressionNodeIF.Quantifier.FORALL;
break;
case PragmaStringLexer.EXISTS:
quantifier = BindingExpressionNodeIF.Quantifier.EXISTS;
break;
// TODO implement other quantifier types in grammar
}
variable = ast.factory().boundVariableDeclarationNode(identifier,
type, null);
if (node.getChild(3).getType() == PragmaStringLexer.BAR) {
constraint = (PureExpressionNodeIF) processExpression(node
.getChild(4));
expressionIndex = 5;
} else {
constraint = ast.factory().integerLiteralNode(null,
ast.factory().booleanTypeNode(), 1);
}
boundExpression = (PureExpressionNodeIF) processExpression(node
.getChild(expressionIndex));
result = ast.factory().bindingExpressionNode(quantifier, variable,
constraint, boundExpression);
variable.setContainingExpression(result);
}
return result;
}
private ExpressionNodeIF processLogicalOr(Tree node) throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
return processLogicalAnd(node.getChild(0));
} else {
ExpressionNodeIF left = null;
ExpressionNodeIF right;
for (int i = 0; i < node.getChildCount() - 2; i += 2) {
if (i == 0) {
left = processLogicalAnd(node.getChild(i));
} else {
left = result;
}
right = processLogicalAnd(node.getChild(i + 2));
result = ast.factory().operatorNode(
OperatorNodeIF.AST_OPERATOR.LOGICAL_OR, left, right);
}
}
return result;
}
private ExpressionNodeIF processLogicalAnd(Tree node)
throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
if (node.getChild(0).getType() == PragmaStringLexer.ADDITIVE_EXPR) {
return processAdditive(node.getChild(0));
}
return processEquality(node.getChild(0));
} else {
ExpressionNodeIF left = null;
ExpressionNodeIF right;
for (int i = 0; i < node.getChildCount() - 2; i += 2) {
if (i == 0) {
// FIXME: Again, not sure why this changed from the old
// front-end. The pragma parser is better, but parts may
// still need to be rewritten.
if (node.getChild(0).getType() == PragmaStringLexer.EQUALITY_EXPR) {
left = processEquality(node.getChild(i));
} else {
left = processLogicalAnd(node.getChild(i));
}
} else {
left = result;
}
if (node.getChild(i + 2).getType() == PragmaStringLexer.EQUALITY_EXPR) {
right = processEquality(node.getChild(i + 2));
} else {
right = processLogicalAnd(node.getChild(i + 2));
}
result = ast.factory().operatorNode(
OperatorNodeIF.AST_OPERATOR.LOGICAL_AND, left, right);
}
}
return result;
}
private ExpressionNodeIF processEquality(Tree node) throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
return processRelational(node.getChild(0));
} else {
ExpressionNodeIF left = null;
ExpressionNodeIF right;
OperatorNodeIF.AST_OPERATOR operator;
for (int i = 0; i < node.getChildCount() - 2; i += 2) {
if (i == 0) {
left = processLogicalAnd(node.getChild(i));
} else {
left = result;
}
if (node.getChild(i + 1).getText().equalsIgnoreCase("==")) {
operator = OperatorNodeIF.AST_OPERATOR.EQUALS;
} else if (node.getChild(i + 1).getText()
.equalsIgnoreCase("!=")) {
operator = OperatorNodeIF.AST_OPERATOR.NOT_EQUALS;
} else {
throw new SyntaxException("Invalid operator type");
}
right = processLogicalAnd(node.getChild(i + 2));
result = ast.factory().operatorNode(operator, left, right);
}
}
return result;
}
private ExpressionNodeIF processRelational(Tree node)
throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
return processAdditive(node.getChild(0));
} else {
String operatorString;
OperatorNodeIF.AST_OPERATOR operator;
ExpressionNodeIF left, right;
for (int i = 0; i < node.getChildCount() - 2; i += 2) {
operatorString = node.getChild(i + 1).getText();
if (operatorString.equalsIgnoreCase("<")) {
operator = OperatorNodeIF.AST_OPERATOR.LESS_THAN;
} else if (operatorString.equalsIgnoreCase("<=")) {
operator = OperatorNodeIF.AST_OPERATOR.LEQ;
} else if (operatorString.equalsIgnoreCase(">")) {
operator = OperatorNodeIF.AST_OPERATOR.GREATER_THAN;
} else if (operatorString.equalsIgnoreCase(">=")) {
operator = OperatorNodeIF.AST_OPERATOR.GTE;
} else {
throw new SyntaxException("Invalid operator type: "
+ operatorString);
}
if (i == 0) {
left = processAdditive(node.getChild(i));
} else {
left = result;
}
right = processAdditive(node.getChild(i + 2));
result = ast.factory().operatorNode(operator, left, right);
}
}
return result;
}
private ExpressionNodeIF processAdditive(Tree node) throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
return processMultiplicative(node.getChild(0));
} else {
OperatorNodeIF.AST_OPERATOR operator;
ExpressionNodeIF left, right;
for (int i = 0; i < node.getChildCount() - 2; i += 2) {
if (node.getChild(i + 1).getText().equalsIgnoreCase("+")) {
operator = OperatorNodeIF.AST_OPERATOR.ADD;
} else if (node.getChild(i + 1).getText().equalsIgnoreCase("-")) {
operator = OperatorNodeIF.AST_OPERATOR.SUBTRACT;
} else {
throw new SyntaxException("Invalid operator type: "
+ node.getChild(i + 1).getText());
}
if (i == 0) {
left = processMultiplicative(node.getChild(i));
} else {
left = result;
}
right = processMultiplicative(node.getChild(i + 2));
result = ast.factory().operatorNode(operator, left, right);
}
}
return result;
}
private ExpressionNodeIF processMultiplicative(Tree node)
throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
// FIXME: Not sure why this has changed from the original front-end,
// but check if this is actually a primary expression. If it is,
// call processPrimary() directly on the whole node instead of the
// child. Maybe there's a better way to do this?
// i.e. have a processNode() method that takes a node, looks at its
// type, and calls the appropriate method rather than depending on
// number of children, etc.?
if (node.getType() == PragmaStringLexer.PRIMARY_EXPR) {
return processPrimary(node);
}
return processUnary(node.getChild(0));
} else {
String operatorString;
OperatorNodeIF.AST_OPERATOR operator;
ExpressionNodeIF left, right;
for (int i = 0; i < node.getChildCount() - 2; i += 2) {
operatorString = node.getChild(i + 1).getText();
if (operatorString.equalsIgnoreCase("*")) {
operator = OperatorNodeIF.AST_OPERATOR.MULTIPLY;
} else if (operatorString.equalsIgnoreCase("/")) {
operator = OperatorNodeIF.AST_OPERATOR.DIVIDE;
} else if (operatorString.equalsIgnoreCase("%")) {
operator = OperatorNodeIF.AST_OPERATOR.MODULO;
} else {
throw new SyntaxException("Invalid operator type: "
+ operatorString);
}
if (i == 0) {
left = processMultiplicative(node.getChild(i));
} else {
left = result;
}
right = processMultiplicative(node.getChild(i + 2));
result = ast.factory().operatorNode(operator, left, right);
}
}
return result;
}
private ExpressionNodeIF processConditional(Tree node)
throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
return processLogicalOr(node.getChild(0));
} else {
ExpressionNodeIF predicate = processLogicalOr(node.getChild(0));
ExpressionNodeIF trueExpr = processExpression(node.getChild(1));
ExpressionNodeIF falseExpr = processExpression(node.getChild(2));
result = ast.factory().operatorNode(
OperatorNodeIF.AST_OPERATOR.COND, predicate, trueExpr,
falseExpr);
}
return result;
}
private ExpressionNodeIF processAssignment(Tree node)
throws SyntaxException {
AssignmentNodeIF result;
if (node.getChildCount() == 3) {
ExpressionNodeIF leftHandSide = processUnary(node.getChild(0));
Tree operator = node.getChild(1);
ExpressionNodeIF rightHandSide = processAssignment(node.getChild(2));
if (!(leftHandSide instanceof LHSExpressionNodeIF)) {
throw new SyntaxException("Left value expected in assignment.");
}
result = ast.factory().assignmentNode(
(LHSExpressionNodeIF) leftHandSide, rightHandSide);
if (operator.equals(PragmaStringParser.PLUS_ASSIGN)) {
result.setAssignmentType(AST_ASSIGNMENT_TYPE.ADDITION);
} else if (operator.equals(PragmaStringParser.SUB_ASSIGN)) {
result.setAssignmentType(AST_ASSIGNMENT_TYPE.SUBTRACTION);
} else if (operator.equals(PragmaStringParser.MULTI_ASSIGN)) {
result.setAssignmentType(AST_ASSIGNMENT_TYPE.MULTIPLICATION);
} else if (operator.equals(PragmaStringParser.DIV_ASSIGN)) {
result.setAssignmentType(AST_ASSIGNMENT_TYPE.DIVISION);
} else if (!operator.equals(PragmaStringParser.ASSIGN)) {
throw new SyntaxException("The assignment type " + operator.getText() + " is not yet supported.");
}
} else {
return processConditional(node.getChild(0));
}
return result;
}
private ExpressionNodeIF processUnary(Tree node) throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
// FIXME: Not sure why this has changed from the original front-end,
// but check if this is actually a primary expression. If it is,
// call processPrimary() directly on the whole node instead of the
// child. Maybe there's a better way to do this?
// i.e. have a processNode() method that takes a node, looks at its
// type, and calls the appropriate method rather than depending on
// number of children, etc.?
if (node.getType() == PragmaStringLexer.PRIMARY_EXPR) {
return processPrimary(node);
}
return processPostfix(node.getChild(0));
} else {
if (node.getChild(0).getType() == PragmaStringParser.SIZEOF) {
TypeNodeIF operand = null;
// sizeof int
if (node.getChild(1).getType() == PragmaStringParser.TYPE_NAME) {
operand = processType(node.getChild(1).getText());
}
// sizeof(a)
else {
// TODO Do analysis of the type of the resulting expression
}
result = ast.factory().sizeOfNode(operand);
} else if (node.getChild(0).getType() == PragmaStringParser.CAST) {
TypeNodeIF castType = processType(node.getChild(1).getText());
result = ast.factory().castNode(castType,
processUnary(node.getChild(2)));
} else if (node.getChild(0).getType() == PragmaStringParser.UNARY_OP) {
String operatorString = node.getChild(0).getChild(0).getText();
OperatorNodeIF.AST_OPERATOR operator = null;
ExpressionNodeIF operand = processUnary(node.getChild(1));
if (operatorString.equalsIgnoreCase("+")) {
operator = OperatorNodeIF.AST_OPERATOR.ADD;
} else if (operatorString.equalsIgnoreCase("-")) {
operator = OperatorNodeIF.AST_OPERATOR.NEGATIVE;
} else if (operatorString.equalsIgnoreCase("!")) {
operator = OperatorNodeIF.AST_OPERATOR.LOGICAL_NOT;
} else if (operatorString.equalsIgnoreCase("~")) {
operator = OperatorNodeIF.AST_OPERATOR.BIT_NOT;
} else if (operatorString.equalsIgnoreCase("*")) {
return ast.factory().dereferenceNode(operand);
} else if (operatorString.equalsIgnoreCase("&")) {
operator = OperatorNodeIF.AST_OPERATOR.ADDRESS_OF;
} else if (operatorString.equalsIgnoreCase("++")) {
// TODO: Handle prefix vs postfix
if (!(operand instanceof LHSExpressionNodeIF)) {
throw new SyntaxException(
"Operand for an increment must be a left hand side expression");
}
return ast.factory().incrementNode(
(LHSExpressionNodeIF) operand, true, true);
} else if (operatorString.equalsIgnoreCase("--")) {
// TODO: Handle prefix vs postfix
if (!(operand instanceof LHSExpressionNodeIF)) {
throw new SyntaxException(
"Operand for a decrement must be a left hand side expression");
}
return ast.factory().incrementNode(
(LHSExpressionNodeIF) operand, true, false);
} else {
throw new SyntaxException("Unknown operator type: "
+ operatorString);
}
result = ast.factory().operatorNode(operator, operand);
}
}
return result;
}
private ExpressionNodeIF processPostfix(Tree node) throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
return processPrimary(node.getChild(0));
} else {
ExpressionNodeIF body = processPrimary(node.getChild(0));
result = processPostfixSuffix(body, node.getChild(1));
}
return result;
}
private ExpressionNodeIF processPostfixSuffix(ExpressionNodeIF body,
Tree node) throws SyntaxException {
ExpressionNodeIF result = null;
int type = node.getChild(0).getType();
// struct member reference
if (type == PragmaStringLexer.DOT) {
ExpressionNodeIF temp = null;
String fieldName = node.getChild(1).getText();
IdentifierNodeIF fieldID = ast.factory().identifierNode(fieldName);
if (!(body instanceof LHSExpressionNodeIF)) {
throw new SyntaxException(body, "The struct to which a field belongs must be a left-hand side expression.");
}
temp = ast.factory().fieldReferenceNode((LHSExpressionNodeIF) body, fieldID);
// Check for additional suffixes
if (node.getChildCount() == 3) {
result = this.processPostfixSuffix(temp, node.getChild(2));
} else {
result = temp;
}
}
// TODO Auto-generated method stub
return result;
}
private ExpressionNodeIF processPrimary(Tree node) throws SyntaxException {
ExpressionNodeIF result = null;
if (node.getChildCount() == 1) {
if (node.getChild(0).getType() == PragmaStringLexer.CONSTANT) {
result = processLiteral(node.getChild(0));
} else if (node.getChild(0).getType() == PragmaStringLexer.EVALUATED_FUNCTION_EXPR) {
result = processEvaluatedFunction(node.getChild(0));
} else if (node.getChild(0).getType() == PragmaStringLexer.DERIVATIVE_EXPR) {
result = processDerivative(node.getChild(0));
} else if (node.getChild(0).getType() == PragmaStringLexer.SPEC_EXPR) {
result = processSpecExpression(node.getChild(0));
} else {
IdentifierNodeIF identifier = ast.factory().identifierNode(
node.getChild(0).getText());
result = ast.factory().variableReferenceNode();
((VariableReferenceNodeIF) result).setName(identifier.name());
}
} else {
result = processExpression(node.getChild(0));
}
return result;
}
private ExpressionNodeIF processSpecExpression(Tree child) {
// TODO Auto-generated method stub
return null;
}
private ExpressionNodeIF processDerivative(Tree child) {
// TODO Auto-generated method stub
return null;
}
private ExpressionNodeIF processEvaluatedFunction(Tree child) {
// TODO Auto-generated method stub
return null;
}
private ExpressionNodeIF processLiteral(Tree node) throws SyntaxException {
ExpressionNodeIF expr = null;
String text;
switch (node.getChild(0).getType()) {
case PragmaStringLexer.TRUE:
expr = ast.factory().integerLiteralNode(null,
ast.factory().booleanTypeNode(), 1);
break;
case PragmaStringLexer.FALSE:
expr = ast.factory().integerLiteralNode(null,
ast.factory().booleanTypeNode(), 0);
break;
case PragmaStringLexer.INT_LITERAL:
// TODO Handle all the different types of ints/doubles
text = node.getChild(0).getText();
text = text.replaceAll("u", "");
text = text.replaceAll("U", "");
text = text.replaceAll("l", "");
text = text.replaceAll("L", "");
expr = ast.factory().integerLiteralNode(null,
ast.factory().integerTypeNode(), Integer.parseInt(text));
break;
case PragmaStringLexer.REAL_LITERAL:
text = node.getChild(0).getText();
text = text.replaceAll("F", "");
text = text.replaceAll("f", "");
expr = ast.factory().realLiteralNode(null,
ast.factory().realTypeNode(),
new RealNumberFactory().rational(text));
break;
case PragmaStringLexer.CHAR_LITERAL:
char[] charValue = node.getChild(0).getText().toCharArray();
if (charValue.length - 2 > 1) {
throw new SyntaxException(
"Char value have length greater than 1.");
}
char value = charValue[1];
expr = ast.factory().characterLiteralNode(null,
ast.factory().characterTypeNode(), value);
break;
// TODO Handle string literals, figure out if we still need system
// variables
// case PragmaStringLexer.STRING_LITERAL:
// String string = node.getChild(0).getText();
// char[] charArray = string.toCharArray();
// // subtract 2 to get rid of leading and trailing "
// int numChars = charArray.length - 2;
// ASTExpressionIF[] charLiterals = new ASTExpressionIF[numChars];
// ASTTypeIF charType = new ASTCharType();
// ASTIntegerLiteral extent = new ASTIntegerLiteral(numChars);
// ASTArrayType arrayType = new ASTArrayType(charType, extent);
//
// for (int i = 0; i < numChars; i++) {
// charLiterals[i] = new ASTCharLiteral(charType, charArray[i + 1]);
// }
// expr = new ASTArrayLiteral(arrayType, charLiterals);
// break;
// case PragmaStringLexer.SYS_VAR:
// if (node.getChild(0).getText().equals("PID")) {
// expr = new ASTSystemVariable(new ASTIntegerType(), SYS_VAR.PID);
// } else {
// expr = new ASTSystemVariable(new ASTIntegerType(),
// SYS_VAR.NPROCS);
// }
// break;
default:
throw new SyntaxException("Unknown constant type: "
+ node.getChild(0));
}
return expr;
}
private TypeNodeIF processType(String type) {
if (type.equals("int")) {
return ast.factory().integerTypeNode();
} else if (type.equals("char")) {
return ast.factory().characterTypeNode();
} else if (type.equals("_Bool")) {
return ast.factory().booleanTypeNode();
}
// TODO Add additional types
return null;
}
private CommonTree prepareTree(String pragma) throws SyntaxException {
// Using the generated lexer and parser to build the ANTLR tree.
PragmaStringLexer lex = new PragmaStringLexer(new ANTLRStringStream(
pragma));
CommonTokenStream tokens = new CommonTokenStream(lex);
PragmaStringParser parser = new PragmaStringParser(tokens);
pragma_return r = null;
try {
r = parser.pragma();
} catch (RecognitionException e) {
throw new SyntaxException(parser.getSourceName()
+ " parsed unsuccessfully: \n" + e.getMessage());
}
// Get the number of syntax errors from the lexer/parser.
int errors = parser.getNumberOfSyntaxErrors();
if (errors > 0) {
throw new SyntaxException(parser.getSourceName()
+ " parsed unsuccessfully.");
}
return (CommonTree) r.getTree();
}
@Override
public String name() {
return "pragmaParser";
}
}