Micro Compiler Portfolio
Total Page:16
File Type:pdf, Size:1020Kb
Montana State University Micro Compiler Portfolio Matt Johnerson Michael Shihrer CSCI 468 Compilers 1 Program 2 Expression.java 2 IRNode.java 2 Listener.java 4 Main.java 10 Micro.java 11 Micro.g4 12 Scope.java 14 Symbol.java 16 SymbolTable.java 17 TinyGenerator.java 19 Teamwork 22 Design Pattern 23 Technical Writing 23 UML Diagram 24 Design TradeOffs 24 Software Development Life Cycle 25 2 1. Program The program’s source code and final submission is located on github. It can be viewed at https://github.com/shihrer/csci468 under the release tagged “Step4”. In order to build and execute the code, the ANTLR v4.5.2 runtime is needed. This can be located at http://www.antlr.org/. a. Expression.java package com.csci468.micro; class Expression { private String name; private String type; Expression(String name, String type) { this.name = name; this.type = type; } String getType() { return this.type; } String getName() { return this.name; } @Override public String toString() { return this.name; } } b. IRNode.java package com.csci468.micro; class IRNode { //Data fields private String _opcode; private Expression _operand1; private Expression _operand2; private Expression _result; IRNode(String OPCode, Expression OP1, Expression OP2, Expression Result) { if (OP1 != null && !OPCode.equals("STR")) { switch (OP1.getType()) { case "INT": this._opcode = OPCode + "I"; 3 break; case "FLOAT": this._opcode = OPCode + "R"; break; default: this._opcode = OPCode + "S"; break; } } else { this._opcode = OPCode; } this._operand1 = OP1; this._operand2 = OP2; this._result = Result; } String getIRCode() { StringBuilder irCode = new StringBuilder(); irCode.append("; "); irCode.append(_opcode).append(" "); if (_operand1 != null) irCode.append(_operand1).append(" "); if (_operand2 != null) irCode.append(_operand2).append(" "); if (_result != null) irCode.append(_result).append(" "); return irCode.toString(); } String getOpcode() { return _opcode; } Expression getOP1() { return _operand1; } Expression getOP2() { return _operand2; } Expression getResult() { return _result; } @Override public String toString() { return getIRCode(); } 4 } c. Listener.java package com.csci468.micro; import java.util.LinkedList; import java.util.Stack; /** * Michael Shihrer * Matthew Johnerson * 26 March 2016 */ class Listener extends MicroBaseListener { // Count variables private int scopeCount = 1; private int labelCount = 0; private int variableCount = 0; private SymbolTable microSymbolTable; // Code generation objects private LinkedList<IRNode> IRNodes; private Stack<Integer> labelStack; private Stack<Expression> expressionStack = new Stack<>(); private Stack<Stack<Expression>> stackStack = new Stack<>(); // Constructor requires IRNodes list Listener(LinkedList<IRNode> IRNodes) { microSymbolTable = new SymbolTable(); this.IRNodes = IRNodes; this.labelStack = new Stack<>(); } @Override public void enterFuncDecl(MicroParser.FuncDeclContext ctx) { //Create new scope microSymbolTable.createScope(ctx.ID().toString()); Expression result = new Expression(ctx.ID().getText(), "STR"); IRNodes.add(new IRNode("LABEL", null, null, result)); } @Override public void exitFuncDecl(MicroParser.FuncDeclContext ctx) { //Pop scope destroyScope(); } 5 @Override public void exitVarDecl(MicroParser.VarDeclContext ctx) { String ids = ctx.idList().getText(); for (String id : ids.split(",")) { Expression result = new Expression(id, ctx.varType().toString()); IRNodes.add(new IRNode("VAR", null, null, result)); } } @Override public void enterParamDecl(MicroParser.ParamDeclContext ctx) { //Add parameter to scope microSymbolTable.createSymbol(ctx.ID().toString(), ctx.varType().getText()); } @Override public void enterIfStmt(MicroParser.IfStmtContext ctx) { createBlockScope(); } @Override public void exitIfStmt(MicroParser.IfStmtContext ctx) { int curLabel = labelStack.pop(); Expression result = new Expression("label" + curLabel, "STR"); IRNodes.add(new IRNode("LABEL", null, null, result)); destroyScope(); } @Override public void enterWhileStmt(MicroParser.WhileStmtContext ctx) { Expression result = new Expression("label" + labelCount, "STR"); IRNodes.add(new IRNode("LABEL", null, null, result)); labelStack.push(labelCount); labelCount++; createBlockScope(); } @Override public void exitWhileStmt(MicroParser.WhileStmtContext ctx) { int curLabel = labelStack.pop(); int jumpLabel = labelStack.pop(); Expression jumpResult = new Expression("label" + jumpLabel, "STR"); Expression labelResult = new Expression("label" + curLabel, "STR"); IRNodes.add(new IRNode("JUMP", null, null, jumpResult)); IRNodes.add(new IRNode("LABEL", null, null, labelResult)); } 6 @Override public void enterElse(MicroParser.ElseContext ctx) { createBlockScope(); int curLabel = labelStack.pop(); Expression jumpResult = new Expression("label" + labelCount, "STR"); Expression labelResult = new Expression("label" + curLabel, "STR"); IRNodes.add(new IRNode("JUMP", null, null, jumpResult)); IRNodes.add(new IRNode("LABEL", null, null, labelResult)); labelStack.push(labelCount); labelCount++; } @Override public void exitElse(MicroParser.ElseContext ctx) { destroyScope(); } @Override public void exitReadStmt(MicroParser.ReadStmtContext ctx) { String ids = ctx.idList().getText(); for (String id : ids.split(",")) { Expression readResult = new Expression(id, microSymbolTable.getSymbol(id).getType()); IRNodes.add(new IRNode("READ", readResult, null, null)); } } private void createBlockScope() { //Create new scope microSymbolTable.createScope(scopeCount); scopeCount++; } private Scope destroyScope() { return microSymbolTable.destroyScope(); } @Override public void enterStringDecl(MicroParser.StringDeclContext ctx) { //Create an entry in the current scope String name = ctx.ID().toString(); String value = ctx.STRINGLITERAL().toString(); String type = ctx.STRING().toString(); microSymbolTable.createSymbol(name, type, value); } @Override 7 public void enterVarDecl(MicroParser.VarDeclContext ctx) { String varType = ctx.varType().getText(); // Create an entry in the current scope String names = ctx.idList().getText(); String[] tokens = names.split(","); for (String s : tokens) { microSymbolTable.createSymbol(s, varType); } } @Override public void exitAssignExpr(MicroParser.AssignExprContext ctx) { //Clear out expression stack, just make sure there's nothing extra to evaluate. while (expressionStack.size() > 1) { buildExpression(); } String OPCode = "STORE"; String ID = ctx.ID().toString(); Expression storeResult = new Expression(ID, microSymbolTable.getSymbol(ID).getType()); // Avoid popping if the stack is empty if (expressionStack.size() > 0) { Expression OP1 = expressionStack.pop(); IRNodes.add(new IRNode(OPCode, OP1, null, storeResult)); } } @Override public void exitCond(MicroParser.CondContext ctx) { //Compare the results of the expressions Expression op1; Expression op2; if (expressionStack.size() > 1) { op1 = expressionStack.pop(); op2 = expressionStack.pop(); Expression compareResult = new Expression("label" + labelCount, "STR"); StringBuilder OPCode = new StringBuilder(); switch (ctx.COMPOP().toString()) { case ">": OPCode.append("LE"); break; case ">=": OPCode.append("LT"); 8 break; case "<": OPCode.append("GE"); break; case "<=": OPCode.append("GT"); break; case "!=": OPCode.append("EQ"); break; case "=": OPCode.append("NE"); break; } IRNodes.add(new