Package pascalcompiler.codegenerator

Source Code of pascalcompiler.codegenerator.CodeGenerator

package pascalcompiler.codegenerator;



import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import pascalcompiler.parser.IdInformation;
import pascalcompiler.parser.SymbolTable;
import pascalcompiler.scanner.PascalToken;
import pascalcompiler.syntaxtree.*;

/**
* This class creates the MIPS code based off of the Pascal syntax tree that
* is passed to it.
* @author Travis
*/
public class CodeGenerator {
   
    private int currentTRegister = 0;
    private int currentSRegister = 0;
    private int ifNumber = 1;
    private int whileNumber = 1;
    private SymbolTable table;
   
    /**
     * Starts the code from the root node by writing the outline of the
     * assembly code, and telling the root node to write its answer into $s0.
     *
     * @param root The root node of the equation to be written
     * @param idTable
     * @return A String of the assembly code.
     */  
    public String writeCodeForRoot( ProgramNode root, SymbolTable idTable) {
        String a = null;
        String result = "";
        table = idTable;
        StringBuilder code = new StringBuilder();
        IdInformation element;
        result += String.format("%-20s%s", "newLine"+":", ".asciiz  \"\\n\"\n");
        Enumeration e = idTable.getTable().elements();
        //Writes global variables to .data section (all variables are global)
        while (e.hasMoreElements()) {
            element = (IdInformation)e.nextElement();
            if (element.getKind() == PascalToken.VAR) {
                result += String.format("%-20s%s", element.getName()+":", ".word    0\n");
            }
        }
        code.append("#Program Name: " + root.getName() + "\n");
        code.append(".data \n");
        code.append(result);
        code.append("\n\n");
        code.append(".text\nmain:\n");
        code.append(writeCode(root.getCompoundStatement()));
        code.append( "li     $v0,   10\n");
        code.append( "syscall\n");
        code.append("\n\n#SubProgram Declarations\n");
        code.append(writeCode(root.getSubDeclarations()));
        return (code.toString());
    }
   
    /**
     * Generates the MIPS assembly code for all the sub programs defined in a
     * Pascal program.
     * @param subPrograms
     * @return
     */
    public String writeCode(SubProgramDeclarationsNode subPrograms) {
        String code = "";
        SubProgramNode currentProgram = null;
        ArrayList<SubProgramNode> list = subPrograms.getSubPrograms();
        Iterator<SubProgramNode> i = list.iterator();
        while (i.hasNext()) {
            currentProgram = i.next();
            code += writeCode(currentProgram);
        }
        return code;
    }
   
    /**
     * Generates the MIPS assembly code for a specified sub program.
     * @param subProgram
     * @return
     */
    public String writeCode(SubProgramNode subProgram) {
        String code = null;
        if (subProgram instanceof FunctionDeclarationNode) {
            code = writeCode((FunctionDeclarationNode)subProgram);
        }
        else if (subProgram instanceof ProcedureDeclarationNode) {
            code = writeCode((ProcedureDeclarationNode)subProgram);
        }
        return code;
    }
     
    /**
     * Generates the MIPS assembly code for a procedure defined in Pascal.
     * @param procedure
     * @return
     */
    public String writeCode(ProcedureDeclarationNode procedure) {
        String code = procedure.getName() + ":\n";
        code += "addi   $sp,   $sp,   -4\n";
        code += "sw     $ra,   0($sp)\n";
        ArrayList<VariableNode> list = (procedure.getArguments()).getArguments();
        int aRegister = 0;
        String aReg = "$a";
        String aTemp;
        String currentVar;
        Iterator i = list.iterator();
        while (i.hasNext()) {
            currentVar = ((VariableNode)i.next()).getName();
            code += "sw     " + aReg + aRegister++ + ",   " + currentVar + "\n";
        }
        code += writeCode(procedure.getCompoundStatement());
        code += "lw     $ra,   0($sp)\n";
        code += "addi   $sp,   $sp,   4\n";
        code += "jr     $ra\n\n";
        return code;
    }
   
    /**
     * Generates the MIPS assembly code for the variables declared in a Pascal
     * program.
     * @param node
     * @return
     */
    public String writeCode(DeclarationsNode node) {
        String code = "";
        ArrayList<VariableNode> declarations = null;
        VariableNode tempVar = null;
        declarations = node.getDeclarations();
        Iterator<VariableNode> variableIterator = declarations.iterator();
        while (variableIterator.hasNext()) {
            tempVar = variableIterator.next();
            if(tempVar.getType() == PascalToken.INTEGER) {
                code += tempVar.getName() + ":";
                code += " .word  0 \n";
            }
            else if (tempVar.getType() == PascalToken.REAL) {
                code += "\n";
            }
        }
        return code;
    }
   
    /**
     * Determines the instance of the statement node and then writes MIPS code
     * for that particular instance.
     * @param node
     * @return
     */
    public String writeCode(StatementNode node) {
        String code = "";
        if(node instanceof VarAssignStatement) {
            VarAssignStatement statement = (VarAssignStatement)node;
            if (statement.isVariable(table)) {
                code += writeCode((VarAssignStatement)node, "$s0");
            }
            else if (statement.isFunction(table)) {
                code += writeCode((VarAssignStatement)node, "$v0");
            }              
        }
        else if (node instanceof CompoundStatementNode) {
                code += writeCode((CompoundStatementNode)node);
        }
        else if (node instanceof ProcedureStatement) {
                code += writeCode((ProcedureStatement)node);
        }
        else if (node instanceof IfStatement) {
                code += writeCode((IfStatement)node);
        }
        else if (node instanceof WhileStatement) {
                code += writeCode((WhileStatement)node);
        }
        else if (node instanceof WriteStatementNode) {
                code += writeCode((WriteStatementNode)node);
        }
        return code;
    }
   
    /**
     * Generates MIPS assembly code for a block of statements.
     * @param node
     * @return
     */
    public String writeCode(CompoundStatementNode node) {
        String code = "";
        ArrayList<StatementNode> statements = null;
        StatementNode tempStatement = null;
        statements = node.getStatements();
        Iterator<StatementNode> variableIterator = statements.iterator();
        int tempTreg = this.currentTRegister;
        while (variableIterator.hasNext()) {
            tempStatement = variableIterator.next();
            code += writeCode(tempStatement);
            this.currentTRegister = tempTreg;
        }// end while
        return code;
    }
   
    /**
     * Generates MIPS assembly code, so the result of a mathematical expression
     * is printed to the screen.
     * @param statement
     * @return
     */
    public String writeCode(WriteStatementNode statement) {
        String answer = "";
        answer += writeCode(statement.getExpression(),"$a0");
        answer += "addi   $v0,   $zero,   1\n";
        answer += "syscall\n";
        answer += "li    $v0,   4\n";
        answer += "la    $a0,   newLine\n";
        answer += "syscall\n";
        return answer;
    }
   
    /**
     * Generates MIPS assembly code for a while statement.
     * @param statement
     * @return
     */
    public String writeCode(WhileStatement statement) {
        String code = "\n", tReg1 = "$t", tReg2 = "$t";
        String beginWhile = "BeginWhile" + this.whileNumber;
        String endWhile = "EndWhile" + this.whileNumber++;
        code += beginWhile + ":\n";
        EquationNode expression = statement.getExpression();
        if (expression instanceof OperationNode) {
            PascalToken relop = ((OperationNode)expression).getOperation();
            if (isRelationalOperator(relop)){
                EquationNode left = ((OperationNode)expression).getLeft();
                EquationNode right = ((OperationNode)expression).getRight();
                int temp = this.currentTRegister;
                tReg1 += this.currentTRegister++;
                tReg2 += this.currentTRegister++;
                this.currentTRegister = temp;
                code += writeCode(left, tReg1);
                code += writeCode(right, tReg2);
                if( relop == PascalToken.LESS_THAN) {
                    code += "slt    " + tReg1 + ",   " + tReg1 + ",   " + tReg2 + "\n";
                    code += "beq    " + tReg1 + ",   " + "$zero" + ",  " + endWhile + "\n";
                }
                else if( relop == PascalToken.GREATER_THAN) {
                    code += "slt    " + tReg1 + ",   " + tReg2 + ",   " + tReg1 + "\n";
                    code += "beq    " + tReg1 + ",   " + "$zero" + ",  " + endWhile + "\n";
                }
                else if ( relop == PascalToken.LESS_THAN_EQUAL) {
                    code += "addi   " + tReg2 + ",   " + "1\n";
                    code += "slt    " + tReg1 + ",   " + tReg1 + ",   " + tReg2 + "\n";
                    code += "beq    " + tReg1 + ",   " + "$zero" + ",  " + endWhile + "\n";
                }
                else if ( relop == PascalToken.GREATER_THAN_EQUAL) {
                    code += "addi   " + tReg1 + ",   " + "1\n";
                    code += "slt    " + tReg1 + ",   " + tReg2 + ",   " + tReg1 + "\n";
                    code += "beq    " + tReg1 + ",   " + "$zero" + ",  " + endWhile + "\n";
                }
                else if ( relop == PascalToken.EQUALS) {
                    code += "bne    " + tReg1 + ",   " + tReg2 + ",  " + endWhile + "\n";
                }
                else if ( relop == PascalToken.NOT_EQUAL) {
                    code += "beq    " + tReg1 + ",   " + tReg2 + ",  " + endWhile + "\n";
                }
            }
            else if (isArithmeticOperator(relop)) {
                tReg1 += this.currentTRegister;
                code += writeCode(expression, tReg1);
                code += "beq  " + tReg1 + ",   " + "$zero" + ",  " + endWhile + "\n";
            }
        }
        StatementNode thenStatement = statement.getStatement();
        if (thenStatement != null) {
                code += writeCode(statement.getStatement());
        }
        code += "j      " + beginWhile + "\n";
        // Printing exit if statement
        code += endWhile + ":\n";
        return code;
    }
   
    /**
     * Generates MIPS assembly code for an IfStatement.
     * @param statement
     * @return
     */
    public String writeCode(IfStatement statement) {
        String code = "\n", tReg1 = "$t", tReg2 = "$t";
        String ifElse = "Else" + this.ifNumber;
        String ifExit = "Exit" + this.ifNumber++;
        EquationNode expression = statement.getExpression();
        if (expression instanceof OperationNode) {
            PascalToken relop = ((OperationNode)expression).getOperation();
            if (isRelationalOperator(relop)){
                EquationNode left = ((OperationNode)expression).getLeft();
                EquationNode right = ((OperationNode)expression).getRight();
                int temp = this.currentTRegister;
                tReg1 += this.currentTRegister++;
                tReg2 += this.currentTRegister++;
                this.currentTRegister = temp;
                code += writeCode(left, tReg1);
                code += writeCode(right, tReg2);
                if( relop == PascalToken.LESS_THAN) {
                    code += "slt    " + tReg1 + ",   " + tReg1 + ",   " + tReg2 + "\n";
                    code += "beq    " + tReg1 + ",   " + "$zero" + ",  " + ifElse + "\n";
                }
                else if( relop == PascalToken.GREATER_THAN) {
                    code += "slt    " + tReg1 + ",   " + tReg2 + ",   " + tReg1 + "\n";
                    code += "beq    " + tReg1 + ",   " + "$zero" + ",  " + ifElse + "\n";
                }
                else if ( relop == PascalToken.LESS_THAN_EQUAL) {
                    code += "addi   " + tReg2 + ",   " + "1\n";
                    code += "slt    " + tReg1 + ",   " + tReg1 + ",   " + tReg2 + "\n";
                    code += "beq    " + tReg1 + ",   " + "$zero" + ",  " + ifElse + "\n";
                }
                else if ( relop == PascalToken.GREATER_THAN_EQUAL) {
                    code += "addi   " + tReg1 + ",   " + "1\n";
                    code += "slt    " + tReg1 + ",   " + tReg2 + ",   " + tReg1 + "\n";
                    code += "beq    " + tReg1 + ",   " + "$zero" + ",  " + ifElse + "\n";
                }
                else if ( relop == PascalToken.EQUALS) {
                    code += "bne    " + tReg1 + ",   " + tReg2 + ",  " + ifElse + "\n";
                }
                else if ( relop == PascalToken.NOT_EQUAL) {
                    code += "beq    " + tReg1 + ",   " + tReg2 + ",  " + ifElse + "\n";
                }
            }
            else if (isArithmeticOperator(relop)) {
                tReg1 += this.currentTRegister;
                code += writeCode(expression, tReg1);
                code += "beq  " + tReg1 + ",   " + "$zero" + ",  " + ifElse + "\n";
            }
        }
        //Otherwise expression is a value node (so far), could be an array or function
        else if (expression instanceof ValueNode) {
            tReg1 += this.currentTRegister;
            code += writeCode(expression, tReg1);
            code += "beq    " + tReg1 + ",   " + "$zero" + ",  " + ifElse + "\n";
        }
        // end of ifExpression to MIPS
        // Printing then statement
        StatementNode thenStatement = statement.getThenStatement();
        if (thenStatement != null) {
                code += writeCode(statement.getThenStatement());
        }
        code += "j      " + ifExit + "\n";
        code += ifElse + ":\n";
        // Printing else statement
        StatementNode elseStatement = statement.getElseStatement();
        if (elseStatement != null) {
            code += writeCode(statement.getElseStatement());
        }
        // Printing exit if statement
        code += ifExit + ":\n";
        return (code += "\n");
    }
   
    /**
     * Generates MIPS assembly code for a variable assignment statement.
     * @param statement
     * @param reg
     * @return
     */
    public String writeCode(VarAssignStatement statement, String reg) {
        String code = "";
        if (statement != null) {
            EquationNode equation = statement.getExpression();
            String varName = statement.getVarName();
            if (equation != null && varName != null) {
               code += writeCode(equation, reg);
               if (statement.isVariable(table)) {
                   code += "sw     $s0,   " + varName + "\n";
              
            }
        }       
        return code;
    }
   
    /**
     * Generates MIPS assembly code for a procedure statement.
     * @param statement
     * @return
     */
    public String writeCode(ProcedureStatement statement) {
        String code = "";
        int aRegister = 0;
        String aReg = "$a";
        String aTemp;
        ArrayList<EquationNode> parameterList = statement.getExpressions();
        Iterator i = parameterList.iterator();
        while (i.hasNext()) {
            aTemp = aReg + aRegister++;
            code += writeCode((EquationNode)i.next(),aTemp);
        }
       
        code += "jal    " + statement.getName() + "\n";
        return code;
    }
   
    /**
     * Generates MIPS assembly code for a mathematical expression.
     * @param node
     * @param reg
     * @return
     */
    public String writeCode( EquationNode node, String reg) {
        String nodeCode = null;
        if( node instanceof OperationNode) {
            nodeCode = writeCode( (OperationNode)node, reg);
        }
        else if( node instanceof ValueNode) {
            nodeCode = writeCode( (ValueNode)node, reg);
        }
        else if( node instanceof FunctionExpressionNode) {
            nodeCode = writeCode( (FunctionExpressionNode)node, reg);
        }
        return( nodeCode);
    }
   
    /**
     * Generates MIPS assembly code for a function call inside a statement.
     * @param function
     * @param reg The name of MIPS register
     * @return
     */
    public String writeCode(FunctionExpressionNode function, String reg) {
        String code = "";
        int aRegister = 0;
        String aReg = "$a";
        String aTemp;
        ArrayList<EquationNode> parameterList = function.getParameters();
        Iterator i = parameterList.iterator();
        while (i.hasNext()) {
            aTemp = aReg + aRegister++;
            code += writeCode((EquationNode)i.next(),aTemp);
        }
       
        code += "jal    " + function.getName() + "\n";
        code += "add    " + reg + ",   $v0,   $zero\n";
        return code;
    }
   
    /**
     * Generates MIPS assembly code for a function definition.
     * @param function
     * @return
     */
    public String writeCode(FunctionDeclarationNode function) {
        String code = function.getName() + ":\n";
        code += "addi   $sp,   $sp,   -4\n";
        code += "sw     $ra,   0($sp)\n";
        ArrayList<VariableNode> list = (function.getArguments()).getArguments();
        int aRegister = 0;
        String aReg = "$a";
        String aTemp;
        String currentVar;
        Iterator i = list.iterator();
        while (i.hasNext()) {
            currentVar = ((VariableNode)i.next()).getName();
            code += "sw     " + aReg + aRegister++ + ",   " + currentVar + "\n";
        }
        //Iterate through compound statement and write last expression in $v0
        code += writeCode(function.getCompoundStatement());
        code += "lw     $ra,   0($sp)\n";
        code += "addi   $sp,   $sp,   4\n";
        code += "jr     $ra\n\n";
        return code;
    }
   
    /**
     * Writes code for an operations node.
     * The code is written by gathering the child nodes' answers into
     * a pair of registers, and then executing the op on those registers,
     * placing the result in the given result register.
     * @param opNode The operation node to perform.
     * @param resultRegister The register in which to put the result.
     * @return The code which executes this operation.
     */
    public String writeCode( OperationNode opNode, String resultRegister)
    {
        String code;
        EquationNode left = opNode.getLeft();
        String leftRegister = "$t" + currentTRegister++;
        code = writeCode( left, leftRegister);
        EquationNode right = opNode.getRight();
        String rightRegister = "$t" + currentTRegister++;
        code += writeCode( right, rightRegister);
        PascalToken kindOfOp = opNode.getOperation();
        if( kindOfOp == PascalToken.PLUS)
        {
            // add resultregister, left, right
            code += "add    " + resultRegister + ",   " + leftRegister +
                    ",   " + rightRegister + "\n";
        }
        if( kindOfOp == PascalToken.MINUS)
        {
            // add resultregister, left, right
            code += "sub    " + resultRegister + ",   " + leftRegister +
                    ",   " + rightRegister + "\n";
        }
        if( kindOfOp == PascalToken.MULTIPLY)
        {
            code += "mult   " + leftRegister + ",   " + rightRegister + "\n";
            code += "mflo   " + resultRegister + "\n";
        }
        if( kindOfOp == PascalToken.DIVIDE)
        {
            code += "div    " + leftRegister + ",   " + rightRegister + "\n";
            code += "mflo   " + resultRegister + "\n";
        }
        if( kindOfOp == PascalToken.MOD)
        {
            code += "div    " + leftRegister + ",   " + rightRegister + "\n";
            code += "mfhi   " + resultRegister + "\n";
        }
        return( code);
    }
   
    /**
     * Writes code for a value node.
     * The code is written by executing an add immediate with the value
     * into the destination register.
     * Writes code that looks like  addi $reg, $zero, value
     * @param valNode The node containing the value.
     * @param resultRegister The register in which to put the value.
     * @return The code which executes this value node.
     */
    public String writeCode( ValueNode valNode, String resultRegister)
    {
        String code;
        String value = valNode.getAttribute();
        if (valNode.isID()) {
            code = "lw     " + resultRegister + ",   " + valNode.getAttribute() + "\n";
        }
        else {
            code = "addi   " + resultRegister + ",   $zero, " + value + "\n";
        }
        return( code);
    }
   
   
    /**
     * Returns true if the token is a relational operator.
     * @param token
     * @return
     */
    public boolean isRelationalOperator(PascalToken token) {
        boolean answer = false;
        if (token == PascalToken.EQUALS
                || token == PascalToken.NOT_EQUAL
                || token == PascalToken.GREATER_THAN
                || token == PascalToken.GREATER_THAN_EQUAL
                || token == PascalToken.LESS_THAN
                || token == PascalToken.LESS_THAN_EQUAL) {
            answer = true;
        }
        return answer;
    }
   
    /**
     * Returns true if the token is an arithmetic operator.
     * @param token
     * @return
     */
    public boolean isArithmeticOperator(PascalToken token) {
        boolean answer = false;
        if (token == PascalToken.PLUS
                || token == PascalToken.MINUS
                || token == PascalToken.MULTIPLY
                || token == PascalToken.DIVIDE) {
            answer = true;
        }
        return answer;
    }
}
TOP

Related Classes of pascalcompiler.codegenerator.CodeGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.