summaryrefslogtreecommitdiff
path: root/submit
diff options
context:
space:
mode:
authorLizzy Hunt <elizabeth.hunt@simponic.xyz>2023-04-10 09:17:11 -0600
committerLizzy Hunt <elizabeth.hunt@simponic.xyz>2023-04-10 09:17:11 -0600
commit5f28f80c4e25a56cd444914c2f0b3da5e7fdb088 (patch)
tree600ad8b1ec5aad5155baf8c0352281054a8e6366 /submit
downloadcminus-5f28f80c4e25a56cd444914c2f0b3da5e7fdb088.tar.gz
cminus-5f28f80c4e25a56cd444914c2f0b3da5e7fdb088.zip
Initial commit - building
Diffstat (limited to 'submit')
-rw-r--r--submit/ASTVisitor.java304
-rw-r--r--submit/MIPSResult.java61
-rw-r--r--submit/RegisterAllocator.java126
-rw-r--r--submit/SymbolInfo.java31
-rw-r--r--submit/SymbolTable.java63
-rw-r--r--submit/ast/AbstractNode.java15
-rw-r--r--submit/ast/Assignment.java33
-rw-r--r--submit/ast/AssignmentType.java35
-rw-r--r--submit/ast/BinaryOperator.java35
-rw-r--r--submit/ast/BinaryOperatorType.java37
-rw-r--r--submit/ast/BoolConstant.java27
-rw-r--r--submit/ast/Break.java18
-rw-r--r--submit/ast/Call.java37
-rw-r--r--submit/ast/CharConstant.java23
-rw-r--r--submit/ast/CompoundStatement.java30
-rw-r--r--submit/ast/Declaration.java13
-rw-r--r--submit/ast/Expression.java13
-rw-r--r--submit/ast/ExpressionStatement.java26
-rw-r--r--submit/ast/FunDeclaration.java46
-rw-r--r--submit/ast/If.java44
-rw-r--r--submit/ast/Mutable.java31
-rw-r--r--submit/ast/Node.java11
-rw-r--r--submit/ast/NumConstant.java23
-rw-r--r--submit/ast/Param.java43
-rw-r--r--submit/ast/ParenExpression.java26
-rw-r--r--submit/ast/Program.java36
-rw-r--r--submit/ast/Return.java31
-rw-r--r--submit/ast/Statement.java16
-rw-r--r--submit/ast/StringConstant.java23
-rw-r--r--submit/ast/UnaryOperator.java27
-rw-r--r--submit/ast/UnaryOperatorType.java35
-rw-r--r--submit/ast/VarDeclaration.java47
-rw-r--r--submit/ast/VarType.java35
-rw-r--r--submit/ast/While.java33
34 files changed, 1434 insertions, 0 deletions
diff --git a/submit/ASTVisitor.java b/submit/ASTVisitor.java
new file mode 100644
index 0000000..b8762b5
--- /dev/null
+++ b/submit/ASTVisitor.java
@@ -0,0 +1,304 @@
+package submit;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.antlr.v4.runtime.tree.TerminalNode;
+import parser.CminusBaseVisitor;
+import parser.CminusParser;
+import submit.ast.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+public class ASTVisitor extends CminusBaseVisitor<Node> {
+ private final Logger LOGGER;
+ private SymbolTable symbolTable;
+
+ public ASTVisitor(Logger LOGGER) {
+ this.LOGGER = LOGGER;
+ }
+
+ public SymbolTable getSymbolTable() {
+ return symbolTable;
+ }
+
+ private VarType getVarType(CminusParser.TypeSpecifierContext ctx) {
+ final String t = ctx.getText();
+ return (t.equals("int")) ? VarType.INT : (t.equals("bool")) ? VarType.BOOL : VarType.CHAR;
+ }
+
+ @Override
+ public Node visitProgram(CminusParser.ProgramContext ctx) {
+ symbolTable = new SymbolTable();
+ List<Declaration> decls = new ArrayList<>();
+ for (CminusParser.DeclarationContext d : ctx.declaration()) {
+ decls.add((Declaration) visitDeclaration(d));
+ }
+ return new Program(decls);
+ }
+
+ @Override
+ public Node visitVarDeclaration(CminusParser.VarDeclarationContext ctx) {
+ VarType type = getVarType(ctx.typeSpecifier());
+ List<String> ids = new ArrayList<>();
+ List<Integer> arraySizes = new ArrayList<>();
+ for (CminusParser.VarDeclIdContext v : ctx.varDeclId()) {
+ String id = v.ID().getText();
+ ids.add(id);
+ symbolTable.addSymbol(id, new SymbolInfo(id, type, false));
+ if (v.NUMCONST() != null) {
+ arraySizes.add(Integer.parseInt(v.NUMCONST().getText()));
+ } else {
+ arraySizes.add(-1);
+ }
+ }
+ final boolean isStatic = false;
+ return new VarDeclaration(type, ids, arraySizes, isStatic);
+ }
+
+ @Override
+ public Node visitFunDeclaration(CminusParser.FunDeclarationContext ctx) {
+ VarType returnType = null;
+ if (ctx.typeSpecifier() != null) {
+ returnType = getVarType(ctx.typeSpecifier());
+ }
+ String id = ctx.ID().getText();
+ List<Param> params = new ArrayList<>();
+ for (CminusParser.ParamContext p : ctx.param()) {
+ params.add((Param) visitParam(p));
+ }
+ Statement statement = (Statement) visitStatement(ctx.statement());
+ symbolTable.addSymbol(id, new SymbolInfo(id, returnType, true));
+ return new FunDeclaration(returnType, id, params, statement);
+ }
+
+ @Override
+ public Node visitParam(CminusParser.ParamContext ctx) {
+ VarType type = getVarType(ctx.typeSpecifier());
+ String id = ctx.paramId().ID().getText();
+ symbolTable.addSymbol(id, new SymbolInfo(id, type, false));
+ return new Param(type, id, ctx.paramId().children.size() > 1);
+ }
+
+ @Override
+ public Node visitCompoundStmt(CminusParser.CompoundStmtContext ctx) {
+ symbolTable = symbolTable.createChild();
+ List<Statement> statements = new ArrayList<>();
+ for (CminusParser.VarDeclarationContext d : ctx.varDeclaration()) {
+ statements.add((VarDeclaration) visitVarDeclaration(d));
+ }
+ for (CminusParser.StatementContext d : ctx.statement()) {
+ statements.add((Statement) visitStatement(d));
+ }
+ symbolTable = symbolTable.getParent();
+ return new CompoundStatement(statements);
+ }
+
+ @Override
+ public Node visitExpressionStmt(CminusParser.ExpressionStmtContext ctx) {
+ if (ctx.expression() == null) {
+ return Statement.empty();
+ }
+ return new ExpressionStatement((Expression) visitExpression(ctx.expression()));
+ }
+
+ @Override
+ public Node visitIfStmt(CminusParser.IfStmtContext ctx) {
+ Expression expression = (Expression) visitSimpleExpression(ctx.simpleExpression());
+ Statement trueStatement = (Statement) visitStatement(ctx.statement(0));
+ Statement falseStatement = null;
+ if (ctx.statement().size() > 1) {
+ falseStatement = (Statement) visitStatement(ctx.statement(1));
+ }
+ return new If(expression, trueStatement, falseStatement);
+ }
+
+ @Override
+ public Node visitWhileStmt(CminusParser.WhileStmtContext ctx) {
+ Expression expression = (Expression) visitSimpleExpression(ctx.simpleExpression());
+ Statement statement = (Statement) visitStatement(ctx.statement());
+ return new While(expression, statement);
+ }
+
+ @Override
+ public Node visitReturnStmt(CminusParser.ReturnStmtContext ctx) {
+ if (ctx.expression() != null) {
+ return new Return((Expression) visitExpression(ctx.expression()));
+ }
+ return new Return(null);
+ }
+
+ @Override
+ public Node visitBreakStmt(CminusParser.BreakStmtContext ctx) {
+ return new Break();
+ }
+
+ @Override
+ public Node visitExpression(CminusParser.ExpressionContext ctx) {
+ final Node ret;
+ CminusParser.MutableContext mutable = ctx.mutable();
+ CminusParser.ExpressionContext expression = ctx.expression();
+ if (mutable != null) {
+ // Assignment
+ ParseTree operator = ctx.getChild(1);
+ Mutable lhs = (Mutable) visitMutable(mutable);// new Mutable(mutable.ID().getText(), (Expression)
+ // visitExpression(mutable.expression()));
+ Expression rhs = null;
+ if (expression != null) {
+ rhs = (Expression) visitExpression(expression);
+ }
+ ret = new Assignment(lhs, operator.getText(), rhs);
+ } else {
+ ret = visitSimpleExpression(ctx.simpleExpression());
+ }
+ return ret;
+ }
+
+ @Override
+ public Node visitOrExpression(CminusParser.OrExpressionContext ctx) {
+ List<Node> ands = new ArrayList<>();
+ for (CminusParser.AndExpressionContext and : ctx.andExpression()) {
+ ands.add(visitAndExpression(and));
+ }
+ if (ands.size() == 1) {
+ return ands.get(0);
+ }
+ BinaryOperator op = new BinaryOperator((Expression) ands.get(0), "||", (Expression) ands.get(1));
+ for (int i = 2; i < ands.size(); ++i) {
+ op = new BinaryOperator(op, "||", (Expression) ands.get(i));
+ }
+ return op;
+ }
+
+ @Override
+ public Node visitAndExpression(CminusParser.AndExpressionContext ctx) {
+ List<Node> uns = new ArrayList<>();
+ for (CminusParser.UnaryRelExpressionContext un : ctx.unaryRelExpression()) {
+ uns.add(visitUnaryRelExpression(un));
+ }
+ if (uns.size() == 1) {
+ return uns.get(0);
+ }
+ BinaryOperator op = new BinaryOperator((Expression) uns.get(0), "&&", (Expression) uns.get(1));
+ for (int i = 2; i < uns.size(); ++i) {
+ op = new BinaryOperator(op, "&&", (Expression) uns.get(i));
+ }
+ return op;
+ }
+
+ @Override
+ public Node visitUnaryRelExpression(CminusParser.UnaryRelExpressionContext ctx) {
+ Expression e = (Expression) visitRelExpression(ctx.relExpression());
+ for (TerminalNode n : ctx.BANG()) {
+ e = new UnaryOperator("!", e);
+ }
+ return e;
+ }
+
+ @Override
+ public Node visitRelExpression(CminusParser.RelExpressionContext ctx) {
+ List<Node> uns = new ArrayList<>();
+ for (CminusParser.SumExpressionContext un : ctx.sumExpression()) {
+ uns.add(visitSumExpression(un));
+ }
+ if (uns.size() == 1) {
+ return uns.get(0);
+ }
+ BinaryOperator op = new BinaryOperator((Expression) uns.get(0), ctx.relop(0).getText(),
+ (Expression) uns.get(1));
+ for (int i = 2; i < uns.size(); ++i) {
+ op = new BinaryOperator(op, ctx.relop(i - 1).getText(), (Expression) uns.get(i));
+ }
+ return op;
+ }
+
+ @Override
+ public Node visitSumExpression(CminusParser.SumExpressionContext ctx) {
+ List<Node> es = new ArrayList<>();
+ for (CminusParser.TermExpressionContext e : ctx.termExpression()) {
+ es.add(visitTermExpression(e));
+ }
+ if (es.size() == 1) {
+ return es.get(0);
+ }
+ BinaryOperator op = new BinaryOperator((Expression) es.get(0), ctx.sumop(0).getText(), (Expression) es.get(1));
+ for (int i = 2; i < es.size(); ++i) {
+ op = new BinaryOperator(op, ctx.sumop(i - 1).getText(), (Expression) es.get(i));
+ }
+ return op;
+ }
+
+ @Override
+ public Node visitTermExpression(CminusParser.TermExpressionContext ctx) {
+ List<Node> es = new ArrayList<>();
+ for (CminusParser.UnaryExpressionContext e : ctx.unaryExpression()) {
+ es.add(visitUnaryExpression(e));
+ }
+ if (es.size() == 1) {
+ return es.get(0);
+ }
+ BinaryOperator op = new BinaryOperator((Expression) es.get(0), ctx.mulop(0).getText(), (Expression) es.get(1));
+ for (int i = 2; i < es.size(); ++i) {
+ op = new BinaryOperator(op, ctx.mulop(i - 1).getText(), (Expression) es.get(i));
+ }
+ return op;
+ }
+
+ @Override
+ public Node visitUnaryExpression(CminusParser.UnaryExpressionContext ctx) {
+ Node ret = visitFactor(ctx.factor());
+ for (int i = ctx.unaryop().size() - 1; i >= 0; i--) {
+ ret = new UnaryOperator(ctx.unaryop(i).getText(), (Expression) ret);
+ }
+ return ret;
+ }
+
+ @Override
+ public Node visitMutable(CminusParser.MutableContext ctx) {
+ Expression e = null;
+ if (ctx.expression() != null) {
+ e = (Expression) visitExpression(ctx.expression());
+ }
+ String id = ctx.ID().getText();
+ if (symbolTable.find(id) == null) {
+ LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() + ": " + id);
+ }
+ return new Mutable(id, e);
+ }
+
+ @Override
+ public Node visitImmutable(CminusParser.ImmutableContext ctx) {
+ if (ctx.expression() != null) {
+ return new ParenExpression((Expression) visitExpression(ctx.expression()));
+ }
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public Node visitCall(CminusParser.CallContext ctx) {
+ final String id = ctx.ID().getText();
+ final List<Expression> args = new ArrayList<>();
+ for (CminusParser.ExpressionContext e : ctx.expression()) {
+ args.add((Expression) visitExpression(e));
+ }
+ if (symbolTable.find(id) == null) {
+ LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() + ": " + id);
+ }
+ return new Call(id, args);
+ }
+
+ @Override
+ public Node visitConstant(CminusParser.ConstantContext ctx) {
+ final Node node;
+ if (ctx.NUMCONST() != null) {
+ node = new NumConstant(Integer.parseInt(ctx.NUMCONST().getText()));
+ } else if (ctx.CHARCONST() != null) {
+ node = new CharConstant(ctx.CHARCONST().getText().charAt(0));
+ } else if (ctx.STRINGCONST() != null) {
+ node = new StringConstant(ctx.STRINGCONST().getText());
+ } else {
+ node = new BoolConstant(ctx.getText().equals("true"));
+ }
+ return node;
+ }
+}
diff --git a/submit/MIPSResult.java b/submit/MIPSResult.java
new file mode 100644
index 0000000..212719e
--- /dev/null
+++ b/submit/MIPSResult.java
@@ -0,0 +1,61 @@
+/*
+ */
+package submit;
+
+import submit.ast.VarType;
+
+/**
+ * This class represents the result of generating MIPS code. There are various
+ * forms this result can take: 1) void, for cases where the calling node doesn't
+ * need any information returned, such as a return statement. 2) register, for
+ * cases where the called node needs to inform the calling node what register a
+ * result is placed in, such as BinaryOperator. 3) address, for cases where the
+ * returning result is in memory, such as StringConstant.
+ *
+ * To instantiate a MIPSResult object use the factory methods create...().
+ *
+ */
+public class MIPSResult {
+
+ private final String register;
+ private final String address;
+ private final VarType type;
+
+ public static MIPSResult createVoidResult() {
+ return new MIPSResult(null, null, null);
+ }
+
+ public static MIPSResult createRegisterResult(String register, VarType type) {
+ return new MIPSResult(register, null, type);
+ }
+
+ public static MIPSResult createAddressResult(String address, VarType type) {
+ return new MIPSResult(null, address, type);
+ }
+
+ private MIPSResult(String register, String address, VarType type) {
+ this.register = register;
+ this.address = address;
+ this.type = type;
+ }
+
+ /**
+ * Anytime you get a register from a result you should seriously consider
+ * calling regAllocator.clear(reg) after using the register to minimize
+ * register usage.
+ *
+ * @return
+ */
+ public String getRegister() {
+ return register;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public VarType getType() {
+ return type;
+ }
+
+}
diff --git a/submit/RegisterAllocator.java b/submit/RegisterAllocator.java
new file mode 100644
index 0000000..ce18b2b
--- /dev/null
+++ b/submit/RegisterAllocator.java
@@ -0,0 +1,126 @@
+/*
+ */
+package submit;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ *
+ *
+ */
+public final class RegisterAllocator {
+
+ // True if t is used
+ private final boolean[] t = new boolean[10];
+ private final boolean[] s = new boolean[8];
+ private final Set<String> used = new HashSet<>();
+
+ public RegisterAllocator() {
+ clearAll();
+ }
+
+ public String getT() {
+ for (int i = 0; i < t.length; ++i) {
+ if (!t[i]) {
+ t[i] = true;
+ String str = "$t" + i;
+ used.add(str);
+ return str;
+ }
+ }
+ return null;
+ }
+
+// public String getS() {
+// for (int i = 0; i < s.length; ++i) {
+// if (!s[i]) {
+// s[i] = true;
+// String str = "$s" + i;
+// used.add(str);
+// return str;
+// }
+// }
+// return null;
+// }
+
+ // Returns the number of bytes used to save the registers
+ public int saveRestore(StringBuilder code, int baseOffset, boolean s_or_t, boolean save) {
+ boolean[] r = s;
+ String prefix = "$s";
+ if (!s_or_t) {
+ r = t;
+ prefix = "$t";
+ }
+ String instruction = "sw";
+ if (!save) {
+ instruction = "lw";
+ }
+ int offset = 0;
+ for (int i = 0; i < r.length; ++i) {
+ if (r[i]) {
+ offset -= 4;
+ String str = prefix + i;
+ code.append(instruction).append(" ").append(str).append(" ").append(offset-baseOffset).append("($sp)\n");
+ }
+ }
+ return -offset;
+ }
+
+// public int saveS(StringBuilder code, int baseOffset) {
+// return saveRestore(code, baseOffset, true, true);
+// }
+
+ public int saveT(StringBuilder code, int baseOffset) {
+ return saveRestore(code, baseOffset, false, true);
+ }
+
+// public int restoreS(StringBuilder code, int baseOffset) {
+// return saveRestore(code, baseOffset, true, false);
+// }
+
+ public int restoreT(StringBuilder code, int baseOffset) {
+ return saveRestore(code, baseOffset, false, false);
+ }
+
+ public List<String> getUsed() {
+ return new ArrayList<>(used);
+ }
+
+ /**
+ * Any time you call this method you should seriously consider adding a
+ * corresponding clear() call.
+ *
+ * @return
+ */
+ public String getAny() {
+// String availS = getS();
+// if (availS != null) {
+// return availS;
+// }
+ String t = getT();
+ if (t == null) {
+ throw new RuntimeException("Out of registers");
+ }
+ return t;
+ }
+
+ public void clear(String reg) {
+ if (reg.charAt(1) == 's') {
+ s[Integer.parseInt(reg.substring(2))] = false;
+ } else if (reg.charAt(1) == 't') {
+ t[Integer.parseInt(reg.substring(2))] = false;
+ } else {
+ throw new RuntimeException("Unexpected register in clear");
+ }
+ }
+
+ public void clearAll() {
+ Arrays.fill(t, false);
+ Arrays.fill(s, false);
+ }
+}
diff --git a/submit/SymbolInfo.java b/submit/SymbolInfo.java
new file mode 100644
index 0000000..19c3f9b
--- /dev/null
+++ b/submit/SymbolInfo.java
@@ -0,0 +1,31 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit;
+
+import submit.ast.VarType;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class SymbolInfo {
+
+ private final String id;
+ // In the case of a function, type is the return type
+ private final VarType type;
+ private final boolean function;
+
+ public SymbolInfo(String id, VarType type, boolean function) {
+ this.id = id;
+ this.type = type;
+ this.function = function;
+ }
+
+ @Override
+ public String toString() {
+ return "<" + id + ", " + type + '>';
+ }
+
+}
diff --git a/submit/SymbolTable.java b/submit/SymbolTable.java
new file mode 100644
index 0000000..7ca6b27
--- /dev/null
+++ b/submit/SymbolTable.java
@@ -0,0 +1,63 @@
+package submit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/*
+ * Code formatter project
+ * CS 4481
+ */
+/**
+ *
+ */
+public class SymbolTable {
+
+ private final HashMap<String, SymbolInfo> table;
+ private SymbolTable parent;
+ private final List<SymbolTable> children;
+
+ public SymbolTable() {
+ table = new HashMap<>();
+ parent = null;
+ children = new ArrayList<>();
+ }
+
+ public void addSymbol(String id, SymbolInfo symbol) {
+ table.put(id, symbol);
+ }
+
+ /**
+ * Returns null if no symbol with that id is in this symbol table or an
+ * ancestor table.
+ *
+ * @param id
+ * @return
+ */
+ public SymbolInfo find(String id) {
+ if (table.containsKey(id)) {
+ return table.get(id);
+ }
+ if (parent != null) {
+ return parent.find(id);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the new child.
+ *
+ * @return
+ */
+ public SymbolTable createChild() {
+ SymbolTable child = new SymbolTable();
+ children.add(child);
+ child.parent = this;
+ return child;
+ }
+
+ public SymbolTable getParent() {
+ return parent;
+ }
+
+}
diff --git a/submit/ast/AbstractNode.java b/submit/ast/AbstractNode.java
new file mode 100644
index 0000000..01719aa
--- /dev/null
+++ b/submit/ast/AbstractNode.java
@@ -0,0 +1,15 @@
+package submit.ast;
+
+import submit.MIPSResult;
+import submit.RegisterAllocator;
+import submit.SymbolTable;
+
+public class AbstractNode implements Node {
+ public void toCminus(StringBuilder sb, String prefix) {
+ }
+
+ public MIPSResult toMIPS(StringBuilder code, StringBuilder data, SymbolTable symbolTable,
+ RegisterAllocator regAllocator) {
+ return null;
+ }
+}
diff --git a/submit/ast/Assignment.java b/submit/ast/Assignment.java
new file mode 100644
index 0000000..1a5d172
--- /dev/null
+++ b/submit/ast/Assignment.java
@@ -0,0 +1,33 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class Assignment extends AbstractNode implements Expression {
+
+ private final Mutable mutable;
+ private final AssignmentType type;
+ private final Expression rhs;
+
+ public Assignment(Mutable mutable, String assign, Expression rhs) {
+ this.mutable = mutable;
+ this.type = AssignmentType.fromString(assign);
+ this.rhs = rhs;
+ }
+
+ public void toCminus(StringBuilder builder, final String prefix) {
+ mutable.toCminus(builder, prefix);
+ if (rhs != null) {
+ builder.append(" ").append(type.toString()).append(" ");
+ rhs.toCminus(builder, prefix);
+ } else {
+ builder.append(type.toString());
+ }
+ }
+
+}
diff --git a/submit/ast/AssignmentType.java b/submit/ast/AssignmentType.java
new file mode 100644
index 0000000..9dd2bdf
--- /dev/null
+++ b/submit/ast/AssignmentType.java
@@ -0,0 +1,35 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public enum AssignmentType {
+
+ EQUALS("="), PLUS("+="), MINUS("-="), TIMES("*="), DIVIDE("/="), INC("++"), DEC("--");
+
+ private final String value;
+
+ private AssignmentType(String value) {
+ this.value = value;
+ }
+
+ public static AssignmentType fromString(String s) {
+ for (AssignmentType at : AssignmentType.values()) {
+ if (at.value.equals(s)) {
+ return at;
+ }
+ }
+ throw new RuntimeException("Illegal string in AssignType.fromString()");
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+}
diff --git a/submit/ast/BinaryOperator.java b/submit/ast/BinaryOperator.java
new file mode 100644
index 0000000..d18766b
--- /dev/null
+++ b/submit/ast/BinaryOperator.java
@@ -0,0 +1,35 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class BinaryOperator extends AbstractNode implements Expression {
+
+ private final Expression lhs, rhs;
+ private final BinaryOperatorType type;
+
+ public BinaryOperator(Expression lhs, BinaryOperatorType type, Expression rhs) {
+ this.lhs = lhs;
+ this.type = type;
+ this.rhs = rhs;
+ }
+
+ public BinaryOperator(Expression lhs, String type, Expression rhs) {
+ this.lhs = lhs;
+ this.type = BinaryOperatorType.fromString(type);
+ this.rhs = rhs;
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ lhs.toCminus(builder, prefix);
+ builder.append(" ").append(type).append(" ");
+ rhs.toCminus(builder, prefix);
+ }
+
+}
diff --git a/submit/ast/BinaryOperatorType.java b/submit/ast/BinaryOperatorType.java
new file mode 100644
index 0000000..37235c8
--- /dev/null
+++ b/submit/ast/BinaryOperatorType.java
@@ -0,0 +1,37 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public enum BinaryOperatorType {
+
+ OR("||"), AND("&&"),
+ LE("<="), LT("<"), GT(">"), GE(">="), EQ("=="), NE("!="),
+ PLUS("+"), MINUS("-"), TIMES("*"), DIVIDE("/"), MOD("%");
+
+ private final String value;
+
+ private BinaryOperatorType(String value) {
+ this.value = value;
+ }
+
+ public static BinaryOperatorType fromString(String s) {
+ for (BinaryOperatorType at : BinaryOperatorType.values()) {
+ if (at.value.equals(s)) {
+ return at;
+ }
+ }
+ throw new RuntimeException("Illegal string in OperatorType.fromString(): " + s);
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+}
diff --git a/submit/ast/BoolConstant.java b/submit/ast/BoolConstant.java
new file mode 100644
index 0000000..4b0ad2c
--- /dev/null
+++ b/submit/ast/BoolConstant.java
@@ -0,0 +1,27 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class BoolConstant extends AbstractNode implements Expression {
+
+ private final boolean value;
+
+ public BoolConstant(boolean value) {
+ this.value = value;
+ }
+
+ public void toCminus(StringBuilder builder, final String prefix) {
+ if (value) {
+ builder.append("true");
+ } else {
+ builder.append("false");
+ }
+ }
+
+}
diff --git a/submit/ast/Break.java b/submit/ast/Break.java
new file mode 100644
index 0000000..e3f28bc
--- /dev/null
+++ b/submit/ast/Break.java
@@ -0,0 +1,18 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class Break extends AbstractNode implements Statement {
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append(prefix).append("break;\n");
+ }
+
+}
diff --git a/submit/ast/Call.java b/submit/ast/Call.java
new file mode 100644
index 0000000..b6e61ba
--- /dev/null
+++ b/submit/ast/Call.java
@@ -0,0 +1,37 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class Call extends AbstractNode implements Expression {
+
+ private final String id;
+ private final List<Expression> args;
+
+ public Call(String id, List<Expression> args) {
+ this.id = id;
+ this.args = new ArrayList<>(args);
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append(id).append("(");
+ for (Expression arg : args) {
+ arg.toCminus(builder, prefix);
+ builder.append(", ");
+ }
+ if (!args.isEmpty()) {
+ builder.setLength(builder.length() - 2);
+ }
+ builder.append(")");
+ }
+
+}
diff --git a/submit/ast/CharConstant.java b/submit/ast/CharConstant.java
new file mode 100644
index 0000000..8ca801d
--- /dev/null
+++ b/submit/ast/CharConstant.java
@@ -0,0 +1,23 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class CharConstant extends AbstractNode implements Expression {
+
+ private final char value;
+
+ public CharConstant(char value) {
+ this.value = value;
+ }
+
+ public void toCminus(StringBuilder builder, final String prefix) {
+ builder.append("'").append(value).append("'");
+ }
+
+}
diff --git a/submit/ast/CompoundStatement.java b/submit/ast/CompoundStatement.java
new file mode 100644
index 0000000..bd5628a
--- /dev/null
+++ b/submit/ast/CompoundStatement.java
@@ -0,0 +1,30 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+import java.util.List;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class CompoundStatement extends AbstractNode implements Statement {
+
+ private final List<Statement> statements;
+
+ public CompoundStatement(List<Statement> statements) {
+ this.statements = statements;
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append(prefix).append("{\n");
+ for (Statement s : statements) {
+ s.toCminus(builder, prefix + " ");
+ }
+ builder.append(prefix).append("}\n");
+ }
+
+}
diff --git a/submit/ast/Declaration.java b/submit/ast/Declaration.java
new file mode 100644
index 0000000..32947e6
--- /dev/null
+++ b/submit/ast/Declaration.java
@@ -0,0 +1,13 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public interface Declaration extends Statement {
+
+}
diff --git a/submit/ast/Expression.java b/submit/ast/Expression.java
new file mode 100644
index 0000000..910f6f0
--- /dev/null
+++ b/submit/ast/Expression.java
@@ -0,0 +1,13 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public interface Expression extends Node {
+
+}
diff --git a/submit/ast/ExpressionStatement.java b/submit/ast/ExpressionStatement.java
new file mode 100644
index 0000000..69071d8
--- /dev/null
+++ b/submit/ast/ExpressionStatement.java
@@ -0,0 +1,26 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class ExpressionStatement extends AbstractNode implements Statement {
+
+ private final Expression expression;
+
+ public ExpressionStatement(Expression expression) {
+ this.expression = expression;
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append(prefix);
+ expression.toCminus(builder, prefix);
+ builder.append(";\n");
+ }
+
+}
diff --git a/submit/ast/FunDeclaration.java b/submit/ast/FunDeclaration.java
new file mode 100644
index 0000000..1ec2ca6
--- /dev/null
+++ b/submit/ast/FunDeclaration.java
@@ -0,0 +1,46 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class FunDeclaration extends AbstractNode implements Declaration {
+
+ private final VarType returnType;
+ private final String id;
+ private final ArrayList<Param> params;
+ private final Statement statement;
+
+ public FunDeclaration(VarType returnType, String id, List<Param> params,
+ Statement statement) {
+ this.returnType = returnType;
+ this.id = id;
+ this.params = new ArrayList<>(params);
+ this.statement = statement;
+ }
+
+ public void toCminus(StringBuilder builder, final String prefix) {
+ String rt = (returnType != null) ? returnType.toString() : "void";
+ builder.append("\n").append(rt).append(" ");
+ builder.append(id);
+ builder.append("(");
+
+ for (Param param : params) {
+ param.toCminus(builder, prefix);
+ builder.append(", ");
+ }
+ if (!params.isEmpty()) {
+ builder.delete(builder.length() - 2, builder.length());
+ }
+ builder.append(")\n");
+ statement.toCminus(builder, prefix);
+ }
+
+}
diff --git a/submit/ast/If.java b/submit/ast/If.java
new file mode 100644
index 0000000..a516c94
--- /dev/null
+++ b/submit/ast/If.java
@@ -0,0 +1,44 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class If extends AbstractNode implements Statement {
+
+ private final Expression expression;
+ private final Statement trueStatement;
+ private final Statement falseStatement;
+
+ public If(Expression expression, Statement trueStatement, Statement falseStatement) {
+ this.expression = expression;
+ this.trueStatement = trueStatement;
+ this.falseStatement = falseStatement;
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append(prefix).append("if (");
+ expression.toCminus(builder, prefix);
+ builder.append(")\n");
+ if (trueStatement instanceof CompoundStatement) {
+ trueStatement.toCminus(builder, prefix);
+ } else {
+ trueStatement.toCminus(builder, prefix + " ");
+ }
+ if (falseStatement != null) {
+ builder.append(prefix).append("else\n");
+ // falseStatement.toCminus(builder, prefix);
+ if (falseStatement instanceof CompoundStatement) {
+ falseStatement.toCminus(builder, prefix);
+ } else {
+ falseStatement.toCminus(builder, prefix + " ");
+ }
+ }
+ // builder.append(prefix).append("}");
+ }
+}
diff --git a/submit/ast/Mutable.java b/submit/ast/Mutable.java
new file mode 100644
index 0000000..d549371
--- /dev/null
+++ b/submit/ast/Mutable.java
@@ -0,0 +1,31 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class Mutable extends AbstractNode implements Expression {
+
+ private final String id;
+ private final Expression index;
+
+ public Mutable(String id, Expression index) {
+ this.id = id;
+ this.index = index;
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append(id);
+ if (index != null) {
+ builder.append("[");
+ index.toCminus(builder, prefix);
+ builder.append("]");
+ }
+ }
+
+}
diff --git a/submit/ast/Node.java b/submit/ast/Node.java
new file mode 100644
index 0000000..2eed788
--- /dev/null
+++ b/submit/ast/Node.java
@@ -0,0 +1,11 @@
+package submit.ast;
+
+import submit.MIPSResult;
+import submit.RegisterAllocator;
+import submit.SymbolTable;
+
+public interface Node {
+ void toCminus(StringBuilder builder, final String prefix);
+
+ MIPSResult toMIPS(StringBuilder code, StringBuilder data, SymbolTable symbolTable, RegisterAllocator regAllocator);
+}
diff --git a/submit/ast/NumConstant.java b/submit/ast/NumConstant.java
new file mode 100644
index 0000000..4e343fd
--- /dev/null
+++ b/submit/ast/NumConstant.java
@@ -0,0 +1,23 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class NumConstant extends AbstractNode implements Expression {
+
+ private final int value;
+
+ public NumConstant(int value) {
+ this.value = value;
+ }
+
+ public void toCminus(StringBuilder builder, final String prefix) {
+ builder.append(Integer.toString(value));
+ }
+
+}
diff --git a/submit/ast/Param.java b/submit/ast/Param.java
new file mode 100644
index 0000000..478c6e2
--- /dev/null
+++ b/submit/ast/Param.java
@@ -0,0 +1,43 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class Param extends AbstractNode implements Node {
+
+ private final VarType type;
+ private final String id;
+ private final boolean array;
+
+ public Param(VarType type, String id, boolean array) {
+ this.type = type;
+ this.id = id;
+ this.array = array;
+ }
+
+ public VarType getType() {
+ return type;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public boolean isArray() {
+ return array;
+ }
+
+ public void toCminus(StringBuilder builder, final String prefix) {
+ if (isArray()) {
+ builder.append(type).append(" ").append(id).append("[]");
+ } else {
+ builder.append(type).append(" ").append(id);
+ }
+ }
+
+}
diff --git a/submit/ast/ParenExpression.java b/submit/ast/ParenExpression.java
new file mode 100644
index 0000000..2eb0b8f
--- /dev/null
+++ b/submit/ast/ParenExpression.java
@@ -0,0 +1,26 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class ParenExpression extends AbstractNode implements Expression {
+
+ private final Expression expression;
+
+ public ParenExpression(Expression expression) {
+ this.expression = expression;
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append("(");
+ expression.toCminus(builder, prefix);
+ builder.append(")");
+ }
+
+}
diff --git a/submit/ast/Program.java b/submit/ast/Program.java
new file mode 100644
index 0000000..1478961
--- /dev/null
+++ b/submit/ast/Program.java
@@ -0,0 +1,36 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class Program extends AbstractNode implements Node {
+
+ private ArrayList<Declaration> declarations;
+
+ public Program(List<Declaration> declarations) {
+ this.declarations = new ArrayList<>(declarations);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ toCminus(builder, "");
+ return builder.toString();
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ for (Declaration declaration : declarations) {
+ declaration.toCminus(builder, "");
+ }
+ }
+
+}
diff --git a/submit/ast/Return.java b/submit/ast/Return.java
new file mode 100644
index 0000000..47a8c16
--- /dev/null
+++ b/submit/ast/Return.java
@@ -0,0 +1,31 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class Return extends AbstractNode implements Statement {
+
+ private final Expression expr;
+
+ public Return(Expression expr) {
+ this.expr = expr;
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append(prefix);
+ if (expr == null) {
+ builder.append("return;\n");
+ } else {
+ builder.append("return ");
+ expr.toCminus(builder, prefix);
+ builder.append(";\n");
+ }
+ }
+
+}
diff --git a/submit/ast/Statement.java b/submit/ast/Statement.java
new file mode 100644
index 0000000..2e0581e
--- /dev/null
+++ b/submit/ast/Statement.java
@@ -0,0 +1,16 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+import java.util.ArrayList;
+
+/**
+ *
+ * @author edwajohn
+ */
+public interface Statement extends Node {
+ public static CompoundStatement empty() { return new CompoundStatement(new ArrayList<>()); }
+
+}
diff --git a/submit/ast/StringConstant.java b/submit/ast/StringConstant.java
new file mode 100644
index 0000000..c3b966e
--- /dev/null
+++ b/submit/ast/StringConstant.java
@@ -0,0 +1,23 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class StringConstant extends AbstractNode implements Expression {
+
+ private final String value;
+
+ public StringConstant(String value) {
+ this.value = value;
+ }
+
+ public void toCminus(StringBuilder builder, final String prefix) {
+ builder.append("\"").append(value).append("\"");
+ }
+
+}
diff --git a/submit/ast/UnaryOperator.java b/submit/ast/UnaryOperator.java
new file mode 100644
index 0000000..1b5082a
--- /dev/null
+++ b/submit/ast/UnaryOperator.java
@@ -0,0 +1,27 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class UnaryOperator extends AbstractNode implements Expression {
+
+ private final UnaryOperatorType type;
+ private final Expression expression;
+
+ public UnaryOperator(String type, Expression expression) {
+ this.type = UnaryOperatorType.fromString(type);
+ this.expression = expression;
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append(type);
+ expression.toCminus(builder, prefix);
+ }
+
+}
diff --git a/submit/ast/UnaryOperatorType.java b/submit/ast/UnaryOperatorType.java
new file mode 100644
index 0000000..828ee5a
--- /dev/null
+++ b/submit/ast/UnaryOperatorType.java
@@ -0,0 +1,35 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public enum UnaryOperatorType {
+
+ NOT("!"), NEG("-"), DEREF("*"), QUESTION("?");
+
+ private final String value;
+
+ private UnaryOperatorType(String value) {
+ this.value = value;
+ }
+
+ public static UnaryOperatorType fromString(String s) {
+ for (UnaryOperatorType at : UnaryOperatorType.values()) {
+ if (at.value.equals(s)) {
+ return at;
+ }
+ }
+ throw new RuntimeException("Illegal string in UnaryOperatorType.fromString()");
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+}
diff --git a/submit/ast/VarDeclaration.java b/submit/ast/VarDeclaration.java
new file mode 100644
index 0000000..d2a5264
--- /dev/null
+++ b/submit/ast/VarDeclaration.java
@@ -0,0 +1,47 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class VarDeclaration extends AbstractNode implements Declaration {
+
+ private final VarType type;
+ private final List<String> ids;
+ private final List<Integer> arraySizes;
+ private final boolean isStatic;
+
+ public VarDeclaration(VarType type, List<String> ids, List<Integer> arraySizes, boolean isStatic) {
+ this.type = type;
+ this.ids = new ArrayList<>(ids);
+ this.arraySizes = arraySizes;
+ this.isStatic = isStatic;
+ }
+
+ public void toCminus(StringBuilder builder, final String prefix) {
+ builder.append(prefix);
+ if (isStatic) {
+ builder.append("static ");
+ }
+ builder.append(type).append(" ");
+ for (int i = 0; i < ids.size(); ++i) {
+ final String id = ids.get(i);
+ final int arraySize = arraySizes.get(i);
+ if (arraySize >= 0) {
+ builder.append(id).append("[").append(arraySize).append("]").append(", ");
+ } else {
+ builder.append(id).append(", ");
+ }
+ }
+ builder.delete(builder.length() - 2, builder.length());
+ builder.append(";\n");
+ }
+
+}
diff --git a/submit/ast/VarType.java b/submit/ast/VarType.java
new file mode 100644
index 0000000..ba28946
--- /dev/null
+++ b/submit/ast/VarType.java
@@ -0,0 +1,35 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public enum VarType {
+
+ INT("int"), BOOL("bool"), CHAR("char");
+
+ private final String value;
+
+ private VarType(String value) {
+ this.value = value;
+ }
+
+ public static VarType fromString(String s) {
+ for (VarType vt : VarType.values()) {
+ if (vt.value.equals(s)) {
+ return vt;
+ }
+ }
+ throw new RuntimeException("Illegal string in VarType.fromString()");
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+}
diff --git a/submit/ast/While.java b/submit/ast/While.java
new file mode 100644
index 0000000..a37195e
--- /dev/null
+++ b/submit/ast/While.java
@@ -0,0 +1,33 @@
+/*
+ * Code formatter project
+ * CS 4481
+ */
+package submit.ast;
+
+/**
+ *
+ * @author edwajohn
+ */
+public class While extends AbstractNode implements Statement {
+
+ private final Expression expression;
+ private final Statement statement;
+
+ public While(Expression expression, Statement statement) {
+ this.expression = expression;
+ this.statement = statement;
+ }
+
+ @Override
+ public void toCminus(StringBuilder builder, String prefix) {
+ builder.append(prefix).append("while (");
+ expression.toCminus(builder, prefix);
+ builder.append(")\n");
+ if (statement instanceof CompoundStatement) {
+ statement.toCminus(builder, prefix);
+ } else {
+ statement.toCminus(builder, prefix + " ");
+ }
+
+ }
+}