AcslContractWorker.java

package edu.udel.cis.vsl.abc.front.c.astgen;

import edu.udel.cis.vsl.abc.ast.node.IF.*;
import edu.udel.cis.vsl.abc.ast.node.IF.acsl.*;
import edu.udel.cis.vsl.abc.ast.node.IF.acsl.CompositeEventNode.EventOperator;
import edu.udel.cis.vsl.abc.ast.node.IF.acsl.ExtendedQuantifiedExpressionNode.ExtendedQuantifier;
import edu.udel.cis.vsl.abc.ast.node.IF.acsl.MPICollectiveBlockNode.MPICommunicatorMode;
import edu.udel.cis.vsl.abc.ast.node.IF.acsl.MPIContractAbsentEventNode.MPIAbsentEventKind;
import edu.udel.cis.vsl.abc.ast.node.IF.acsl.MPIContractConstantNode.MPIConstantKind;
import edu.udel.cis.vsl.abc.ast.node.IF.acsl.MPIContractExpressionNode.MPIContractExpressionKind;
import edu.udel.cis.vsl.abc.ast.node.IF.acsl.MemoryEventNode.MemoryEventNodeKind;
import edu.udel.cis.vsl.abc.ast.node.IF.declaration.FunctionDeclarationNode;
import edu.udel.cis.vsl.abc.ast.node.IF.declaration.VariableDeclarationNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.*;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.ConstantNode.ConstantKind;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.OperatorNode.Operator;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.QuantifiedExpressionNode.Quantifier;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.BlockItemNode;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.CompoundStatementNode;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.StatementNode;
import edu.udel.cis.vsl.abc.ast.node.IF.type.ArrayTypeNode;
import edu.udel.cis.vsl.abc.ast.node.IF.type.FunctionTypeNode;
import edu.udel.cis.vsl.abc.ast.node.IF.type.TypeNode;
import edu.udel.cis.vsl.abc.ast.node.IF.type.TypeNode.TypeNodeKind;
import edu.udel.cis.vsl.abc.ast.type.IF.StandardBasicType.BasicTypeKind;
import edu.udel.cis.vsl.abc.ast.type.IF.StandardSignedIntegerType.SignedIntKind;
import edu.udel.cis.vsl.abc.ast.type.IF.StandardUnsignedIntegerType.UnsignedIntKind;
import edu.udel.cis.vsl.abc.ast.type.IF.Type;
import edu.udel.cis.vsl.abc.ast.type.IF.TypeFactory;
import edu.udel.cis.vsl.abc.config.IF.Configuration;
import edu.udel.cis.vsl.abc.err.IF.ABCRuntimeException;
import edu.udel.cis.vsl.abc.front.c.parse.AcslParser;
import edu.udel.cis.vsl.abc.front.c.ptree.CParseTree;
import edu.udel.cis.vsl.abc.front.common.astgen.SimpleScope;
import edu.udel.cis.vsl.abc.token.IF.*;
import edu.udel.cis.vsl.abc.token.IF.CivlcToken.TokenVocabulary;
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.Tree;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import static edu.udel.cis.vsl.abc.ast.node.IF.acsl.MPIContractAbsentEventNode.MPIAbsentEventKind.*;
import static edu.udel.cis.vsl.abc.front.IF.CivlcTokenConstant.EXPR;
import static edu.udel.cis.vsl.abc.front.IF.CivlcTokenConstant.TYPE;
import static edu.udel.cis.vsl.abc.front.c.parse.AcslParser.*;

/**
 * This is responsible for translating a CParseTree that represents an ACSL
 * contract specification for a function or a loop into an ordered list of
 * Contract nodes. It serves as a helper for {@link AcslContractHandler}. <br>
 * Precondition: all tokens are preprocessed with the regular program
 * components. <br>
 * Note: there are no separated lexer for the ACSL parser. All keywords are
 * recognized as IDENTIFIER or EXTENDED_IDENTIFIER and semantic predicates are
 * used to match different keywords, like <code>requires</code>,
 * <code>ensures</code>, <code>assumes</code> as IDENTIFIER and
 * <code>\valid</code>, <code>\result</code>, <code>\valid</code> as
 * EXTENDED_IDENTIFIER.
 *
 * @author Manchun Zheng (zmanchun)
 */
public class AcslContractWorker {

    /**
     * A collection of translated nodes. The collection is the result of any
     * ACSL contract translation. The collection includes two groups:
     * <li>a set of {@link ContractNode}s</li>
     * <li>a set of {@link BlockItemNode}s that can be directly put at the
     * position of the translated ACSL contract.</li>
     *
     * @author ziqingluo
     */
    public class ACSLSpecTranslation {
        /**
         * A set of {@link ContractNode}s which are the translation results of
         * the ACSL contract annotations.
         */
        final SequenceNode<ContractNode> contractNodes;
        /**
         * A set of {@link BlockItemNode}s which are the translation results of
         * some ACSL contract annotations that can be directly mapped to
         * existing ABC nodes.
         */
        final List<BlockItemNode> blockItemNodes;

        ACSLSpecTranslation(Source acslSpecSource,
                List<ContractNode> contractNodes,
                List<BlockItemNode> blockItemNodes) {
            assert contractNodes != null;
            assert blockItemNodes != null;
            this.contractNodes = nodeFactory.newSequenceNode(acslSpecSource,
                    "ACSL spec", contractNodes);
            this.blockItemNodes = blockItemNodes;
        }
    }

    /**
     * the parse tree to be translated
     */
    private CParseTree parseTree;

    /**
     * the node factory to be used for creating AST nodes
     */
    private NodeFactory nodeFactory;

    /**
     * the token factory
     */
    private TokenFactory tokenFactory;

    /**
     * the type factory
     */
    private TypeFactory typeFactory;

    /**
     * the formation to be used for transforming ANTLR tokens into CTokens
     */
    private Formation formation;

    /**
     * the configuration of this translation task
     */
    private Configuration config;

    /* ******************** Constants ******************* */
    private final String MPI_COMM_RANK = "\\mpi_comm_rank";
    private final String MPI_COMM_SIZE = "\\mpi_comm_size";
    private final String CIVL_ASSERT = "$assert";

    /**
     * creates a new instance of AcslContractWorker
     *
     * @param factory
     *         the node factory to be used
     * @param tokenFactory
     *         the token factory to be used
     * @param parseTree
     *         the parse tree to be translated
     */
    public AcslContractWorker(NodeFactory factory, TokenFactory tokenFactory,
            CParseTree parseTree, Configuration config) {
        this.nodeFactory = factory;
        this.tokenFactory = tokenFactory;
        this.parseTree = parseTree;
        this.typeFactory = nodeFactory.typeFactory();
        this.config = config;
        formation = tokenFactory.newTransformFormation("ACSL", "contract");
    }

    /**
     * translates the parse tree to a list of contract nodes. Currently, two
     * kinds of contracts are supported, one is function contract, the other is
     * loop annotation.
     *
     * @param scope
     *         the scope of the contract
     * @return the list of contract nodes which is the result of translating the
     * parse tree
     * @throws SyntaxException
     *         if there are syntax errors during the translation
     */
    public ACSLSpecTranslation generateContractNodes(SimpleScope scope)
            throws SyntaxException {
        CommonTree contractTree = parseTree.getRoot();
        List<ContractNode> translatedContractNodes = new LinkedList<>();
        List<BlockItemNode> translatedBlockItems = new LinkedList<>();

        switch (contractTree.getType()) {
            case AcslParser.FUNC_CONTRACT:
                translatedContractNodes.addAll(translateFunctionContractBlock(
                        (CommonTree) contractTree.getChild(0), scope));
                break;
            case AcslParser.LOOP_CONTRACT:
                translatedContractNodes.addAll(translateLoopContractBlock(
                        (CommonTree) contractTree.getChild(0), scope));
                break;
            case AcslParser.LOGIC_FUNCTIONS:
                translatedBlockItems
                        .addAll(translateLogicFunctions(contractTree, scope));
                break;
            case AcslParser.ASSERT_ACSL:
                translatedBlockItems
                        .add(translateACSLAssertion(contractTree, scope));
                break;
            default:
                throw this.error("unknown kind of contract", contractTree);
        }
        return new ACSLSpecTranslation(parseTree.source(contractTree),
                translatedContractNodes, translatedBlockItems);
    }

    /**
     * translates the contract for a loop.
     *
     * @param tree
     *         the tree to be translated, which represented the contracts of
     *         the loop
     * @param scope
     *         the current scope
     * @return the list of contracts associated with a loop
     * @throws SyntaxException
     *         if there are syntax errors
     */
    private List<ContractNode> translateLoopContractBlock(CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        int numChildren = tree.getChildCount();
        List<ContractNode> result = new ArrayList<>();

        assert tree.getType() == AcslParser.LOOP_CONTRACT_BLOCK;
        for (int i = 0; i < numChildren; i++) {
            CommonTree loopIterm = (CommonTree) tree.getChild(i);
            int loopItemKind = loopIterm.getType();

            switch (loopItemKind) {
                case AcslParser.LOOP_CLAUSE:
                    result.add(this.translateLoopClause(
                            (CommonTree) loopIterm.getChild(0), scope));
                    break;
                case AcslParser.LOOP_VARIANT:
                    System.err.println(
                            "loop variants are not supported hence ignored.");
                    break;
                case AcslParser.LOOP_BEHAVIOR:
                default:
                    throw this.error("unknown kind of loop contract",
                            loopIterm);
            }
        }
        return result;
    }

    /**
     * translate the LOGIC_FUNCTIONS list, which is a list of mixed items, each
     * of which is either a LOGIC_FUNCTION_CLAUSE or PREDICATE_CLAUSE:
     */
    private List<BlockItemNode> translateLogicFunctions(
            CommonTree logicFunctions, SimpleScope scope)
            throws SyntaxException {
        int numChild = logicFunctions.getChildCount();
        List<BlockItemNode> programNodes = new LinkedList<>();

        for (int i = 0; i < numChild; i++) {
            CommonTree clause = (CommonTree) logicFunctions.getChild(i);
            BlockItemNode translatedClause;

            if (clause.getType() == AcslParser.PREDICATE_CLAUSE)
                translatedClause = translatePredicateClause(clause, scope);
            else {
                assert clause.getType() == AcslParser.LOGIC_FUNCTION_CLAUSE;
                translatedClause = translateLogicFunctionClause(clause, scope);
            }
            programNodes.add(translatedClause);
        }
        return programNodes;
    }

    /**
     * Translate ACSL assert to CIVL $assert.
     */
    private BlockItemNode translateACSLAssertion(CommonTree assertTree,
            SimpleScope scope) throws SyntaxException {
        CommonTree predicate = (CommonTree) assertTree.getChild(0);
        Source source = parseTree.source(assertTree);
        ExpressionNode assertCall = nodeFactory.newFunctionCallNode(source,
                nodeFactory.newIdentifierExpressionNode(source,
                        nodeFactory.newIdentifierNode(source, CIVL_ASSERT)),
                Arrays.asList(translateExpression(predicate, scope)), null);

        return nodeFactory.newExpressionStatementNode(assertCall);
    }

    /**
     * Translate ACSL predicate clause
     * <code>predicate id binders (opt) = definition (opt) </code>
     *
     * @param predicate
     * @param scope
     * @return
     * @throws SyntaxException
     */
    private BlockItemNode translatePredicateClause(CommonTree predicateClause,
            SimpleScope scope) throws SyntaxException {
        CommonTree identifierTree = (CommonTree) predicateClause.getChild(0);
        CommonTree definitionTree = (CommonTree) predicateClause.getChild(1);
        FunctionDeclarationNode result = translateLogicFunctionBody(
                identifierTree, definitionTree,
                nodeFactory.newBasicTypeNode(parseTree.source(identifierTree),
                        BasicTypeKind.BOOL),
                scope);

        result.setIsLogicFunction(true);
        return result;
    }

    /**
     * Translate ACSL predicate clause
     * <code>logic type id binders (opt) = definition (opt) </code>
     *
     * @param logicFunctionClause
     * @param scope
     * @return
     * @throws SyntaxException
     */
    private BlockItemNode translateLogicFunctionClause(
            CommonTree logicFunctionClause, SimpleScope scope)
            throws SyntaxException {
        CommonTree typeTree = (CommonTree) logicFunctionClause.getChild(0);
        CommonTree identifierTree = (CommonTree) logicFunctionClause
                .getChild(1);
        CommonTree definitionTree = (CommonTree) logicFunctionClause
                .getChild(2);
        TypeNode returnType = translateTypeExpr(typeTree, scope);
        FunctionDeclarationNode result = translateLogicFunctionBody(
                identifierTree, definitionTree, returnType, scope);

        result.setIsLogicFunction(true);
        return result;
    }

    private FunctionDeclarationNode translateLogicFunctionBody(
            CommonTree identifierTree, CommonTree definitionTree,
            TypeNode outputType, SimpleScope scope) throws SyntaxException {
        CommonTree bindersTree = (CommonTree) definitionTree.getChild(0);
        CommonTree bodyTree = (CommonTree) definitionTree.getChild(1);
        SimpleScope defiScope = new SimpleScope(scope);
        SequenceNode<VariableDeclarationNode> binders;
        Source source = parseTree.source(definitionTree);
        ExpressionNode definition = null;
        IdentifierNode identifier = translateIdentifier(identifierTree);

        if (bindersTree.getType() != AcslParser.ABSENT)
            binders = translateBinders(bindersTree,
                    parseTree.source(bindersTree), defiScope);
        else
            binders = nodeFactory.newSequenceNode(source, "ABSENT",
                    Arrays.asList());

        FunctionTypeNode funcTypeNode = nodeFactory.newFunctionTypeNode(source,
                outputType, binders, false);
        FunctionDeclarationNode result;

        if (bodyTree.getType() != AcslParser.ABSENT) {
            definition = translateExpression(bodyTree, defiScope);

            StatementNode expressionBody = nodeFactory
                    .newReturnNode(definition.getSource(), definition);
            CompoundStatementNode returnExpr = nodeFactory
                    .newCompoundStatementNode(expressionBody.getSource(),
                            Arrays.asList(expressionBody));

            result = nodeFactory.newFunctionDefinitionNode(source, identifier,
                    funcTypeNode, null, returnExpr);
        } else
            result = nodeFactory.newAbstractFunctionDefinitionNode(source,
                    identifier, funcTypeNode, null, 0, null);
        return result;
    }

    /**
     * translates a loop clause, which could be a loop invariant, an assigns
     * clause, an allocate clause, or a free clause. Currently, only loop
     * invariant is supported.
     *
     * @param tree
     *         the tree represented a loop contract clause
     * @param scope
     *         the current scope
     * @return the contract node represented a loop clause
     * @throws SyntaxException
     *         if there are some syntax errors
     */
    private ContractNode translateLoopClause(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        int loopClauseKind = tree.getType();
        Source source = this.newSource(tree);

        switch (loopClauseKind) {
            case AcslParser.LOOP_INVARIANT: {
                CommonTree exprTree = (CommonTree) tree.getChild(0);
                ExpressionNode expression = this.translateExpression(exprTree,
                        scope);

                return this.nodeFactory.newInvariantNode(source, true,
                        expression);
            }
            case AcslParser.LOOP_ASSIGNS:
                return translateReadsOrAssigns(tree, scope, false);
            case AcslParser.LOOP_ALLOC:
            case AcslParser.LOOP_FREE:
            default:
                throw this.error("unknown kind of loop contract clause", tree);
        }
    }

    /**
     * translates a contract block associated with a function
     *
     * @param tree
     *         the tree representing the contract block
     * @param scope
     *         the current scope, which is the scope of the function
     *         parameter
     * @return the list of contract nodes after translation
     * @throws SyntaxException
     *         if there are syntax errors
     */
    private List<ContractNode> translateFunctionContractBlock(CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        int numChildren = tree.getChildCount();
        List<ContractNode> result = new ArrayList<>();

        assert tree.getType() == AcslParser.FUNC_CONTRACT_BLOCK;
        for (int i = 0; i < numChildren; i++) {
            CommonTree child = (CommonTree) tree.getChild(i);
            int childKind = child.getType();

            switch (childKind) {
                case AcslParser.CLAUSE_NORMAL:
                    result.add(this.translateContractClause(
                            (CommonTree) child.getChild(0), scope));
                    break;
                case AcslParser.CLAUSE_BEHAVIOR:
                    result.add(this.translateBehavior(
                            (CommonTree) child.getChild(0), scope));
                    break;
                case AcslParser.CLAUSE_COMPLETE:
                    result.add(this.translateCompleteness(
                            (CommonTree) child.getChild(0), scope));
                    break;
                case AcslParser.MPI_COLLECTIVE:
                    result.add(this.translateMPICollectiveBlock(
                            this.parseTree.source(child), child, scope));
                    break;
                default:
                    throw this.error("Unknown contract kind", tree);
            }
        }
        return result;
    }

    /**
     * translates the ACSL completeness clause for behavior, which could be
     * COMPLETE or DISJOINT.
     *
     * @param tree
     *         the tree representing the completeness clause
     * @param scope
     *         the current scope
     * @return the completeness node which is the result of translating the
     * given tree
     * @throws SyntaxException
     *         if there are some syntax errors
     */
    private CompletenessNode translateCompleteness(CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        int kind = tree.getType();
        boolean isComplete = false;
        SequenceNode<IdentifierNode> idList = this
                .translateIdList((CommonTree) tree.getChild(2), scope);
        Source source = this.parseTree.source(tree);

        switch (kind) {
            case AcslParser.BEHAVIOR_COMPLETE:
                isComplete = true;
                break;
            case AcslParser.BEHAVIOR_DISJOINT:
                break;
            default:
                throw this.error("Unknown kind of completeness clause", tree);
        }
        return this.nodeFactory.newCompletenessNode(source, isComplete, idList);
    }

    /**
     * translates a list of identifiers
     *
     * @param tree
     *         a tree that represents a list of identifiers
     * @param scope
     *         the current scope
     * @return a sequence of identifier node
     */
    private SequenceNode<IdentifierNode> translateIdList(CommonTree tree,
            SimpleScope scope) {
        int numChildren = tree.getChildCount();
        List<IdentifierNode> list = new ArrayList<>();
        Source source = this.parseTree.source(tree);

        for (int i = 0; i < numChildren; i++) {
            CommonTree idTree = (CommonTree) tree.getChild(i);

            list.add(this.translateIdentifier(idTree));
        }
        return this.nodeFactory.newSequenceNode(source, "ID list", list);
    }

    /**
     * translates an ACSL behavior block
     *
     * @param tree
     *         the tree that represents a behavior block
     * @param scope
     *         the current scope
     * @return the behavior node which is the result of translating the given
     * behavior block
     * @throws SyntaxException
     *         if there are any syntax errors.
     */
    private BehaviorNode translateBehavior(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        CommonTree idTree = (CommonTree) tree.getChild(1);
        CommonTree bodyTree = (CommonTree) tree.getChild(2);
        IdentifierNode id = this.translateIdentifier(idTree);
        SequenceNode<ContractNode> body = this.translateBehaviorBody(bodyTree,
                scope);

        return this.nodeFactory.newBehaviorNode(this.parseTree.source(tree), id,
                body);
    }

    /**
     * translates the body of a behavior block.
     *
     * @param tree
     *         the tree that represents the body of a behavior block
     * @param scope
     *         the current scope
     * @return a sequence of contract nodes which is the result of the
     * translation
     * @throws SyntaxException
     *         if there are any syntax errors
     */
    private SequenceNode<ContractNode> translateBehaviorBody(CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        Source source = this.parseTree.source(tree);
        int numChildren = tree.getChildCount();
        List<ContractNode> clauses = new ArrayList<>();

        for (int i = 0; i < numChildren; i++) {
            CommonTree clause = (CommonTree) tree.getChild(i);

            clauses.add(this.translateContractClause(clause, scope));
        }
        return this.nodeFactory.newSequenceNode(source, "behavior body",
                clauses);
    }

    /**
     * translates a contract clause.
     *
     * @param tree
     *         the tree that representing a contract clause
     * @param scope
     *         the current scope
     * @return the contract node which is the result of the translation
     * @throws SyntaxException
     *         if there are any syntax errors
     */
    private ContractNode translateContractClause(CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        int kind = tree.getType();

        switch (kind) {
            case AcslParser.ALLOC:
                return this.translateAllocation(tree, scope, true);
            case AcslParser.FREES:
                return this.translateAllocation(tree, scope, false);
            case AcslParser.REQUIRES_ACSL:
                return this.translateRequires(tree, scope);
            case AcslParser.ENSURES_ACSL:
                return this.translateEnsures(tree, scope);
            case AcslParser.ASSIGNS_ACSL:
                return this.translateReadsOrAssigns(tree, scope, false);
            case AcslParser.ASSUMES_ACSL:
                return this.translateAssumes(tree, scope);
            case AcslParser.READS_ACSL:
                return this.translateReadsOrAssigns(tree, scope, true);
            case AcslParser.DEPENDSON:
                return this.translateDepends(tree, scope);
            case AcslParser.EXECUTES_WHEN:
                return this.translateGuards(tree, scope);
            case AcslParser.WAITSFOR:
                return this.translateWaitsfor(tree, scope);
            default:
                throw this.error("Unknown contract clause kind", tree);
        }
    }

    private AllocationNode translateAllocation(CommonTree tree,
            SimpleScope scope, boolean isAllocates) throws SyntaxException {
        SequenceNode<ExpressionNode> memoryList = this
                .translateArgumentList((CommonTree) tree.getChild(1), scope);

        return this.nodeFactory.newAllocationNode(this.newSource(tree),
                isAllocates, memoryList);
    }

    /**
     * translates a guard clause, which has the syntax
     * <code>executes_when expr</code>.
     *
     * @param tree
     *         the tree that represents the guard clause
     * @param scope
     *         the current scope
     * @return the guard node that is the result of the translation
     * @throws SyntaxException
     *         if there are some syntax errors.
     */
    private GuardsNode translateGuards(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        CommonTree expressionTree = (CommonTree) tree.getChild(1);

        return this.nodeFactory.newGuardNode(this.newSource(tree),
                this.translateExpression(expressionTree, scope));
    }

    private WaitsforNode translateWaitsfor(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        CommonTree expressionTree = (CommonTree) tree.getChild(1);
        SequenceNode<ExpressionNode> arguments = translateArgumentList(
                expressionTree, scope);

        return nodeFactory.newWaitsforNode(newSource(tree), arguments);
    }

    /**
     * translates an assume clause, which has the syntax
     * <code>assumes expr</code>.
     *
     * @param tree
     *         the tree that represents an assumes clause
     * @param scope
     *         the current scope
     * @return the Assumes node
     * @throws SyntaxException
     *         if there are any syntax errors.
     */
    private AssumesNode translateAssumes(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        CommonTree exprTree = (CommonTree) tree.getChild(1);
        ExpressionNode predicate = this.translateExpression(exprTree, scope);
        Source source = this.parseTree.source(tree);

        return this.nodeFactory.newAssumesNode(source, predicate);
    }

    private AssignsOrReadsNode translateReadsOrAssigns(CommonTree tree,
            SimpleScope scope, boolean isRead) throws SyntaxException {
        Source source = this.parseTree.source(tree);
        SequenceNode<ExpressionNode> memoryList = translateArgumentList(
                (CommonTree) tree.getChild(1), scope);

        if (isRead)
            return this.nodeFactory.newReadsNode(source, memoryList);
        else
            return this.nodeFactory.newAssignsNode(source, memoryList);
    }

    private DependsNode translateDepends(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        Source source = this.parseTree.source(tree);
        CommonTree argumentTree = (CommonTree) tree.getChild(1);
        SequenceNode<DependsEventNode> argumentList = this
                .translateDependsEventList(argumentTree, scope);

        return this.nodeFactory.newDependsNode(source, null, argumentList);
    }

    private SequenceNode<ExpressionNode> translateArgumentList(CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        int numChildren = tree.getChildCount();
        List<ExpressionNode> list = new ArrayList<>();

        for (int i = 0; i < numChildren; i++) {
            CommonTree arg = (CommonTree) tree.getChild(i);

            list.add(this.translateExpression(arg, scope));
        }
        return this.nodeFactory.newSequenceNode(this.parseTree.source(tree),
                "argument list", list);
    }

    private SequenceNode<DependsEventNode> translateDependsEventList(
            CommonTree tree, SimpleScope scope) throws SyntaxException {
        int numChildren = tree.getChildCount();
        List<DependsEventNode> events = new ArrayList<>();
        Source source = this.parseTree.source(tree);

        for (int i = 0; i < numChildren; i++) {
            CommonTree event = (CommonTree) tree.getChild(i);

            events.add(this.translateDependsEvent(event, scope));
        }
        return this.nodeFactory.newSequenceNode(source, "depends event list",
                events);
    }

    private DependsEventNode translateDependsEvent(CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        int kind = tree.getType();

        switch (kind) {
            case EVENT_PLUS:
                EventOperator operator = EventOperator.UNION;
                return translateOperatorEvent(tree, operator, scope);
            case EVENT_SUB:
                operator = EventOperator.DIFFERENCE;
                return translateOperatorEvent(tree, operator, scope);
            case EVENT_INTS:
                operator = EventOperator.INTERSECT;
                return translateOperatorEvent(tree, operator, scope);
            case EVENT_BASE:
                return translateDependsEventBase((CommonTree) tree.getChild(0),
                        scope);
            default:
                throw this.error("unknown kind of operator for depends events",
                        tree);
        }
    }

    private CompositeEventNode translateOperatorEvent(CommonTree tree,
            EventOperator op, SimpleScope scope) throws SyntaxException {
        Source source = this.parseTree.source(tree);
        CommonTree leftTree = (CommonTree) tree.getChild(0),
                rightTree = (CommonTree) tree.getChild(1);
        DependsEventNode left = this.translateDependsEventBase(leftTree, scope),
                right = this.translateDependsEventBase(rightTree, scope);

        return this.nodeFactory.newOperatorEventNode(source, op, left, right);
    }

    private DependsEventNode translateDependsEventBase(CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        int kind = tree.getType();
        Source source = this.parseTree.source(tree);

        switch (kind) {
            case READ_ACSL: {
                SequenceNode<ExpressionNode> memList = this
                        .translateArgumentList((CommonTree) tree.getChild(1),
                                scope);

                return nodeFactory.newMemoryEventNode(source,
                        MemoryEventNodeKind.READ, memList);
            }
            case WRITE_ACSL: {
                SequenceNode<ExpressionNode> memList = this
                        .translateArgumentList((CommonTree) tree.getChild(1),
                                scope);

                return nodeFactory.newMemoryEventNode(source,
                        MemoryEventNodeKind.WRITE, memList);
            }
            case ACCESS_ACSL: {
                SequenceNode<ExpressionNode> memList = this
                        .translateArgumentList((CommonTree) tree.getChild(1),
                                scope);

                return nodeFactory.newMemoryEventNode(source,
                        MemoryEventNodeKind.REACH, memList);

            }
            case CALL_ACSL: {
                IdentifierNode function = this
                        .translateIdentifier((CommonTree) tree.getChild(1));
                SequenceNode<ExpressionNode> args = this.translateArgumentList(
                        (CommonTree) tree.getChild(1), scope);

                return nodeFactory.newCallEventNode(source,
                        this.nodeFactory.newIdentifierExpressionNode(
                                function.getSource(), function),
                        args);
            }
            case NOTHING:
                return nodeFactory.newNoactNode(source);
            case ANYACT:
                return nodeFactory.newAnyactNode(source);
            case EVENT_PARENTHESIZED:
                return translateDependsEvent((CommonTree) tree.getChild(0),
                        scope);
            default:
                throw this.error("unknown kind of nodes for depends events",
                        tree);
        }
    }

    private RequiresNode translateRequires(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        CommonTree expressionTree = (CommonTree) tree.getChild(1);
        Source source = this.newSource(tree);
        ExpressionNode expression = this.translateExpression(expressionTree,
                scope);

        return nodeFactory.newRequiresNode(source, expression);
    }

    private EnsuresNode translateEnsures(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        Source source = this.newSource(tree);
        CommonTree expressionTree = (CommonTree) tree.getChild(1);
        ExpressionNode expression = this.translateExpression(expressionTree,
                scope);

        return nodeFactory.newEnsuresNode(source, expression);
    }

    /**
     * Translates an expression.
     *
     * @param expressionTree
     *         any CommonTree node representing an expression
     * @return an ExpressionNode
     * @throws SyntaxException
     */
    private ExpressionNode translateExpression(CommonTree expressionTree,
            SimpleScope scope) throws SyntaxException {
        Source source = this.newSource(expressionTree);
        int kind = expressionTree.getType();

        switch (kind) {
            case INTEGER_CONSTANT:
                return translateIntegerConstant(source, expressionTree);
            case FLOATING_CONSTANT:
                return translateFloatingConstant(source, expressionTree);
            case CHARACTER_CONSTANT:
                return translateCharacterConstant(source, expressionTree);
            case STRING_LITERAL:
                return translateStringLiteral(source, expressionTree);
            case IDENTIFIER: {
                IdentifierNode identifier = translateIdentifier(expressionTree);
                ExpressionNode enumerationConsant = translateEnumerationConstant(
                        identifier, scope);

                return enumerationConsant != null
                        ? enumerationConsant
                        : nodeFactory.newIdentifierExpressionNode(source,
                        identifier);
            }
            case TERM_PARENTHESIZED:
                return translateExpression(
                        (CommonTree) expressionTree.getChild(0), scope);
            case DOT:
            case ARROW:
                return translateDotOrArrow(source, expressionTree, scope);
            case OPERATOR:
                return translateOperatorExpression(source, expressionTree,
                        scope);
            case RELCHAIN:
                return translateRelationalChain(source, expressionTree, scope);
            case TRUE_ACSL:
                return translateTrue(source);
            case FALSE_ACSL:
                return translateFalse(source);
            case RESULT_ACSL:
                return nodeFactory.newResultNode(source);
            case SELF:
                return nodeFactory.newSelfNode(source);
            case DOTDOT:
                return translateRegularRange(source, expressionTree, scope);
            case WRITE_ACSL:
                return translateWriteEvent(source, expressionTree, scope);
            case NOTHING:
                return this.nodeFactory.newNothingNode(source);
            case ELLIPSIS:
                return this.nodeFactory.newWildcardNode(source);
            case MPI_CONSTANT:
                return translateMPIConstantNode(expressionTree, source);
            case MPI_EXPRESSION:
                return translateMPIExpressionNode(expressionTree, source,
                        scope);
            case VALID:
                return this.translateValidNode(expressionTree, source, scope);
            case REMOTE_ACCESS:
                return translateRemoteExpression(expressionTree, source, scope);
            case QUANTIFIED:
                return translateQuantifiedExpression(expressionTree, source,
                        scope);
            case FUNC_CALL:
                return translateCall(source, expressionTree, scope);
            case AcslParser.OBJECT_OF:
                return translateObjectOf(source, expressionTree, scope);
            case AcslParser.QUANTIFIED_EXT:
                return translateExtendedQuantification(source,
                        (CommonTree) expressionTree.getChild(0), scope);
            case AcslParser.LAMBDA_ACSL:
                return translateLambda(source, expressionTree, scope);
            case AcslParser.OLD:
                return translateOld(source, expressionTree, scope);
            case SIZEOF:
                return translateSizeOf(source, expressionTree, scope);
            case CAST:
                return nodeFactory.newCastNode(source,
                        translateTypeExpr(
                                (CommonTree) expressionTree.getChild(0), scope),
                        translateExpression(
                                (CommonTree) expressionTree.getChild(1),
                                scope));
            case SET_BINDERS:
                throw error("Unsupported expression kind", expressionTree);
            default:
                throw error("Unknown expression kind", expressionTree);
        } // end switch
    }

    /**
     * @param expressionTree
     * @return
     * @throws SyntaxException
     */
    private SizeofNode translateSizeOf(Source source, CommonTree expressionTree,
            SimpleScope scope) throws SyntaxException {
        int kind = expressionTree.getChild(0).getType();
        CommonTree child = (CommonTree) expressionTree.getChild(1);
        SizeableNode sizeable;

        if (kind == EXPR)
            sizeable = translateExpression(child, scope);
        else if (kind == TYPE)
            sizeable = this.translateTypeExpr(child, scope);
        else
            throw error("Unexpected argument to sizeof", expressionTree);
        return nodeFactory.newSizeofNode(source, sizeable);
    }

    private ExpressionNode translateOld(Source source, CommonTree old,
            SimpleScope scope) throws SyntaxException {
        ExpressionNode expr = this
                .translateExpression((CommonTree) old.getChild(1), scope);

        return nodeFactory.newOperatorNode(source, Operator.OLD, expr);
    }

    private ExpressionNode translateLambda(Source source, CommonTree lambda,
            SimpleScope scope) throws SyntaxException {
        SimpleScope newScope = new SimpleScope(scope);
        SequenceNode<VariableDeclarationNode> variableList = this
                .translateBinders((CommonTree) lambda.getChild(1),
                        this.newSource((CommonTree) lambda.getChild(1)),
                        newScope);
        ExpressionNode expression = this
                .translateExpression((CommonTree) lambda.getChild(2), newScope);

        assert variableList.numChildren() == 1;
        return nodeFactory.newLambdaNode(source,
                variableList.getSequenceChild(0).copy(), expression);
    }

    private ExpressionNode translateExtendedQuantification(Source source,
            CommonTree extQuant, SimpleScope scope) throws SyntaxException {
        int quant = extQuant.getType();
        ExtendedQuantifier quantifier = null;
        ExpressionNode lo = this
                .translateExpression((CommonTree) extQuant.getChild(1), scope),
                hi = this.translateExpression((CommonTree) extQuant.getChild(2),
                        scope),
                function = this.translateExpression(
                        (CommonTree) extQuant.getChild(3), scope);

        switch (quant) {
            case AcslParser.MAX:
                quantifier = ExtendedQuantifier.MAX;
                break;
            case AcslParser.MIN:
                quantifier = ExtendedQuantifier.MIN;
                break;
            case AcslParser.SUM:
                quantifier = ExtendedQuantifier.SUM;
                break;
            case AcslParser.PROD:
                quantifier = ExtendedQuantifier.PROD;
                break;
            case AcslParser.NUMOF:
                quantifier = ExtendedQuantifier.NUMOF;
                break;
            default:
                throw this.error("unknown kind of extended quantifier ",
                        extQuant);
        }
        return nodeFactory.newExtendedQuantifiedExpressionNode(source,
                quantifier, lo, hi, function);
    }

    private ExpressionNode translateObjectOf(Source source, CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        CommonTree operandTree = (CommonTree) tree.getChild(2);
        ExpressionNode operand = this.translateExpression(operandTree, scope);

        return nodeFactory.newObjectofNode(source, operand);
    }

    /**
     * translate a quantified expression. e.g. \\forall | \\exists type_name
     * identifier; predicate
     *
     * @param expressionTree
     * @param source
     * @param scope
     * @return
     * @throws SyntaxException
     */
    private ExpressionNode translateQuantifiedExpression(
            CommonTree expressionTree, Source source, SimpleScope scope)
            throws SyntaxException {
        SimpleScope newScope = new SimpleScope(scope);
        CommonTree quantifierTree = (CommonTree) expressionTree.getChild(0);
        // The children of the quantifierTree are as follows:
        // arg0: the keyword "\forall", "\exists", or "\lambda"
        // arg1: the binders tree
        // arg2: the formula
        CommonTree bindersTree = (CommonTree) expressionTree.getChild(1);
        CommonTree predTree = (CommonTree) expressionTree.getChild(2);
        ExpressionNode restrict, pred;
        SequenceNode<VariableDeclarationNode> binders;
        Quantifier quantifier;
        // If the quantified expression has more than one binder, it will be
        // translated into several quantifiedExpressions each of which has exact
        // one binder:
        // boolean firstQuantifiedExpr = true;
        // ExpressionNode result = null;
        List<PairNode<SequenceNode<VariableDeclarationNode>, ExpressionNode>> boundVariableList = new LinkedList<>();

        if (quantifierTree.getType() == AcslParser.FORALL_ACSL) {
            quantifier = Quantifier.FORALL;
            restrict = null;
            // if the expression has the form "forall ... ; p==>q",
            // the type of predicate will be OPERATOR, arg0 will be IMPLIES
            // or IMPLIES_ACSL, and arg1 will be an ARGUMENT_LIST with 2
            // children, p and q.
            if (predTree.getType() == OPERATOR) {
                Tree predOperatorTree = predTree.getChild(0);
                int predOperatorType = predOperatorTree.getType();

                if (predOperatorType == IMPLIES_ACSL
                    || predOperatorType == IMPLIES) {
                    Tree predArgTree = predTree.getChild(1);

                    assert predArgTree.getChildCount() == 2;

                    CommonTree restrictTree = (CommonTree) predArgTree
                            .getChild(0);

                    predTree = (CommonTree) predArgTree.getChild(1);
                    restrict = translateExpression(restrictTree, newScope);
                }
            }
            pred = translateExpression(predTree, newScope);
        } else if (quantifierTree.getType() == AcslParser.EXISTS_ACSL) {
            quantifier = Quantifier.EXISTS;
            pred = translateExpression(predTree, newScope);
            restrict = null;
        } else {
            throw error("Unexpexted quantifier " + quantifierTree.getType(),
                    quantifierTree);
        }
        binders = translateBinders(bindersTree, source, newScope);
        boundVariableList.add(nodeFactory.newPairNode(source, binders, null));
        return nodeFactory.newQuantifiedExpressionNode(source, quantifier,
                nodeFactory.newSequenceNode(source,
                        "bound variable declaration list", boundVariableList),
                restrict, pred, null);
    }

    private ExpressionNode translateRemoteExpression(CommonTree tree,
            Source source, SimpleScope scope) throws SyntaxException {
        SimpleScope newScope = new SimpleScope(scope);
        CommonTree procTree = (CommonTree) tree.getChild(1);
        CommonTree exprTree = (CommonTree) tree.getChild(2);
        ExpressionNode exprArg, procArg;

        exprArg = translateExpression(exprTree, newScope);
        procArg = translateExpression(procTree, newScope);
        return nodeFactory.newRemoteOnExpressionNode(source, procArg, exprArg);
    }

    private SequenceNode<VariableDeclarationNode> translateBinders(
            CommonTree tree, Source source, SimpleScope scope)
            throws SyntaxException {
        int count = tree.getChildCount();
        List<VariableDeclarationNode> vars = new LinkedList<>();

        for (int i = 0; i < count; i++) {
            CommonTree binder = (CommonTree) tree.getChild(i);

            vars.addAll(this.translateBinder(binder, scope));
        }
        return this.nodeFactory.newSequenceNode(source, "Binder List", vars);
    }

    private List<VariableDeclarationNode> translateBinder(CommonTree tree,
            SimpleScope scope) throws SyntaxException {
        CommonTree typeTree = (CommonTree) tree.getChild(0);
        int numChild = tree.getChildCount();
        TypeNode type = this.translateTypeExpr(typeTree, scope);
        List<VariableDeclarationNode> result = new LinkedList<>();

        for (int i = 1; i < numChild; i++) {
            CommonTree varIdent = (CommonTree) tree.getChild(i);

            result.add(
                    this.translateVariableIdent(varIdent, scope, type.copy()));
        }
        return result;
    }

    private TypeNode translateTypeExpr(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        int kind = tree.getType();

        switch (kind) {
            case LOGIC_TYPE:
                return translateLogicType((CommonTree) tree.getChild(0), scope);
            case C_TYPE:
                return translateCType((CommonTree) tree.getChild(0),
                        (CommonTree) tree.getChild(1), scope);
            default:
                throw this.error("unkown kind of tyep expression", tree);
        }
    }

    /**
     * ^(C_TYPE specifierList abstractDeclarator)
     *
     * @param specifierList
     *         Type specifier tree
     * @param declarators
     *         Abstract declarator tree
     * @param scope
     * @return
     * @throws SyntaxException
     */
    private TypeNode translateCType(CommonTree specifierList,
            CommonTree declarators, SimpleScope scope) throws SyntaxException {
        Source specifierSource = newSource(specifierList);
        SpecifierAnalysis specifierAnalyzer;
        TypeNode result;
        DeclaratorData declaratorData;

        specifierAnalyzer = new SpecifierAnalysis(specifierList, parseTree,
                config);
        if (specifierAnalyzer.typeNameKind == TypeNodeKind.BASIC)
            result = nodeFactory.newBasicTypeNode(specifierSource,
                    specifierAnalyzer.getBasicTypeKind());
        else if (specifierAnalyzer.typeNameKind == TypeNodeKind.VOID)
            result = nodeFactory.newVoidTypeNode(specifierSource);
        else
            throw new RuntimeException("Translation of C type of kind : "
                                       + specifierAnalyzer.typeNameKind
                                       + " has not been implemented.");
        if (declarators.getType() != ABSENT) {
            declaratorData = processDeclarator(declarators, result, scope);
            result = declaratorData.type;
        }
        return result;
    }

    /**
     * Creates a new DeclaratorData based on given direct declarator tree node
     * and base type. The direct declarator may be abstract.
     *
     * @param directDeclarator
     *         CommonTree node of type DIRECT_DECLARATOR,
     *         DIRECT_ABSTRACT_DECLARATOR, or ABSENT
     * @param type
     *         base type
     * @return new DeclaratorData with derived type and identifier
     * @throws SyntaxException
     */
    private DeclaratorData processDirectDeclarator(CommonTree directDeclarator,
            TypeNode type, SimpleScope scope) throws SyntaxException {
        if (directDeclarator.getType() == ABSENT) {
            return new DeclaratorData(type, null);
        } else {
            int numChildren = directDeclarator.getChildCount();
            CommonTree prefix = (CommonTree) directDeclarator.getChild(0);

            // need to peel off right-most suffix first. Example:
            // T prefix [](); : (array of function returning T) prefix;
            for (int i = numChildren - 1; i >= 1; i--)
                type = translateDeclaratorSuffix(
                        (CommonTree) directDeclarator.getChild(i), type, scope);
            switch (prefix.getType()) {
                case ABSTRACT_DECLARATOR:
                    return processDeclarator(prefix, type, scope);
                case ABSENT:
                    return new DeclaratorData(type, null);
                default:
                    throw error("Unexpected node for direct declarator prefix",
                            prefix);
            }
        }
    }

    /**
     * Creates new DeclaratorData based on given declarator tree node and base
     * type. The declarator may be abstract. The data gives the new type formed
     * by applying the type derivation operations of the declarator to the base
     * type. The data also gives the identifier being declared, though this may
     * be null in the case of an abstract declarator.
     *
     * @param declarator
     *         CommonTree node of type DECLARATOR, ABSTRACT_DECLARATOR, or
     *         ABSENT
     * @param type
     *         the start type before applying declarator operations
     * @return new DeclaratorData with type derived from given type and
     * identifier
     * @throws SyntaxException
     */
    private DeclaratorData processDeclarator(CommonTree declarator,
            TypeNode type, SimpleScope scope) throws SyntaxException {
        if (declarator.getType() == ABSENT) {
            return new DeclaratorData(type, null);
        } else {
            CommonTree pointerTree = (CommonTree) declarator.getChild(0);
            CommonTree directDeclarator = (CommonTree) declarator.getChild(1);
            type = translatePointers(pointerTree, type, scope);

            return processDirectDeclarator(directDeclarator, type, scope);
        }
    }

    /**
     * Returns the new type obtained by taking the given type and applying the
     * pointer operations to it. For example, if the old type is "int" and the
     * pointerTree is "*", the result is the type "pointer to int".
     *
     * @param pointerTree
     *         CommonTree node of type POINTER or ABSENT
     * @param type
     *         base type
     * @return modified type
     * @throws SyntaxException
     *         if an unknown kind of type qualifier appears
     */
    private TypeNode translatePointers(CommonTree pointerTree, TypeNode type,
            SimpleScope scope) throws SyntaxException {
        int numChildren = pointerTree.getChildCount();
        Source source = type.getSource();

        for (int i = 0; i < numChildren; i++) {
            CommonTree starNode = (CommonTree) pointerTree.getChild(i);

            source = tokenFactory.join(source, newSource(starNode));
            type = nodeFactory.newPointerTypeNode(source, type);
        }
        return type;
    }

    /**
     * Process declarator suffix, currently it only supports ARRAY_SUFFIX
     *
     * @param suffix
     *         a CommonTree node of type ARRAY_SUFFIX or FUNCTION_SUFFIX
     * @param type
     * @return new type
     * @throws SyntaxException
     *         if the kind of suffix is not function or array
     */
    private TypeNode translateDeclaratorSuffix(CommonTree suffix,
            TypeNode baseType, SimpleScope scope) throws SyntaxException {
        int kind = suffix.getType();

        if (kind == ARRAY_SUFFIX)
            return translateArraySuffix(suffix, baseType, scope);
        else
            throw error("Unknown declarator suffix", suffix);
    }

    /**
     * process ARRAY_SUFFIX tree, currently it only supports two subscript
     * forms. The form is either specified with extent or not:
     * <code>[ ] or [extent]</code>
     *
     * @param suffix
     * @param baseType
     * @return
     * @throws SyntaxException
     */
    private ArrayTypeNode translateArraySuffix(CommonTree suffix,
            TypeNode baseType, SimpleScope scope) throws SyntaxException {
        CommonTree extentNode = (CommonTree) suffix.getChild(1);
        int extentNodeType = extentNode.getType();
        ExpressionNode extent = null;
        Source source = tokenFactory.join(baseType.getSource(),
                newSource(suffix));

        switch (extentNodeType) {
            case ABSENT:
                break;
            default:
                extent = translateExpression(extentNode, scope);
        }
        return nodeFactory.newArrayTypeNode(source, baseType, extent);
    }

    private TypeNode translateLogicType(CommonTree tree, SimpleScope scope)
            throws SyntaxException {
        int kind = tree.getType();
        Source source = this.newSource(tree);

        switch (kind) {
            case TYPE_BUILTIN: {
                int typeKind = tree.getChild(0).getType();

                switch (typeKind) {
                    case BOOLEAN:
                        return this.nodeFactory.newBasicTypeNode(source,
                                BasicTypeKind.BOOL);
                    case INTEGER:
                        return this.nodeFactory.newBasicTypeNode(source,
                                BasicTypeKind.INT);
                    case REAL_ACSL:
                        return this.nodeFactory.newBasicTypeNode(source,
                                BasicTypeKind.REAL);
                    default:
                        throw this.error("unknown built-in logic type", tree);
                }
            }
            case TYPE_ID:
                return this.nodeFactory.newTypedefNameNode(
                        this.translateIdentifier((CommonTree) tree.getChild(0)),
                        null);
            default:
                throw this.error("unknown kind of logic type", tree);
        }
    }

    private VariableDeclarationNode translateVariableIdent(CommonTree tree,
            SimpleScope scope, TypeNode baseType) throws SyntaxException {
        int kind = tree.getType();
        Source source = this.newSource(tree);

        switch (kind) {
            case VAR_ID_STAR: {
                VariableDeclarationNode baseVar = this
                        .translateVariableIdentBase(
                                (CommonTree) tree.getChild(0), source, scope,
                                baseType);
                TypeNode baseVarType, type;

                baseVarType = baseVar.getTypeNode();
                baseVarType.remove();
                type = this.nodeFactory.newPointerTypeNode(source, baseVarType);
                baseVar.setTypeNode(type);
                return baseVar;
            }
            case VAR_ID_SQUARE: {
                VariableDeclarationNode baseVar = this
                        .translateVariableIdentBase(
                                (CommonTree) tree.getChild(0), source, scope,
                                baseType);
                TypeNode baseVarType, type;

                baseVarType = baseVar.getTypeNode();
                baseVarType.remove();
                type = this.nodeFactory.newArrayTypeNode(source, baseVarType,
                        null);
                baseVar.setTypeNode(type);
                return baseVar;
            }
            case VAR_ID:
                return this.translateVariableIdentBase(
                        (CommonTree) tree.getChild(0), source, scope, baseType);
            default:
                throw this.error("unknown kind of variable identity", tree);
        }
    }

    private VariableDeclarationNode translateVariableIdentBase(CommonTree tree,
            Source source, SimpleScope scope, TypeNode baseType)
            throws SyntaxException {
        int kind = tree.getType();

        switch (kind) {
            case IDENTIFIER: {
                IdentifierNode identifier = this.translateIdentifier(tree);

                return this.nodeFactory.newVariableDeclarationNode(
                        identifier.getSource(), identifier, baseType);
            }
            case VAR_ID_BASE:
                return this.translateVariableIdent(
                        (CommonTree) tree.getChild(0), scope, baseType);
            default:
                throw this.error("unknown kind of variable identity base",
                        tree);
        }
    }

    // ////////////////////////////////////
    private ExpressionNode translateValidNode(CommonTree tree, Source source,
            SimpleScope scope) throws SyntaxException {
        CommonTree argumentTree = (CommonTree) tree.getChild(1);
        ExpressionNode argument;

        argument = translateExpression(argumentTree, scope);
        return nodeFactory.newOperatorNode(source, Operator.VALID, argument);
    }

    private ExpressionNode translateWriteEvent(Source source,
            CommonTree expressionTree, SimpleScope scope) {
        // TODO Auto-generated method stub
        return null;
    }

    private IntegerConstantNode translateIntegerConstant(Source source,
            CommonTree integerConstant) throws SyntaxException {
        return nodeFactory.newIntegerConstantNode(source,
                integerConstant.getText());
    }

    private FloatingConstantNode translateFloatingConstant(Source source,
            CommonTree floatingConstant) throws SyntaxException {
        return nodeFactory.newFloatingConstantNode(source,
                floatingConstant.getText());
    }

    private CharacterConstantNode translateCharacterConstant(Source source,
            CommonTree characterConstant) throws SyntaxException {
        CharacterToken token = (CharacterToken) characterConstant.getToken();

        return nodeFactory.newCharacterConstantNode(source,
                characterConstant.getText(), token.getExecutionCharacter());
    }

    private ConstantNode translateTrue(Source source) {
        return nodeFactory.newBooleanConstantNode(source, true);
    }

    private ConstantNode translateFalse(Source source) {
        return nodeFactory.newBooleanConstantNode(source, false);
    }

    private StringLiteralNode translateStringLiteral(Source source,
            CommonTree stringLiteral) throws SyntaxException {
        StringToken token = (StringToken) stringLiteral.getToken();

        return nodeFactory.newStringLiteralNode(source, stringLiteral.getText(),
                token.getStringLiteral());
    }

    private ExpressionNode translateRegularRange(Source source,
            CommonTree expressionTree, SimpleScope scope)
            throws SyntaxException {
        // regular range expression lo..hi or lo..hi#step
        ExpressionNode loNode = translateExpression(
                (CommonTree) expressionTree.getChild(0), scope);
        ExpressionNode hiNode = translateExpression(
                (CommonTree) expressionTree.getChild(1), scope);
        if (expressionTree.getChildCount() > 2) {
            CommonTree stepTree = (CommonTree) expressionTree.getChild(2);

            if (stepTree != null /* && stepTree.getType() != ABSENT */) {
                ExpressionNode stepNode = translateExpression(stepTree, scope);

                return nodeFactory.newRegularRangeNode(source, loNode, hiNode,
                        stepNode);
            }
        }
        return nodeFactory.newRegularRangeNode(source, loNode, hiNode);

    }

    /**
     * Translates a function call expression.
     *
     * @param callTree
     *         CommonTree node of type CALL, representing a function call
     * @return a FunctionCallNode corresponding to the ANTLR tree
     * @throws SyntaxException
     */
    private FunctionCallNode translateCall(Source source, CommonTree callTree,
            SimpleScope scope) throws SyntaxException {
        CommonTree functionTree = (CommonTree) callTree.getChild(0);
        // CommonTree contextArgumentListTree = (CommonTree)
        // callTree.getChild(2);
        CommonTree argumentListTree = (CommonTree) callTree.getChild(1);
        ExpressionNode functionNode = translateExpression(functionTree, scope);
        // int numContextArgs = contextArgumentListTree.getChildCount();
        int numArgs = argumentListTree.getChildCount();
        // List<ExpressionNode> contextArgumentList = new
        // LinkedList<ExpressionNode>();
        List<ExpressionNode> argumentList = new LinkedList<ExpressionNode>();

        for (int i = 0; i < numArgs; i++) {
            CommonTree argumentTree = (CommonTree) argumentListTree.getChild(i);
            ExpressionNode argumentNode = translateExpression(argumentTree,
                    scope);

            argumentList.add(argumentNode);
        }
        return nodeFactory.newFunctionCallNode(source, functionNode,
                new LinkedList<ExpressionNode>(), argumentList, null);
    }

    /**
     * @param expressionTree
     * @return
     * @throws SyntaxException
     */
    private ExpressionNode translateDotOrArrow(Source source,
            CommonTree expressionTree, SimpleScope scope)
            throws SyntaxException {
        int kind = expressionTree.getType();
        CommonTree argumentNode = (CommonTree) expressionTree.getChild(0);
        CommonTree fieldNode = (CommonTree) expressionTree.getChild(1);
        ExpressionNode argument = translateExpression(argumentNode, scope);
        IdentifierNode fieldName = translateIdentifier(fieldNode);

        if (kind == DOT)
            return nodeFactory.newDotNode(source, argument, fieldName);
        else
            return nodeFactory.newArrowNode(source, argument, fieldName);
    }

    /**
     * Translates an ACSL relational chain expression. An example is "x < y < z"
     * , which is ACSL short-hand for "x<y && y<z". Here are some notes from the
     * ACSL spec:
     *
     * <pre>
     * The construct t1 relop1 t2 relop2 t3 · · · tk
     * with several consecutive comparison operators is a shortcut
     * (t1 relop1 t2) && (t2 relop2 t3) && ···.
     * It is required that the relopi operators must be in the same "direction",
     * i.e. they must all belong either to {<, <=, ==} or to {>,>=,==}.
     * Expressions such as x < y > z or x != y != z are not allowed.
     * </pre>
     *
     * @param source
     *         source for the token sequence which makes up the expression
     * @param expressionTree
     *         the parse tree resulting from parsing the expression token
     *         sequence
     * @param scope
     *         the scope in which the expression occurs
     * @return the root of an AST tree representing this expression
     * @throws SyntaxException
     *         if the operators are not all in the same "direction"
     */
    private OperatorNode translateRelationalChain(Source source,
            CommonTree tree, SimpleScope scope) throws SyntaxException {
        assert tree.getType() == RELCHAIN;

        int numChildren = tree.getChildCount();

        if (numChildren < 3)
            throw new SyntaxException(
                    "relational chain has fewer than 3 arguments", source);
        if (numChildren % 2 == 0)
            throw new SyntaxException(
                    "relational chain has even number of arguments", source);

        // direction: 0=equality or unknown, 1=increasing, -1=decreasing,
        // -2=inequality
        int direction = 0;
        CommonTree arg1 = (CommonTree) tree.getChild(0), arg2;
        Source source1 = newSource(arg1), source2;
        int i = 1;
        OperatorNode result = null;
        Source resultSource = null;

        while (i < numChildren) {
            CommonTree rel = (CommonTree) tree.getChild(i);
            Operator operator;

            if (i > 1 && direction == -2)
                throw error("'!=' prohibited in a relational chain", rel);
            i++;
            switch (rel.getType()) {
                case LT:
                    operator = Operator.LT;
                    if (direction == 0)
                        direction = 1;
                    else if (direction < 0)
                        throw error(
                                "'<' prohibited in a decreasing relational chain",
                                rel);
                    break;
                case LTE:
                    operator = Operator.LTE;
                    if (direction == 0)
                        direction = 1;
                    else if (direction < 0)
                        throw error(
                                "'<=' prohibited in a decreasing relational chain",
                                rel);
                    break;
                case EQUALS:
                    operator = Operator.EQUALS;
                    break;
                case GTE:
                    operator = Operator.GTE;
                    if (direction == 0)
                        direction = -1;
                    else if (direction > 0)
                        throw error(
                                "'>=' prohibited in an increasing relational chain",
                                rel);
                    break;
                case GT:
                    operator = Operator.GT;
                    if (direction == 0)
                        direction = -1;
                    else if (direction > 0)
                        throw error(
                                "'>' prohibited in an increasing relational chain",
                                rel);
                    break;
                case NEQ:
                    if (i > 2)
                        throw error("'!=' prohibited in a relational chain",
                                rel);
                    operator = Operator.NEQ;
                    direction = -2;
                    break;
                default:
                    throw new ABCRuntimeException(
                            "unknown ACSL relational operator: " + rel);
            }
            arg2 = (CommonTree) tree.getChild(i);
            i++;

            ExpressionNode node1 = translateExpression(arg1, scope);
            ExpressionNode node2 = translateExpression(arg2, scope);

            source2 = node2.getSource();

            Source clauseSource = tokenFactory.join(source1, source2);
            OperatorNode clause = nodeFactory.newOperatorNode(clauseSource,
                    operator, node1, node2);

            if (result == null) {
                resultSource = clauseSource;
                result = clause;
            } else {
                resultSource = tokenFactory.join(resultSource, source2);
                result = nodeFactory.newOperatorNode(resultSource,
                        Operator.LAND, result, clause);
            }
            arg1 = arg2;
            source1 = source2;
        }
        return result;
    }

    /**
     * @param expressionTree
     * @return
     * @throws SyntaxException
     */
    private OperatorNode translateOperatorExpression(Source source,
            CommonTree expressionTree, SimpleScope scope)
            throws SyntaxException {
        CommonTree operatorTree = (CommonTree) expressionTree.getChild(0);
        int operatorKind = operatorTree.getType();
        CommonTree argumentList = (CommonTree) expressionTree.getChild(1);
        int numArgs = argumentList.getChildCount();
        List<ExpressionNode> arguments = new LinkedList<ExpressionNode>();
        Operator operator;

        for (int i = 0; i < numArgs; i++) {
            ExpressionNode argument = translateExpression(
                    (CommonTree) argumentList.getChild(i), scope);

            arguments.add(argument);
        }
        switch (operatorKind) {
            case AMPERSAND:
                operator = numArgs == 1 ? Operator.ADDRESSOF : Operator.BITAND;
                break;
            case ASSIGN:
                operator = Operator.ASSIGN;
                break;
            case TILDE:
                operator = Operator.BITCOMPLEMENT;
                break;
            case BITOR:
                operator = Operator.BITOR;
                break;
            case BITXOR:
                operator = Operator.BITXOR;
                break;
            case COMMA:
                operator = Operator.COMMA;
                break;
            case QMARK:
                operator = Operator.CONDITIONAL;
                break;
            case STAR:
                operator = numArgs == 1 ? Operator.DEREFERENCE : Operator.TIMES;
                break;
            case DIV:
                operator = Operator.DIV;
                break;
            case EQUALS:
                operator = Operator.EQUALS;
                break;
            case GT:
                operator = Operator.GT;
                break;
            case GTE:
                operator = Operator.GTE;
                break;
            case HASH:
                operator = Operator.HASH;
                break;
            case AND:
                operator = Operator.LAND;
                break;
            case OR:
                operator = Operator.LOR;
                break;
            case IMPLIES_ACSL:
                operator = Operator.IMPLIES;
                break;
            case LT:
                operator = Operator.LT;
                break;
            case LTE:
                operator = Operator.LTE;
                break;
            case SUB:
                operator = numArgs == 1 ? Operator.UNARYMINUS : Operator.MINUS;
                break;
            case MOD:
                operator = Operator.MOD;
                break;
            case NEQ:
                operator = Operator.NEQ;
                break;
            case NOT:
                operator = Operator.NOT;
                break;
            case PLUS:
                operator = numArgs == 1 ? Operator.UNARYPLUS : Operator.PLUS;
                break;
            case SHIFTLEFT:
                operator = Operator.SHIFTLEFT;
                break;
            case SHIFTRIGHT:
                operator = Operator.SHIFTRIGHT;
                break;
            case INDEX:
                operator = Operator.SUBSCRIPT;
                break;
            case XOR_ACSL:
                operator = Operator.LXOR;
                break;
            case BEQUIV_ACSL:
                operator = Operator.BITEQUIV;
                break;
            case BIMPLIES_ACSL:
                operator = Operator.BITIMPLIES;
                break;
            case EQUIV_ACSL:
                operator = Operator.LEQ; // TODO: Huh???? Do this right.
                break;
            default:
                throw error("Unknown operator : " + operatorTree.getText(),
                        operatorTree);
        }
        return nodeFactory.newOperatorNode(source, operator, arguments);
    }

    /**
     * tries to translate the given identifier node into an enumeration node
     * according to the scope. If the identifer's name has NOT been declared as
     * an enumeration constant in the scope, then return null.
     *
     * @param identifier
     *         the identifier node to be translated
     * @param scope
     *         the current scope
     * @return an enumeration constant node if the identifer's name has been
     * declared as an enumeration in the scope otherwise return null.
     */
    private EnumerationConstantNode translateEnumerationConstant(
            IdentifierNode identifier, SimpleScope scope) {
        String name = identifier.name();

        if (scope.isEnumerationConstant(name))
            return this.nodeFactory.newEnumerationConstantNode(identifier);
        return null;
    }

    private IdentifierNode translateIdentifier(CommonTree identifier) {
        Token idToken = identifier.getToken();
        CivlcToken token;
        Source source;

        if (idToken instanceof CivlcToken)
            token = (CivlcToken) idToken;
        else
            token = tokenFactory.newCivlcToken(idToken, formation,
                    TokenVocabulary.CIVLC);
        source = tokenFactory.newSource(token);
        return nodeFactory.newIdentifierNode(source, token.getText());
    }

    // ////////////////////////////////////

    private MPICollectiveBlockNode translateMPICollectiveBlock(Source source,
            CommonTree colBlock, SimpleScope scope) throws SyntaxException {
        CommonTree mpiComm = (CommonTree) colBlock.getChild(1);
        CommonTree kind = (CommonTree) colBlock.getChild(2);
        CommonTree body = (CommonTree) colBlock.getChild(3);
        List<ContractNode> bodyComponents = new LinkedList<>();
        SequenceNode<ContractNode> bodyNode;
        ExpressionNode mpiCommNode;
        MPICommunicatorMode colKind;

        mpiCommNode = translateExpression(mpiComm, scope);
        // The mpi collective kind can only be :COL, P2P or BOTH
        switch (kind.getType()) {
            case AcslParser.COL:
                colKind = MPICommunicatorMode.COL;
                break;
            case AcslParser.P2P:
                colKind = MPICommunicatorMode.P2P;
                break;
            case AcslParser.BOTH:
                colKind = MPICommunicatorMode.BOTH;
                break;
            default:
                throw error("Unknown MPI collective kind", kind);
        }
        bodyComponents.addAll(translateFunctionContractBlock(body, scope));
        bodyNode = nodeFactory.newSequenceNode(source, "mpi_collective body",
                bodyComponents);
        return nodeFactory.newMPICollectiveBlockNode(source, mpiCommNode,
                colKind, bodyNode);
    }

    private MPIContractConstantNode translateMPIConstantNode(CommonTree tree,
            Source source) throws SyntaxException {
        CommonTree constantTree = (CommonTree) tree.getChild(0);
        MPIContractConstantNode result;

        switch (constantTree.getType()) {
            case AcslParser.MPI_COMM_RANK:
                result = nodeFactory.newMPIConstantNode(source, MPI_COMM_RANK,
                        MPIConstantKind.MPI_COMM_RANK, ConstantKind.INT);
                break;
            case AcslParser.MPI_COMM_SIZE:
                result = nodeFactory.newMPIConstantNode(source, MPI_COMM_SIZE,
                        MPIConstantKind.MPI_COMM_SIZE, ConstantKind.INT);
                break;
            default:
                throw error("Unknown MPI Constant", tree);
        }
        result.setInitialType(typeFactory.signedIntegerType(SignedIntKind.INT));
        return result;
    }

    private MPIContractExpressionNode translateMPIExpressionNode(
            CommonTree expressionTree, Source source, SimpleScope scope)
            throws SyntaxException {
        CommonTree expression = (CommonTree) expressionTree.getChild(0);
        int kind = expression.getType();
        List<ASTNode> args = new LinkedList<>();
        String exprName = expression.getText();
        MPIContractExpressionKind mpiExprKind;
        MPIContractExpressionNode result;
        Type initialType;
        int numChildren = expression.getChildCount();

        switch (kind) {
            case AcslParser.MPI_AGREE:
                mpiExprKind = MPIContractExpressionKind.MPI_AGREE;
                initialType = typeFactory
                        .unsignedIntegerType(UnsignedIntKind.BOOL);
                break;
            case AcslParser.MPI_EMPTY_IN:
                mpiExprKind = MPIContractExpressionKind.MPI_EMPTY_IN;
                initialType = typeFactory
                        .unsignedIntegerType(UnsignedIntKind.BOOL);
                break;
            case AcslParser.MPI_EMPTY_OUT:
                mpiExprKind = MPIContractExpressionKind.MPI_EMPTY_OUT;
                initialType = typeFactory
                        .unsignedIntegerType(UnsignedIntKind.BOOL);
                break;
            case AcslParser.MPI_EQUALS:
                mpiExprKind = MPIContractExpressionKind.MPI_EQUALS;
                initialType = typeFactory
                        .unsignedIntegerType(UnsignedIntKind.BOOL);
                break;
            case AcslParser.MPI_EXTENT:
                mpiExprKind = MPIContractExpressionKind.MPI_EXTENT;
                initialType = typeFactory
                        .unsignedIntegerType(UnsignedIntKind.UNSIGNED);
                break;
            case AcslParser.MPI_REGION:
                mpiExprKind = MPIContractExpressionKind.MPI_REGION;
                initialType = typeFactory.pointerType(typeFactory.voidType());
                break;
            case AcslParser.MPI_OFFSET:
                mpiExprKind = MPIContractExpressionKind.MPI_OFFSET;
                initialType = typeFactory.pointerType(typeFactory.voidType());
                break;
            case AcslParser.MPI_VALID:
                mpiExprKind = MPIContractExpressionKind.MPI_VALID;
                initialType = typeFactory
                        .unsignedIntegerType(UnsignedIntKind.BOOL);
                break;
            case AcslParser.MPI_ABSENT:
                return translateMPIAbsentExpressionNode(expression, source, scope);
            default:
                throw error("Unknown MPI expression " + exprName,
                        expressionTree);
        }
        for (int i = 1; i < numChildren; i++) {
            ExpressionNode child = translateExpression(
                    (CommonTree) expression.getChild(i), scope);

            args.add(child);
        }
        result = nodeFactory.newMPIExpressionNode(source, args, mpiExprKind,
                exprName);
        result.setInitialType(initialType);
        return result;
    }

    /**
     * <p>translates the parse tree of MPI_ABSENT to {@link MPIContractAbsentNode}</p>
     *
     * @param expr
     *         a parse tree representing an MPI_ABSENT expression
     * @param source
     *         the {@link Source} of the parse tree
     * @param scope
     *         the scope where the parsed expression belongs to
     * @return the translated {@link MPIContractAbsentNode}, which is a sub-class
     * of {@link ExpressionNode}.
     */
    private MPIContractExpressionNode translateMPIAbsentExpressionNode(CommonTree expr,
            Source source, SimpleScope scope) throws SyntaxException {
        CommonTree absentEventTree = (CommonTree) expr.getChild(0);
        CommonTree fromEventTree = (CommonTree) expr.getChild(1);
        CommonTree untilEventTree = (CommonTree) expr.getChild(2);
        MPIContractAbsentEventNode absentEvent = translateMPIAbsentEventNode(
                absentEventTree, scope);
        MPIContractAbsentEventNode fromEvent = translateMPIAbsentEventNode(
                fromEventTree, scope);
        MPIContractAbsentEventNode untilEvent = translateMPIAbsentEventNode(
                untilEventTree, scope);
        List<ASTNode> events = new LinkedList<>();

        events.add(absentEvent);
        events.add(fromEvent);
        events.add(untilEvent);
        return nodeFactory.newMPIExpressionNode(source, events,
                MPIContractExpressionKind.MPI_ABSENT, expr.getText());
    }

    /**
     * <p>translates an MPI absent event parse tree to a
     * {@link MPIContractAbsentEventNode}</p>
     *
     * @throws SyntaxException
     */
    private MPIContractAbsentEventNode translateMPIAbsentEventNode(CommonTree
            eventTree, SimpleScope scope) throws SyntaxException {
        Source source;

        if (eventTree.getTokenStartIndex() < 0)
            source = newSource(eventTree.parent);
        else
            source = newSource(eventTree);

        List<ExpressionNode> args = new LinkedList<>();
        MPIAbsentEventKind kind;
        int type = eventTree.getType();

        switch (type) {
            case ABSENT_EVENT_SENDTO:
            case ABSENT_EVENT_SENDFROM: {
                CommonTree destOrSrcTree = (CommonTree) eventTree.getChild(0);
                CommonTree tagTree = (CommonTree) eventTree.getChild(1);

                args.add(translateExpression(destOrSrcTree, scope));
                args.add(translateExpression(tagTree, scope));
                kind = type == ABSENT_EVENT_SENDTO ? SENDTO : SENDFROM;
                return nodeFactory.newMPIAbsentEventNode(source, args, kind);
            }
            case ABSENT_EVENT_ENTER:
            case ABSENT_EVENT_EXIT: {
                CommonTree argTree = (CommonTree) eventTree.getChild(0);

                if (argTree.getType() != ABSENT)
                    args.add(translateExpression(argTree, scope));
                kind = type == ABSENT_EVENT_ENTER ? ENTER : EXIT;
                return nodeFactory.newMPIAbsentEventNode(source, args, kind);
            }
            default:
                throw new ABCRuntimeException("unexpected parse tree type");
        }
    }

    private SyntaxException error(String message, CommonTree tree) {
        return new SyntaxException(message, newSource(tree));
    }

    private Source newSource(CommonTree tree) {
        Source result = parseTree.source(tree);

        return result;
    }

}