diff --git a/README.md b/README.md index 99535e3..f26ce65 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,19 @@ MiniJava Compiler ================= -[Version 1.0.0 - 04/15/2014] +[Version 1.0.0 - 04/26/2014] -The following is a LL(1) compiler for a subset of Java, denoted MiniJava. As of now, it appears to work for the most -part, passing the regression tests performed after each segment. +The following is a complete MiniJava Compiler implementation, according to the specifications in the docs folder. -Noted bugs: -* Changing a field of an object in an array causes crashes - This is not really a surprise, considering the Contextual Analysis aspect of the project - is in fairly rough shape. - -As of now, I do not plan on implementing more things to this, unless there is some potential for extra credit. +Other Features to include in future releases +-------------------------------------------- +* Static Field Initialization +* Keyword 'null' +* Support class constructors +* 'for' loop +* String type and string literals +* Code generation for conditional operations && and || +* Overloaded methods +* Inheritance of fields and methods +* Dynamic Method Invocation +* Support for instanceof/super diff --git a/docs/PA1.pdf b/docs/PA1.pdf deleted file mode 100644 index b934180..0000000 Binary files a/docs/PA1.pdf and /dev/null differ diff --git a/docs/pa-final.pdf b/docs/pa-final.pdf new file mode 100644 index 0000000..baaf0d5 Binary files /dev/null and b/docs/pa-final.pdf differ diff --git a/docs/pa1-updated.pdf b/docs/pa1-updated.pdf new file mode 100644 index 0000000..827a832 Binary files /dev/null and b/docs/pa1-updated.pdf differ diff --git a/docs/PA2.pdf b/docs/pa2.pdf similarity index 100% rename from docs/PA2.pdf rename to docs/pa2.pdf diff --git a/docs/PA3.pdf b/docs/pa3.pdf similarity index 100% rename from docs/PA3.pdf rename to docs/pa3.pdf diff --git a/docs/PA4.pdf b/docs/pa4.pdf similarity index 100% rename from docs/PA4.pdf rename to docs/pa4.pdf diff --git a/src/mJAM/Test.java b/src/mJAM/Test.java index b886ca9..c3b0d66 100644 --- a/src/mJAM/Test.java +++ b/src/mJAM/Test.java @@ -151,7 +151,6 @@ public class Test /* run code */ System.out.println("Running code ... "); Interpreter.debug(objectCodeFileName, asmCodeFileName); - // Interpreter.interpret(objectCodeFileName); System.out.println("*** mJAM execution completed"); } diff --git a/src/miniJava/AbstractSyntaxTrees/AST.java b/src/miniJava/AbstractSyntaxTrees/AST.java index 9303c82..5982b3f 100644 --- a/src/miniJava/AbstractSyntaxTrees/AST.java +++ b/src/miniJava/AbstractSyntaxTrees/AST.java @@ -1,27 +1,27 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public abstract class AST { - - public AST(SourcePosition posn) { - this.posn = posn; - } - - public String toString() { - String fullClassName = this.getClass().getName(); - String cn = fullClassName.substring(1 + fullClassName.lastIndexOf('.')); - if (ASTDisplay.showPosition) - cn = cn + " " + posn.toString(); - return cn; - } - - public abstract R visit(Visitor v, A o); - - public SourcePosition posn; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public abstract class AST { + + public AST(SourcePosition posn) { + this.posn = posn; + } + + public String toString() { + String fullClassName = this.getClass().getName(); + String cn = fullClassName.substring(1 + fullClassName.lastIndexOf('.')); + if (ASTDisplay.showPosition) + cn = cn + " " + posn.toString(); + return cn; + } + + public abstract R visit(Visitor v, A o); + + public SourcePosition posn; +} diff --git a/src/miniJava/AbstractSyntaxTrees/ASTDisplay.java b/src/miniJava/AbstractSyntaxTrees/ASTDisplay.java index e0daf6b..08d18db 100644 --- a/src/miniJava/AbstractSyntaxTrees/ASTDisplay.java +++ b/src/miniJava/AbstractSyntaxTrees/ASTDisplay.java @@ -1,358 +1,358 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -/* - * Display AST in text form - * In-order traversal of AST, visiting each node with a method of the form - * - * public Object visitXXX( XXX astnode, String arg) - * - * where arg is a prefix string (indentation) to precede display of ast node - * and a null Object is returned as the result. - * - * implements Visitor - */ -public class ASTDisplay implements Visitor { - - public static boolean showPosition = false; - - /** - * print text representation of AST to stdout - * - * @param ast - * root node of AST - */ - public void showTree(AST ast) { - System.out.println("======= AST Display ========================="); - ast.visit(this, ""); - System.out.println("============================================="); - } - - // methods to format output - - /** - * display arbitrary text for a node - * - * @param prefix - * spacing to indicate depth in AST - * @param text - * preformatted node display - */ - private void show(String prefix, String text) { - System.out.println(prefix + text); - } - - /** - * display AST node by name - * - * @param prefix - * spacing to indicate depth in AST - * @param node - * AST node, will be shown by name - */ - private void show(String prefix, AST node) { - System.out.println(prefix + node.toString()); - } - - /** - * quote a string - * - * @param text - * string to quote - */ - private String quote(String text) { - return ("\"" + text + "\""); - } - - /** - * increase depth in AST - * - * @param prefix - * current spacing to indicate depth in AST - * @return new spacing - */ - private String indent(String prefix) { - return prefix + " "; - } - - // ///////////////////////////////////////////////////////////////////////////// - // - // PACKAGE - // - // ///////////////////////////////////////////////////////////////////////////// - - public Object visitPackage(Package prog, String arg) { - show(arg, prog); - ClassDeclList cl = prog.classDeclList; - show(arg, " ClassDeclList [" + cl.size() + "]"); - String pfx = arg + " . "; - for (ClassDecl c : prog.classDeclList) { - c.visit(this, pfx); - } - return null; - } - - // ///////////////////////////////////////////////////////////////////////////// - // - // DECLARATIONS - // - // ///////////////////////////////////////////////////////////////////////////// - - public Object visitClassDecl(ClassDecl clas, String arg) { - show(arg, clas); - show(indent(arg), quote(clas.name) + " classname"); - show(arg, " FieldDeclList [" + clas.fieldDeclList.size() + "]"); - String pfx = arg + " . "; - for (FieldDecl f : clas.fieldDeclList) - f.visit(this, pfx); - show(arg, " MethodDeclList [" + clas.methodDeclList.size() + "]"); - for (MethodDecl m : clas.methodDeclList) - m.visit(this, pfx); - return null; - } - - public Object visitFieldDecl(FieldDecl f, String arg) { - show(arg, "(" + (f.isPrivate ? "private" : "public") - + (f.isStatic ? " static) " : ") ") + f.toString()); - f.type.visit(this, indent(arg)); - show(indent(arg), quote(f.name) + " fieldname"); - return null; - } - - public Object visitMethodDecl(MethodDecl m, String arg) { - show(arg, "(" + (m.isPrivate ? "private" : "public") - + (m.isStatic ? " static) " : ") ") + m.toString()); - m.type.visit(this, indent(arg)); - show(indent(arg), quote(m.name) + " methodname"); - ParameterDeclList pdl = m.parameterDeclList; - show(arg, " ParameterDeclList [" + pdl.size() + "]"); - String pfx = ((String) arg) + " . "; - for (ParameterDecl pd : pdl) { - pd.visit(this, pfx); - } - StatementList sl = m.statementList; - show(arg, " StmtList [" + sl.size() + "]"); - for (Statement s : sl) { - s.visit(this, pfx); - } - if (m.returnExp != null) { - m.returnExp.visit(this, indent(arg)); - } - return null; - } - - public Object visitParameterDecl(ParameterDecl pd, String arg) { - show(arg, pd); - pd.type.visit(this, indent(arg)); - show(indent(arg), quote(pd.name) + "parametername "); - return null; - } - - public Object visitVarDecl(VarDecl vd, String arg) { - show(arg, vd); - vd.type.visit(this, indent(arg)); - show(indent(arg), quote(vd.name) + " varname"); - return null; - } - - // ///////////////////////////////////////////////////////////////////////////// - // - // TYPES - // - // ///////////////////////////////////////////////////////////////////////////// - - public Object visitBaseType(BaseType type, String arg) { - show(arg, type.typeKind + " " + type.toString()); - return null; - } - - public Object visitClassType(ClassType type, String arg) { - show(arg, type); - show(indent(arg), quote(type.className.spelling) + " classname"); - return null; - } - - public Object visitArrayType(ArrayType type, String arg) { - show(arg, type); - type.eltType.visit(this, indent(arg)); - return null; - } - - // ///////////////////////////////////////////////////////////////////////////// - // - // STATEMENTS - // - // ///////////////////////////////////////////////////////////////////////////// - - public Object visitBlockStmt(BlockStmt stmt, String arg) { - show(arg, stmt); - StatementList sl = stmt.sl; - show(arg, " StatementList [" + sl.size() + "]"); - String pfx = arg + " . "; - for (Statement s : sl) { - s.visit(this, pfx); - } - return null; - } - - public Object visitVardeclStmt(VarDeclStmt stmt, String arg) { - show(arg, stmt); - stmt.varDecl.visit(this, indent(arg)); - stmt.initExp.visit(this, indent(arg)); - return null; - } - - public Object visitAssignStmt(AssignStmt stmt, String arg) { - show(arg, stmt); - stmt.ref.visit(this, indent(arg)); - stmt.val.visit(this, indent(arg)); - return null; - } - - public Object visitCallStmt(CallStmt stmt, String arg) { - show(arg, stmt); - stmt.methodRef.visit(this, indent(arg)); - ExprList al = stmt.argList; - show(arg, " ExprList [" + al.size() + "]"); - String pfx = arg + " . "; - for (Expression e : al) { - e.visit(this, pfx); - } - return null; - } - - public Object visitIfStmt(IfStmt stmt, String arg) { - show(arg, stmt); - stmt.cond.visit(this, indent(arg)); - stmt.thenStmt.visit(this, indent(arg)); - if (stmt.elseStmt != null) - stmt.elseStmt.visit(this, indent(arg)); - return null; - } - - public Object visitWhileStmt(WhileStmt stmt, String arg) { - show(arg, stmt); - stmt.cond.visit(this, indent(arg)); - stmt.body.visit(this, indent(arg)); - return null; - } - - // ///////////////////////////////////////////////////////////////////////////// - // - // EXPRESSIONS - // - // ///////////////////////////////////////////////////////////////////////////// - - public Object visitUnaryExpr(UnaryExpr expr, String arg) { - show(arg, expr); - expr.operator.visit(this, indent(arg)); - expr.expr.visit(this, indent(indent(arg))); - return null; - } - - public Object visitBinaryExpr(BinaryExpr expr, String arg) { - show(arg, expr); - expr.operator.visit(this, indent(arg)); - expr.left.visit(this, indent(indent(arg))); - expr.right.visit(this, indent(indent(arg))); - return null; - } - - public Object visitRefExpr(RefExpr expr, String arg) { - show(arg, expr); - expr.ref.visit(this, indent(arg)); - return null; - } - - public Object visitCallExpr(CallExpr expr, String arg) { - show(arg, expr); - expr.functionRef.visit(this, indent(arg)); - ExprList al = expr.argList; - show(arg, " ExprList + [" + al.size() + "]"); - String pfx = arg + " . "; - for (Expression e : al) { - e.visit(this, pfx); - } - return null; - } - - public Object visitLiteralExpr(LiteralExpr expr, String arg) { - show(arg, expr); - expr.literal.visit(this, indent(arg)); - return null; - } - - public Object visitNewArrayExpr(NewArrayExpr expr, String arg) { - show(arg, expr); - expr.eltType.visit(this, indent(arg)); - expr.sizeExpr.visit(this, indent(arg)); - return null; - } - - public Object visitNewObjectExpr(NewObjectExpr expr, String arg) { - show(arg, expr); - expr.classtype.visit(this, indent(arg)); - return null; - } - - // ///////////////////////////////////////////////////////////////////////////// - // - // REFERENCES - // - // ///////////////////////////////////////////////////////////////////////////// - - public Object visitQualifiedRef(QualifiedRef qr, String arg) { - show(arg, qr); - qr.id.visit(this, indent(arg)); - qr.ref.visit(this, indent(arg)); - return null; - } - - public Object visitIndexedRef(IndexedRef ir, String arg) { - show(arg, ir); - ir.indexExpr.visit(this, indent(arg)); - ir.ref.visit(this, indent(arg)); - return null; - } - - public Object visitIdRef(IdRef ref, String arg) { - show(arg, ref); - ref.id.visit(this, indent(arg)); - return null; - } - - public Object visitThisRef(ThisRef ref, String arg) { - show(arg, ref); - return null; - } - - // ///////////////////////////////////////////////////////////////////////////// - // - // TERMINALS - // - // ///////////////////////////////////////////////////////////////////////////// - - public Object visitIdentifier(Identifier id, String arg) { - show(arg, quote(id.spelling) + " " + id.toString()); - return null; - } - - public Object visitOperator(Operator op, String arg) { - show(arg, quote(op.spelling) + " " + op.toString()); - return null; - } - - public Object visitIntLiteral(IntLiteral num, String arg) { - show(arg, quote(num.spelling) + " " + num.toString()); - return null; - } - - public Object visitBooleanLiteral(BooleanLiteral bool, String arg) { - show(arg, quote(bool.spelling) + " " + bool.toString()); - return null; - } -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +/* + * Display AST in text form + * In-order traversal of AST, visiting each node with a method of the form + * + * public Object visitXXX( XXX astnode, String arg) + * + * where arg is a prefix string (indentation) to precede display of ast node + * and a null Object is returned as the result. + * + * implements Visitor + */ +public class ASTDisplay implements Visitor { + + public static boolean showPosition = false; + + /** + * print text representation of AST to stdout + * + * @param ast + * root node of AST + */ + public void showTree(AST ast) { + System.out.println("======= AST Display ========================="); + ast.visit(this, ""); + System.out.println("============================================="); + } + + // methods to format output + + /** + * display arbitrary text for a node + * + * @param prefix + * spacing to indicate depth in AST + * @param text + * preformatted node display + */ + private void show(String prefix, String text) { + System.out.println(prefix + text); + } + + /** + * display AST node by name + * + * @param prefix + * spacing to indicate depth in AST + * @param node + * AST node, will be shown by name + */ + private void show(String prefix, AST node) { + System.out.println(prefix + node.toString()); + } + + /** + * quote a string + * + * @param text + * string to quote + */ + private String quote(String text) { + return ("\"" + text + "\""); + } + + /** + * increase depth in AST + * + * @param prefix + * current spacing to indicate depth in AST + * @return new spacing + */ + private String indent(String prefix) { + return prefix + " "; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // PACKAGE + // + // ///////////////////////////////////////////////////////////////////////////// + + public Object visitPackage(Package prog, String arg) { + show(arg, prog); + ClassDeclList cl = prog.classDeclList; + show(arg, " ClassDeclList [" + cl.size() + "]"); + String pfx = arg + " . "; + for (ClassDecl c : prog.classDeclList) { + c.visit(this, pfx); + } + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // DECLARATIONS + // + // ///////////////////////////////////////////////////////////////////////////// + + public Object visitClassDecl(ClassDecl clas, String arg) { + show(arg, clas); + show(indent(arg), quote(clas.name) + " classname"); + show(arg, " FieldDeclList [" + clas.fieldDeclList.size() + "]"); + String pfx = arg + " . "; + for (FieldDecl f : clas.fieldDeclList) + f.visit(this, pfx); + show(arg, " MethodDeclList [" + clas.methodDeclList.size() + "]"); + for (MethodDecl m : clas.methodDeclList) + m.visit(this, pfx); + return null; + } + + public Object visitFieldDecl(FieldDecl f, String arg) { + show(arg, "(" + (f.isPrivate ? "private" : "public") + + (f.isStatic ? " static) " : ") ") + f.toString()); + f.type.visit(this, indent(arg)); + show(indent(arg), quote(f.name) + " fieldname"); + return null; + } + + public Object visitMethodDecl(MethodDecl m, String arg) { + show(arg, "(" + (m.isPrivate ? "private" : "public") + + (m.isStatic ? " static) " : ") ") + m.toString()); + m.type.visit(this, indent(arg)); + show(indent(arg), quote(m.name) + " methodname"); + ParameterDeclList pdl = m.parameterDeclList; + show(arg, " ParameterDeclList [" + pdl.size() + "]"); + String pfx = ((String) arg) + " . "; + for (ParameterDecl pd : pdl) { + pd.visit(this, pfx); + } + StatementList sl = m.statementList; + show(arg, " StmtList [" + sl.size() + "]"); + for (Statement s : sl) { + s.visit(this, pfx); + } + if (m.returnExp != null) { + m.returnExp.visit(this, indent(arg)); + } + return null; + } + + public Object visitParameterDecl(ParameterDecl pd, String arg) { + show(arg, pd); + pd.type.visit(this, indent(arg)); + show(indent(arg), quote(pd.name) + "parametername "); + return null; + } + + public Object visitVarDecl(VarDecl vd, String arg) { + show(arg, vd); + vd.type.visit(this, indent(arg)); + show(indent(arg), quote(vd.name) + " varname"); + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // TYPES + // + // ///////////////////////////////////////////////////////////////////////////// + + public Object visitBaseType(BaseType type, String arg) { + show(arg, type.typeKind + " " + type.toString()); + return null; + } + + public Object visitClassType(ClassType type, String arg) { + show(arg, type); + show(indent(arg), quote(type.className.spelling) + " classname"); + return null; + } + + public Object visitArrayType(ArrayType type, String arg) { + show(arg, type); + type.eltType.visit(this, indent(arg)); + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // STATEMENTS + // + // ///////////////////////////////////////////////////////////////////////////// + + public Object visitBlockStmt(BlockStmt stmt, String arg) { + show(arg, stmt); + StatementList sl = stmt.sl; + show(arg, " StatementList [" + sl.size() + "]"); + String pfx = arg + " . "; + for (Statement s : sl) { + s.visit(this, pfx); + } + return null; + } + + public Object visitVardeclStmt(VarDeclStmt stmt, String arg) { + show(arg, stmt); + stmt.varDecl.visit(this, indent(arg)); + stmt.initExp.visit(this, indent(arg)); + return null; + } + + public Object visitAssignStmt(AssignStmt stmt, String arg) { + show(arg, stmt); + stmt.ref.visit(this, indent(arg)); + stmt.val.visit(this, indent(arg)); + return null; + } + + public Object visitCallStmt(CallStmt stmt, String arg) { + show(arg, stmt); + stmt.methodRef.visit(this, indent(arg)); + ExprList al = stmt.argList; + show(arg, " ExprList [" + al.size() + "]"); + String pfx = arg + " . "; + for (Expression e : al) { + e.visit(this, pfx); + } + return null; + } + + public Object visitIfStmt(IfStmt stmt, String arg) { + show(arg, stmt); + stmt.cond.visit(this, indent(arg)); + stmt.thenStmt.visit(this, indent(arg)); + if (stmt.elseStmt != null) + stmt.elseStmt.visit(this, indent(arg)); + return null; + } + + public Object visitWhileStmt(WhileStmt stmt, String arg) { + show(arg, stmt); + stmt.cond.visit(this, indent(arg)); + stmt.body.visit(this, indent(arg)); + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // EXPRESSIONS + // + // ///////////////////////////////////////////////////////////////////////////// + + public Object visitUnaryExpr(UnaryExpr expr, String arg) { + show(arg, expr); + expr.operator.visit(this, indent(arg)); + expr.expr.visit(this, indent(indent(arg))); + return null; + } + + public Object visitBinaryExpr(BinaryExpr expr, String arg) { + show(arg, expr); + expr.operator.visit(this, indent(arg)); + expr.left.visit(this, indent(indent(arg))); + expr.right.visit(this, indent(indent(arg))); + return null; + } + + public Object visitRefExpr(RefExpr expr, String arg) { + show(arg, expr); + expr.ref.visit(this, indent(arg)); + return null; + } + + public Object visitCallExpr(CallExpr expr, String arg) { + show(arg, expr); + expr.functionRef.visit(this, indent(arg)); + ExprList al = expr.argList; + show(arg, " ExprList + [" + al.size() + "]"); + String pfx = arg + " . "; + for (Expression e : al) { + e.visit(this, pfx); + } + return null; + } + + public Object visitLiteralExpr(LiteralExpr expr, String arg) { + show(arg, expr); + expr.literal.visit(this, indent(arg)); + return null; + } + + public Object visitNewArrayExpr(NewArrayExpr expr, String arg) { + show(arg, expr); + expr.eltType.visit(this, indent(arg)); + expr.sizeExpr.visit(this, indent(arg)); + return null; + } + + public Object visitNewObjectExpr(NewObjectExpr expr, String arg) { + show(arg, expr); + expr.classtype.visit(this, indent(arg)); + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // REFERENCES + // + // ///////////////////////////////////////////////////////////////////////////// + + public Object visitQualifiedRef(QualifiedRef qr, String arg) { + show(arg, qr); + qr.id.visit(this, indent(arg)); + qr.ref.visit(this, indent(arg)); + return null; + } + + public Object visitIndexedRef(IndexedRef ir, String arg) { + show(arg, ir); + ir.indexExpr.visit(this, indent(arg)); + ir.ref.visit(this, indent(arg)); + return null; + } + + public Object visitIdRef(IdRef ref, String arg) { + show(arg, ref); + ref.id.visit(this, indent(arg)); + return null; + } + + public Object visitThisRef(ThisRef ref, String arg) { + show(arg, ref); + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // TERMINALS + // + // ///////////////////////////////////////////////////////////////////////////// + + public Object visitIdentifier(Identifier id, String arg) { + show(arg, quote(id.spelling) + " " + id.toString()); + return null; + } + + public Object visitOperator(Operator op, String arg) { + show(arg, quote(op.spelling) + " " + op.toString()); + return null; + } + + public Object visitIntLiteral(IntLiteral num, String arg) { + show(arg, quote(num.spelling) + " " + num.toString()); + return null; + } + + public Object visitBooleanLiteral(BooleanLiteral bool, String arg) { + show(arg, quote(bool.spelling) + " " + bool.toString()); + return null; + } +} diff --git a/src/miniJava/AbstractSyntaxTrees/ArrayType.java b/src/miniJava/AbstractSyntaxTrees/ArrayType.java index bee4008..3275a14 100644 --- a/src/miniJava/AbstractSyntaxTrees/ArrayType.java +++ b/src/miniJava/AbstractSyntaxTrees/ArrayType.java @@ -1,23 +1,27 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ - -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class ArrayType extends Type { - - public ArrayType(Type eltType, SourcePosition posn) { - super(TypeKind.ARRAY, posn); - this.eltType = eltType; - } - - public R visit(Visitor v, A o) { - return v.visitArrayType(this, o); - } - - public Type eltType; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ + +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class ArrayType extends Type { + + public ArrayType(Type eltType, SourcePosition posn) { + super(TypeKind.ARRAY, posn); + this.eltType = eltType; + } + + public R visit(Visitor v, A o) { + return v.visitArrayType(this, o); + } + + public String toString() { + return eltType + " Array"; + } + + public Type eltType; +} diff --git a/src/miniJava/AbstractSyntaxTrees/AssignStmt.java b/src/miniJava/AbstractSyntaxTrees/AssignStmt.java index cc78e3f..d7c3d44 100644 --- a/src/miniJava/AbstractSyntaxTrees/AssignStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/AssignStmt.java @@ -1,23 +1,23 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class AssignStmt extends Statement { - public AssignStmt(Reference r, Expression e, SourcePosition posn) { - super(posn); - ref = r; - val = e; - } - - public R visit(Visitor v, A o) { - return v.visitAssignStmt(this, o); - } - - public Reference ref; - public Expression val; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class AssignStmt extends Statement { + public AssignStmt(Reference r, Expression e, SourcePosition posn) { + super(posn); + ref = r; + val = e; + } + + public R visit(Visitor v, A o) { + return v.visitAssignStmt(this, o); + } + + public Reference ref; + public Expression val; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/BaseType.java b/src/miniJava/AbstractSyntaxTrees/BaseType.java index d39fe5b..69bc9af 100644 --- a/src/miniJava/AbstractSyntaxTrees/BaseType.java +++ b/src/miniJava/AbstractSyntaxTrees/BaseType.java @@ -1,18 +1,22 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class BaseType extends Type { - public BaseType(TypeKind t, SourcePosition posn) { - super(t, posn); - } - - public R visit(Visitor v, A o) { - return v.visitBaseType(this, o); - } -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class BaseType extends Type { + public BaseType(TypeKind t, SourcePosition posn) { + super(t, posn); + } + + public R visit(Visitor v, A o) { + return v.visitBaseType(this, o); + } + + public String toString() { + return typeKind.toString(); + } +} diff --git a/src/miniJava/AbstractSyntaxTrees/BinaryExpr.java b/src/miniJava/AbstractSyntaxTrees/BinaryExpr.java index 4488c19..cb925a5 100644 --- a/src/miniJava/AbstractSyntaxTrees/BinaryExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/BinaryExpr.java @@ -1,26 +1,26 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class BinaryExpr extends Expression { - public BinaryExpr(Operator o, Expression e1, Expression e2, - SourcePosition posn) { - super(posn); - operator = o; - left = e1; - right = e2; - } - - public R visit(Visitor v, A o) { - return v.visitBinaryExpr(this, o); - } - - public Operator operator; - public Expression left; - public Expression right; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class BinaryExpr extends Expression { + public BinaryExpr(Operator o, Expression e1, Expression e2, + SourcePosition posn) { + super(posn); + operator = o; + left = e1; + right = e2; + } + + public R visit(Visitor v, A o) { + return v.visitBinaryExpr(this, o); + } + + public Operator operator; + public Expression left; + public Expression right; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/BlockStmt.java b/src/miniJava/AbstractSyntaxTrees/BlockStmt.java index 1a4e2d9..a2c7459 100644 --- a/src/miniJava/AbstractSyntaxTrees/BlockStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/BlockStmt.java @@ -1,21 +1,21 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class BlockStmt extends Statement { - public BlockStmt(StatementList sl, SourcePosition posn) { - super(posn); - this.sl = sl; - } - - public R visit(Visitor v, A o) { - return v.visitBlockStmt(this, o); - } - - public StatementList sl; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class BlockStmt extends Statement { + public BlockStmt(StatementList sl, SourcePosition posn) { + super(posn); + this.sl = sl; + } + + public R visit(Visitor v, A o) { + return v.visitBlockStmt(this, o); + } + + public StatementList sl; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/BooleanLiteral.java b/src/miniJava/AbstractSyntaxTrees/BooleanLiteral.java index d0b4302..669c205 100644 --- a/src/miniJava/AbstractSyntaxTrees/BooleanLiteral.java +++ b/src/miniJava/AbstractSyntaxTrees/BooleanLiteral.java @@ -1,19 +1,19 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class BooleanLiteral extends Literal { - - public BooleanLiteral(String spelling, SourcePosition posn) { - super(spelling, posn); - } - - public R visit(Visitor v, A o) { - return v.visitBooleanLiteral(this, o); - } -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class BooleanLiteral extends Literal { + + public BooleanLiteral(String spelling, SourcePosition posn) { + super(spelling, posn); + } + + public R visit(Visitor v, A o) { + return v.visitBooleanLiteral(this, o); + } +} diff --git a/src/miniJava/AbstractSyntaxTrees/CallExpr.java b/src/miniJava/AbstractSyntaxTrees/CallExpr.java index 5aaa41f..d17ba9f 100644 --- a/src/miniJava/AbstractSyntaxTrees/CallExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/CallExpr.java @@ -1,23 +1,23 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class CallExpr extends Expression { - public CallExpr(Reference f, ExprList el, SourcePosition posn) { - super(posn); - functionRef = f; - argList = el; - } - - public R visit(Visitor v, A o) { - return v.visitCallExpr(this, o); - } - - public Reference functionRef; - public ExprList argList; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class CallExpr extends Expression { + public CallExpr(Reference f, ExprList el, SourcePosition posn) { + super(posn); + functionRef = f; + argList = el; + } + + public R visit(Visitor v, A o) { + return v.visitCallExpr(this, o); + } + + public Reference functionRef; + public ExprList argList; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/CallStmt.java b/src/miniJava/AbstractSyntaxTrees/CallStmt.java index 966f984..2353a82 100644 --- a/src/miniJava/AbstractSyntaxTrees/CallStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/CallStmt.java @@ -1,23 +1,23 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class CallStmt extends Statement { - public CallStmt(Reference m, ExprList el, SourcePosition posn) { - super(posn); - methodRef = m; - argList = el; - } - - public R visit(Visitor v, A o) { - return v.visitCallStmt(this, o); - } - - public Reference methodRef; - public ExprList argList; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class CallStmt extends Statement { + public CallStmt(Reference m, ExprList el, SourcePosition posn) { + super(posn); + methodRef = m; + argList = el; + } + + public R visit(Visitor v, A o) { + return v.visitCallStmt(this, o); + } + + public Reference methodRef; + public ExprList argList; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/ClassDecl.java b/src/miniJava/AbstractSyntaxTrees/ClassDecl.java index 39a96be..d99706c 100644 --- a/src/miniJava/AbstractSyntaxTrees/ClassDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/ClassDecl.java @@ -1,27 +1,25 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class ClassDecl extends Declaration { - - public ClassDecl(String cn, FieldDeclList fdl, MethodDeclList mdl, SourcePosition posn) { - super(cn, null, posn); - fieldDeclList = fdl; - methodDeclList = mdl; - - Identifier ident = new Identifier(cn, posn); - type = new ClassType(ident, posn); - } - - public R visit(Visitor v, A o) { - return v.visitClassDecl(this, o); - } - - public FieldDeclList fieldDeclList; - public MethodDeclList methodDeclList; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class ClassDecl extends Declaration { + + public ClassDecl(String cn, FieldDeclList fdl, MethodDeclList mdl, + SourcePosition posn) { + super(cn, null, posn); + fieldDeclList = fdl; + methodDeclList = mdl; + } + + public R visit(Visitor v, A o) { + return v.visitClassDecl(this, o); + } + + public FieldDeclList fieldDeclList; + public MethodDeclList methodDeclList; +} diff --git a/src/miniJava/AbstractSyntaxTrees/ClassDeclList.java b/src/miniJava/AbstractSyntaxTrees/ClassDeclList.java index 64dd757..495908d 100644 --- a/src/miniJava/AbstractSyntaxTrees/ClassDeclList.java +++ b/src/miniJava/AbstractSyntaxTrees/ClassDeclList.java @@ -1,32 +1,32 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import java.util.*; - -public class ClassDeclList implements Iterable { - public ClassDeclList() { - classDeclList = new ArrayList(); - } - - public void add(ClassDecl cd) { - classDeclList.add(cd); - } - - public ClassDecl get(int i) { - return classDeclList.get(i); - } - - public int size() { - return classDeclList.size(); - } - - public Iterator iterator() { - return classDeclList.iterator(); - } - - private List classDeclList; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import java.util.*; + +public class ClassDeclList implements Iterable { + public ClassDeclList() { + classDeclList = new ArrayList(); + } + + public void add(ClassDecl cd) { + classDeclList.add(cd); + } + + public ClassDecl get(int i) { + return classDeclList.get(i); + } + + public int size() { + return classDeclList.size(); + } + + public Iterator iterator() { + return classDeclList.iterator(); + } + + private List classDeclList; +} diff --git a/src/miniJava/AbstractSyntaxTrees/ClassType.java b/src/miniJava/AbstractSyntaxTrees/ClassType.java index 0c2c312..b1e8df9 100644 --- a/src/miniJava/AbstractSyntaxTrees/ClassType.java +++ b/src/miniJava/AbstractSyntaxTrees/ClassType.java @@ -1,21 +1,25 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class ClassType extends Type { - public ClassType(Identifier cn, SourcePosition posn) { - super(TypeKind.CLASS, posn); - className = cn; - } - - public R visit(Visitor v, A o) { - return v.visitClassType(this, o); - } - - public Identifier className; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class ClassType extends Type { + public ClassType(Identifier cn, SourcePosition posn) { + super(TypeKind.CLASS, posn); + className = cn; + } + + public R visit(Visitor v, A o) { + return v.visitClassType(this, o); + } + + public String toString() { + return "Class " + className.spelling; + } + + public Identifier className; +} diff --git a/src/miniJava/AbstractSyntaxTrees/Declaration.java b/src/miniJava/AbstractSyntaxTrees/Declaration.java index a412631..05f6021 100644 --- a/src/miniJava/AbstractSyntaxTrees/Declaration.java +++ b/src/miniJava/AbstractSyntaxTrees/Declaration.java @@ -1,32 +1,24 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.CodeGenerator.RuntimeEntity; -import miniJava.SyntacticAnalyzer.SourcePosition; - -public abstract class Declaration extends AST { - - public Declaration(String name, Type type, SourcePosition posn) { - super(posn); - this.name = name; - this.type = type; - } - - @Override - public String toString() { - if (posn != null) { - return this.name + "(Line: " + posn.line + ", Column: " + posn.col - + ")"; - } else { - return super.toString(); - } - } - - public RuntimeEntity entity; - public String name; - public Type type; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.CodeGenerator.RuntimeEntity; +import miniJava.ContextualAnalyzer.IdTable; +import miniJava.SyntacticAnalyzer.SourcePosition; + +public abstract class Declaration extends AST { + + public Declaration(String name, Type type, SourcePosition posn) { + super(posn); + this.name = name; + this.type = type; + } + + public RuntimeEntity entity; + public IdTable table; + public String name; + public Type type; +} diff --git a/src/miniJava/AbstractSyntaxTrees/Declarators.java b/src/miniJava/AbstractSyntaxTrees/Declarators.java index 3f10afb..e6c3a0e 100644 --- a/src/miniJava/AbstractSyntaxTrees/Declarators.java +++ b/src/miniJava/AbstractSyntaxTrees/Declarators.java @@ -2,6 +2,10 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; +/** + * The following is a custom class, included for use with method and field + * declarations. + */ public class Declarators { public Declarators(boolean isPrivate, boolean isStatic, Type mt, @@ -16,4 +20,4 @@ public class Declarators { public boolean isStatic; public Type mt; public SourcePosition posn; -} +} \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/ExprList.java b/src/miniJava/AbstractSyntaxTrees/ExprList.java index 3aa9cf8..a30054f 100644 --- a/src/miniJava/AbstractSyntaxTrees/ExprList.java +++ b/src/miniJava/AbstractSyntaxTrees/ExprList.java @@ -1,32 +1,32 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import java.util.*; - -public class ExprList implements Iterable { - public ExprList() { - elist = new ArrayList(); - } - - public void add(Expression e) { - elist.add(e); - } - - public Expression get(int i) { - return elist.get(i); - } - - public int size() { - return elist.size(); - } - - public Iterator iterator() { - return elist.iterator(); - } - - private List elist; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import java.util.*; + +public class ExprList implements Iterable { + public ExprList() { + elist = new ArrayList(); + } + + public void add(Expression e) { + elist.add(e); + } + + public Expression get(int i) { + return elist.get(i); + } + + public int size() { + return elist.size(); + } + + public Iterator iterator() { + return elist.iterator(); + } + + private List elist; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/Expression.java b/src/miniJava/AbstractSyntaxTrees/Expression.java index 7086815..34912ee 100644 --- a/src/miniJava/AbstractSyntaxTrees/Expression.java +++ b/src/miniJava/AbstractSyntaxTrees/Expression.java @@ -1,16 +1,16 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public abstract class Expression extends AST { - - public Expression(SourcePosition posn) { - super(posn); - } - -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public abstract class Expression extends AST { + + public Expression(SourcePosition posn) { + super(posn); + } + +} diff --git a/src/miniJava/AbstractSyntaxTrees/FieldDecl.java b/src/miniJava/AbstractSyntaxTrees/FieldDecl.java index 12a11f7..ee7e71e 100644 --- a/src/miniJava/AbstractSyntaxTrees/FieldDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/FieldDecl.java @@ -1,24 +1,28 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class FieldDecl extends MemberDecl { - - public FieldDecl(boolean isPrivate, boolean isStatic, Type t, String name, - SourcePosition posn) { - super(isPrivate, isStatic, t, name, posn); - } - - public FieldDecl(MemberDecl md, SourcePosition posn) { - super(md, posn); - } - - public R visit(Visitor v, A o) { - return v.visitFieldDecl(this, o); - } -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class FieldDecl extends MemberDecl { + + public FieldDecl(boolean isPrivate, boolean isStatic, Type t, String name, + SourcePosition posn) { + super(isPrivate, isStatic, t, name, posn); + } + + public FieldDecl(MemberDecl md, SourcePosition posn) { + super(md, posn); + } + + public FieldDecl(Declarators d, String name) { + super(d.isPrivate, d.isStatic, d.mt, name, d.posn); + } + + public R visit(Visitor v, A o) { + return v.visitFieldDecl(this, o); + } +} diff --git a/src/miniJava/AbstractSyntaxTrees/FieldDeclList.java b/src/miniJava/AbstractSyntaxTrees/FieldDeclList.java index a2a476b..03e8226 100644 --- a/src/miniJava/AbstractSyntaxTrees/FieldDeclList.java +++ b/src/miniJava/AbstractSyntaxTrees/FieldDeclList.java @@ -1,37 +1,32 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import java.util.*; - -public class FieldDeclList implements Iterable { - public FieldDeclList() { - fieldDeclList = new ArrayList(); - } - - public FieldDeclList(FieldDecl f) { - fieldDeclList = new ArrayList(); - fieldDeclList.add(f); - } - - public void add(FieldDecl cd) { - fieldDeclList.add(cd); - } - - public FieldDecl get(int i) { - return fieldDeclList.get(i); - } - - public int size() { - return fieldDeclList.size(); - } - - public Iterator iterator() { - return fieldDeclList.iterator(); - } - - private List fieldDeclList; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import java.util.*; + +public class FieldDeclList implements Iterable { + public FieldDeclList() { + fieldDeclList = new ArrayList(); + } + + public void add(FieldDecl cd) { + fieldDeclList.add(cd); + } + + public FieldDecl get(int i) { + return fieldDeclList.get(i); + } + + public int size() { + return fieldDeclList.size(); + } + + public Iterator iterator() { + return fieldDeclList.iterator(); + } + + private List fieldDeclList; +} diff --git a/src/miniJava/AbstractSyntaxTrees/IdRef.java b/src/miniJava/AbstractSyntaxTrees/IdRef.java index cc3e555..696ec40 100644 --- a/src/miniJava/AbstractSyntaxTrees/IdRef.java +++ b/src/miniJava/AbstractSyntaxTrees/IdRef.java @@ -1,22 +1,22 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class IdRef extends Reference { - - public IdRef(Identifier id, SourcePosition posn) { - super(posn); - this.id = id; - } - - public R visit(Visitor v, A o) { - return v.visitIdRef(this, o); - } - - public Identifier id; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class IdRef extends Reference { + + public IdRef(Identifier id, SourcePosition posn) { + super(posn); + this.id = id; + } + + public R visit(Visitor v, A o) { + return v.visitIdRef(this, o); + } + + public Identifier id; +} diff --git a/src/miniJava/AbstractSyntaxTrees/Identifier.java b/src/miniJava/AbstractSyntaxTrees/Identifier.java index 1d0c0a5..dde46f7 100644 --- a/src/miniJava/AbstractSyntaxTrees/Identifier.java +++ b/src/miniJava/AbstractSyntaxTrees/Identifier.java @@ -1,21 +1,23 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class Identifier extends Terminal { - - public Identifier(String s, SourcePosition posn) { - super(s, posn); - } - - public R visit(Visitor v, A o) { - return v.visitIdentifier(this, o); - } - - public Declaration decl = null; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.CodeGenerator.RuntimeEntity; +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class Identifier extends Terminal { + + public Identifier(String s, SourcePosition posn) { + super(s, posn); + } + + public R visit(Visitor v, A o) { + return v.visitIdentifier(this, o); + } + + public Declaration decl; + public RuntimeEntity entity; +} diff --git a/src/miniJava/AbstractSyntaxTrees/IfStmt.java b/src/miniJava/AbstractSyntaxTrees/IfStmt.java index 7ceb5aa..f546cb2 100644 --- a/src/miniJava/AbstractSyntaxTrees/IfStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/IfStmt.java @@ -1,32 +1,32 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class IfStmt extends Statement { - public IfStmt(Expression b, Statement t, Statement e, SourcePosition posn) { - super(posn); - cond = b; - thenStmt = t; - elseStmt = e; - } - - public IfStmt(Expression b, Statement t, SourcePosition posn) { - super(posn); - cond = b; - thenStmt = t; - elseStmt = null; - } - - public R visit(Visitor v, A o) { - return v.visitIfStmt(this, o); - } - - public Expression cond; - public Statement thenStmt; - public Statement elseStmt; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class IfStmt extends Statement { + public IfStmt(Expression b, Statement t, Statement e, SourcePosition posn) { + super(posn); + cond = b; + thenStmt = t; + elseStmt = e; + } + + public IfStmt(Expression b, Statement t, SourcePosition posn) { + super(posn); + cond = b; + thenStmt = t; + elseStmt = null; + } + + public R visit(Visitor v, A o) { + return v.visitIfStmt(this, o); + } + + public Expression cond; + public Statement thenStmt; + public Statement elseStmt; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/IndexedRef.java b/src/miniJava/AbstractSyntaxTrees/IndexedRef.java index a52a014..d009e2c 100644 --- a/src/miniJava/AbstractSyntaxTrees/IndexedRef.java +++ b/src/miniJava/AbstractSyntaxTrees/IndexedRef.java @@ -1,24 +1,24 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class IndexedRef extends Reference { - - public IndexedRef(Reference ref, Expression expr, SourcePosition posn) { - super(posn); - this.ref = ref; - this.indexExpr = expr; - } - - public R visit(Visitor v, A o) { - return v.visitIndexedRef(this, o); - } - - public Reference ref; - public Expression indexExpr; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class IndexedRef extends Reference { + + public IndexedRef(Reference ref, Expression expr, SourcePosition posn) { + super(posn); + this.ref = ref; + this.indexExpr = expr; + } + + public R visit(Visitor v, A o) { + return v.visitIndexedRef(this, o); + } + + public Reference ref; + public Expression indexExpr; +} diff --git a/src/miniJava/AbstractSyntaxTrees/IntLiteral.java b/src/miniJava/AbstractSyntaxTrees/IntLiteral.java index 2e0e0d1..8b97e8e 100644 --- a/src/miniJava/AbstractSyntaxTrees/IntLiteral.java +++ b/src/miniJava/AbstractSyntaxTrees/IntLiteral.java @@ -1,19 +1,19 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class IntLiteral extends Literal { - - public IntLiteral(String s, SourcePosition posn) { - super(s, posn); - } - - public R visit(Visitor v, A o) { - return v.visitIntLiteral(this, o); - } +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class IntLiteral extends Literal { + + public IntLiteral(String s, SourcePosition posn) { + super(s, posn); + } + + public R visit(Visitor v, A o) { + return v.visitIntLiteral(this, o); + } } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/Literal.java b/src/miniJava/AbstractSyntaxTrees/Literal.java index 5c0f5cc..ae727fc 100644 --- a/src/miniJava/AbstractSyntaxTrees/Literal.java +++ b/src/miniJava/AbstractSyntaxTrees/Literal.java @@ -1,15 +1,15 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public abstract class Literal extends Terminal { - - public Literal(String spelling, SourcePosition posn) { - super(spelling, posn); - } -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public abstract class Literal extends Terminal { + + public Literal(String spelling, SourcePosition posn) { + super(spelling, posn); + } +} diff --git a/src/miniJava/AbstractSyntaxTrees/LiteralExpr.java b/src/miniJava/AbstractSyntaxTrees/LiteralExpr.java index 83c26d1..70aad01 100644 --- a/src/miniJava/AbstractSyntaxTrees/LiteralExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/LiteralExpr.java @@ -1,21 +1,21 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class LiteralExpr extends Expression { - public LiteralExpr(Literal c, SourcePosition posn) { - super(posn); - literal = c; - } - - public R visit(Visitor v, A o) { - return v.visitLiteralExpr(this, o); - } - - public Literal literal; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class LiteralExpr extends Expression { + public LiteralExpr(Literal c, SourcePosition posn) { + super(posn); + literal = c; + } + + public R visit(Visitor v, A o) { + return v.visitLiteralExpr(this, o); + } + + public Literal literal; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/LocalDecl.java b/src/miniJava/AbstractSyntaxTrees/LocalDecl.java index d03b6c2..8968ac0 100644 --- a/src/miniJava/AbstractSyntaxTrees/LocalDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/LocalDecl.java @@ -1,16 +1,16 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public abstract class LocalDecl extends Declaration { - - public LocalDecl(String name, Type t, SourcePosition posn) { - super(name, t, posn); - } - -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public abstract class LocalDecl extends Declaration { + + public LocalDecl(String name, Type t, SourcePosition posn) { + super(name, t, posn); + } + +} diff --git a/src/miniJava/AbstractSyntaxTrees/MemberDecl.java b/src/miniJava/AbstractSyntaxTrees/MemberDecl.java index a199a86..5a2df13 100644 --- a/src/miniJava/AbstractSyntaxTrees/MemberDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/MemberDecl.java @@ -1,27 +1,27 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -abstract public class MemberDecl extends Declaration { - - public MemberDecl(boolean isPrivate, boolean isStatic, Type mt, - String name, SourcePosition posn) { - super(name, mt, posn); - this.isPrivate = isPrivate; - this.isStatic = isStatic; - } - - public MemberDecl(MemberDecl md, SourcePosition posn) { - super(md.name, md.type, posn); - this.isPrivate = md.isPrivate; - this.isStatic = md.isStatic; - } - - public boolean isPrivate; - public boolean isStatic; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +abstract public class MemberDecl extends Declaration { + + public MemberDecl(boolean isPrivate, boolean isStatic, Type mt, + String name, SourcePosition posn) { + super(name, mt, posn); + this.isPrivate = isPrivate; + this.isStatic = isStatic; + } + + public MemberDecl(MemberDecl md, SourcePosition posn) { + super(md.name, md.type, posn); + this.isPrivate = md.isPrivate; + this.isStatic = md.isStatic; + } + + public boolean isPrivate; + public boolean isStatic; +} diff --git a/src/miniJava/AbstractSyntaxTrees/MethodDecl.java b/src/miniJava/AbstractSyntaxTrees/MethodDecl.java index 54ab4e5..71c58a2 100644 --- a/src/miniJava/AbstractSyntaxTrees/MethodDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/MethodDecl.java @@ -1,27 +1,27 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class MethodDecl extends MemberDecl { - - public MethodDecl(MemberDecl md, ParameterDeclList pl, StatementList sl, - Expression e, SourcePosition posn) { - super(md, posn); - parameterDeclList = pl; - statementList = sl; - returnExp = e; - } - - public R visit(Visitor v, A o) { - return v.visitMethodDecl(this, o); - } - - public ParameterDeclList parameterDeclList; - public StatementList statementList; - public Expression returnExp; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class MethodDecl extends MemberDecl { + + public MethodDecl(MemberDecl md, ParameterDeclList pl, StatementList sl, + Expression e, SourcePosition posn) { + super(md, posn); + parameterDeclList = pl; + statementList = sl; + returnExp = e; + } + + public R visit(Visitor v, A o) { + return v.visitMethodDecl(this, o); + } + + public ParameterDeclList parameterDeclList; + public StatementList statementList; + public Expression returnExp; +} diff --git a/src/miniJava/AbstractSyntaxTrees/MethodDeclList.java b/src/miniJava/AbstractSyntaxTrees/MethodDeclList.java index 41bb12f..bf79e72 100644 --- a/src/miniJava/AbstractSyntaxTrees/MethodDeclList.java +++ b/src/miniJava/AbstractSyntaxTrees/MethodDeclList.java @@ -1,37 +1,32 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import java.util.*; - -public class MethodDeclList implements Iterable { - public MethodDeclList() { - methodDeclList = new ArrayList(); - } - - public MethodDeclList(MethodDecl m) { - methodDeclList = new ArrayList(); - methodDeclList.add(m); - } - - public void add(MethodDecl cd) { - methodDeclList.add(cd); - } - - public MethodDecl get(int i) { - return methodDeclList.get(i); - } - - public int size() { - return methodDeclList.size(); - } - - public Iterator iterator() { - return methodDeclList.iterator(); - } - - private List methodDeclList; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import java.util.*; + +public class MethodDeclList implements Iterable { + public MethodDeclList() { + methodDeclList = new ArrayList(); + } + + public void add(MethodDecl cd) { + methodDeclList.add(cd); + } + + public MethodDecl get(int i) { + return methodDeclList.get(i); + } + + public int size() { + return methodDeclList.size(); + } + + public Iterator iterator() { + return methodDeclList.iterator(); + } + + private List methodDeclList; +} diff --git a/src/miniJava/AbstractSyntaxTrees/NewArrayExpr.java b/src/miniJava/AbstractSyntaxTrees/NewArrayExpr.java index 398c18e..52a8934 100644 --- a/src/miniJava/AbstractSyntaxTrees/NewArrayExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/NewArrayExpr.java @@ -1,23 +1,23 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class NewArrayExpr extends NewExpr { - public NewArrayExpr(Type et, Expression e, SourcePosition posn) { - super(posn); - eltType = et; - sizeExpr = e; - } - - public R visit(Visitor v, A o) { - return v.visitNewArrayExpr(this, o); - } - - public Type eltType; - public Expression sizeExpr; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class NewArrayExpr extends NewExpr { + public NewArrayExpr(Type et, Expression e, SourcePosition posn) { + super(posn); + eltType = et; + sizeExpr = e; + } + + public R visit(Visitor v, A o) { + return v.visitNewArrayExpr(this, o); + } + + public Type eltType; + public Expression sizeExpr; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/NewExpr.java b/src/miniJava/AbstractSyntaxTrees/NewExpr.java index 62c271d..9842110 100644 --- a/src/miniJava/AbstractSyntaxTrees/NewExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/NewExpr.java @@ -1,15 +1,15 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public abstract class NewExpr extends Expression { - - public NewExpr(SourcePosition posn) { - super(posn); - } -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public abstract class NewExpr extends Expression { + + public NewExpr(SourcePosition posn) { + super(posn); + } +} diff --git a/src/miniJava/AbstractSyntaxTrees/NewObjectExpr.java b/src/miniJava/AbstractSyntaxTrees/NewObjectExpr.java index 9217ebf..82ea4ea 100644 --- a/src/miniJava/AbstractSyntaxTrees/NewObjectExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/NewObjectExpr.java @@ -1,21 +1,21 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class NewObjectExpr extends NewExpr { - public NewObjectExpr(ClassType ct, SourcePosition posn) { - super(posn); - classtype = ct; - } - - public R visit(Visitor v, A o) { - return v.visitNewObjectExpr(this, o); - } - - public ClassType classtype; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class NewObjectExpr extends NewExpr { + public NewObjectExpr(ClassType ct, SourcePosition posn) { + super(posn); + classtype = ct; + } + + public R visit(Visitor v, A o) { + return v.visitNewObjectExpr(this, o); + } + + public ClassType classtype; +} diff --git a/src/miniJava/AbstractSyntaxTrees/Operator.java b/src/miniJava/AbstractSyntaxTrees/Operator.java index 00016ab..f570d02 100644 --- a/src/miniJava/AbstractSyntaxTrees/Operator.java +++ b/src/miniJava/AbstractSyntaxTrees/Operator.java @@ -1,23 +1,22 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; -import miniJava.SyntacticAnalyzer.Token; - -public class Operator extends Terminal { - - public Operator(Token t, SourcePosition posn) { - super(t.spelling, posn); - token = t; - } - - public R visit(Visitor v, A o) { - return v.visitOperator(this, o); - } - - public Token token; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; +import miniJava.SyntacticAnalyzer.Token; + +public class Operator extends Terminal { + + public Operator(Token t, SourcePosition posn) { + super(t.spelling, posn); + } + + public R visit(Visitor v, A o) { + return v.visitOperator(this, o); + } + + public Token token; +} diff --git a/src/miniJava/AbstractSyntaxTrees/Package.java b/src/miniJava/AbstractSyntaxTrees/Package.java index 974564c..638d322 100644 --- a/src/miniJava/AbstractSyntaxTrees/Package.java +++ b/src/miniJava/AbstractSyntaxTrees/Package.java @@ -1,22 +1,22 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class Package extends AST { - - public Package(ClassDeclList cdl, SourcePosition posn) { - super(posn); - classDeclList = cdl; - } - - public R visit(Visitor v, A o) { - return v.visitPackage(this, o); - } - - public ClassDeclList classDeclList; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class Package extends AST { + + public Package(ClassDeclList cdl, SourcePosition posn) { + super(posn); + classDeclList = cdl; + } + + public R visit(Visitor v, A o) { + return v.visitPackage(this, o); + } + + public ClassDeclList classDeclList; +} diff --git a/src/miniJava/AbstractSyntaxTrees/ParameterDecl.java b/src/miniJava/AbstractSyntaxTrees/ParameterDecl.java index 56655e4..ba454e2 100644 --- a/src/miniJava/AbstractSyntaxTrees/ParameterDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/ParameterDecl.java @@ -1,19 +1,19 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class ParameterDecl extends LocalDecl { - - public ParameterDecl(Type t, String name, SourcePosition posn) { - super(name, t, posn); - } - - public R visit(Visitor v, A o) { - return v.visitParameterDecl(this, o); - } -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class ParameterDecl extends LocalDecl { + + public ParameterDecl(Type t, String name, SourcePosition posn) { + super(name, t, posn); + } + + public R visit(Visitor v, A o) { + return v.visitParameterDecl(this, o); + } +} diff --git a/src/miniJava/AbstractSyntaxTrees/ParameterDeclList.java b/src/miniJava/AbstractSyntaxTrees/ParameterDeclList.java index 9612836..2b80ada 100644 --- a/src/miniJava/AbstractSyntaxTrees/ParameterDeclList.java +++ b/src/miniJava/AbstractSyntaxTrees/ParameterDeclList.java @@ -1,37 +1,32 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import java.util.*; - -public class ParameterDeclList implements Iterable { - public ParameterDeclList() { - parameterDeclList = new ArrayList(); - } - - public ParameterDeclList(ParameterDecl p) { - parameterDeclList = new ArrayList(); - parameterDeclList.add(p); - } - - public void add(ParameterDecl s) { - parameterDeclList.add(s); - } - - public ParameterDecl get(int i) { - return parameterDeclList.get(i); - } - - public int size() { - return parameterDeclList.size(); - } - - public Iterator iterator() { - return parameterDeclList.iterator(); - } - - private List parameterDeclList; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import java.util.*; + +public class ParameterDeclList implements Iterable { + public ParameterDeclList() { + parameterDeclList = new ArrayList(); + } + + public void add(ParameterDecl s) { + parameterDeclList.add(s); + } + + public ParameterDecl get(int i) { + return parameterDeclList.get(i); + } + + public int size() { + return parameterDeclList.size(); + } + + public Iterator iterator() { + return parameterDeclList.iterator(); + } + + private List parameterDeclList; +} diff --git a/src/miniJava/AbstractSyntaxTrees/QualifiedRef.java b/src/miniJava/AbstractSyntaxTrees/QualifiedRef.java index c147f79..74192a7 100644 --- a/src/miniJava/AbstractSyntaxTrees/QualifiedRef.java +++ b/src/miniJava/AbstractSyntaxTrees/QualifiedRef.java @@ -1,25 +1,25 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class QualifiedRef extends Reference { - - public QualifiedRef(Reference ref, Identifier id, SourcePosition posn) { - super(posn); - this.ref = ref; - this.id = id; - } - - @Override - public R visit(Visitor v, A o) { - return v.visitQualifiedRef(this, o); - } - - public Reference ref; - public Identifier id; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class QualifiedRef extends Reference { + + public QualifiedRef(Reference ref, Identifier id, SourcePosition posn) { + super(posn); + this.ref = ref; + this.id = id; + } + + @Override + public R visit(Visitor v, A o) { + return v.visitQualifiedRef(this, o); + } + + public Reference ref; + public Identifier id; +} diff --git a/src/miniJava/AbstractSyntaxTrees/RefExpr.java b/src/miniJava/AbstractSyntaxTrees/RefExpr.java index 4f289b2..2d570e2 100644 --- a/src/miniJava/AbstractSyntaxTrees/RefExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/RefExpr.java @@ -1,21 +1,21 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class RefExpr extends Expression { - public RefExpr(Reference r, SourcePosition posn) { - super(posn); - ref = r; - } - - public R visit(Visitor v, A o) { - return v.visitRefExpr(this, o); - } - - public Reference ref; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class RefExpr extends Expression { + public RefExpr(Reference r, SourcePosition posn) { + super(posn); + ref = r; + } + + public R visit(Visitor v, A o) { + return v.visitRefExpr(this, o); + } + + public Reference ref; +} diff --git a/src/miniJava/AbstractSyntaxTrees/Reference.java b/src/miniJava/AbstractSyntaxTrees/Reference.java index 7998896..c373659 100644 --- a/src/miniJava/AbstractSyntaxTrees/Reference.java +++ b/src/miniJava/AbstractSyntaxTrees/Reference.java @@ -1,18 +1,19 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.CodeGenerator.RuntimeEntity; -import miniJava.SyntacticAnalyzer.SourcePosition; - -public abstract class Reference extends AST { - public Reference(SourcePosition posn) { - super(posn); - } - - public Declaration decl; - public RuntimeEntity entity; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.CodeGenerator.RuntimeEntity; +import miniJava.SyntacticAnalyzer.SourcePosition; + +public abstract class Reference extends AST { + public Reference(SourcePosition posn) { + super(posn); + } + + public String spelling; + public Declaration decl; + public RuntimeEntity entity; +} diff --git a/src/miniJava/AbstractSyntaxTrees/Statement.java b/src/miniJava/AbstractSyntaxTrees/Statement.java index e8db4cb..6d332b0 100644 --- a/src/miniJava/AbstractSyntaxTrees/Statement.java +++ b/src/miniJava/AbstractSyntaxTrees/Statement.java @@ -1,16 +1,16 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public abstract class Statement extends AST { - - public Statement(SourcePosition posn) { - super(posn); - } - -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public abstract class Statement extends AST { + + public Statement(SourcePosition posn) { + super(posn); + } + +} diff --git a/src/miniJava/AbstractSyntaxTrees/StatementList.java b/src/miniJava/AbstractSyntaxTrees/StatementList.java index b6bd1d9..d2fbfb8 100644 --- a/src/miniJava/AbstractSyntaxTrees/StatementList.java +++ b/src/miniJava/AbstractSyntaxTrees/StatementList.java @@ -1,32 +1,32 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import java.util.*; - -public class StatementList implements Iterable { - public StatementList() { - slist = new ArrayList(); - } - - public void add(Statement s) { - slist.add(s); - } - - public Statement get(int i) { - return slist.get(i); - } - - public int size() { - return slist.size(); - } - - public Iterator iterator() { - return slist.iterator(); - } - - private List slist; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import java.util.*; + +public class StatementList implements Iterable { + public StatementList() { + slist = new ArrayList(); + } + + public void add(Statement s) { + slist.add(s); + } + + public Statement get(int i) { + return slist.get(i); + } + + public int size() { + return slist.size(); + } + + public Iterator iterator() { + return slist.iterator(); + } + + private List slist; +} diff --git a/src/miniJava/AbstractSyntaxTrees/Terminal.java b/src/miniJava/AbstractSyntaxTrees/Terminal.java index fb28172..4ee4f21 100644 --- a/src/miniJava/AbstractSyntaxTrees/Terminal.java +++ b/src/miniJava/AbstractSyntaxTrees/Terminal.java @@ -1,18 +1,18 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -abstract public class Terminal extends AST { - - public Terminal(String s, SourcePosition posn) { - super(posn); - spelling = s; - } - - public String spelling; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +abstract public class Terminal extends AST { + + public Terminal(String s, SourcePosition posn) { + super(posn); + spelling = s; + } + + public String spelling; +} diff --git a/src/miniJava/AbstractSyntaxTrees/ThisRef.java b/src/miniJava/AbstractSyntaxTrees/ThisRef.java index 082340c..874a590 100644 --- a/src/miniJava/AbstractSyntaxTrees/ThisRef.java +++ b/src/miniJava/AbstractSyntaxTrees/ThisRef.java @@ -1,21 +1,21 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class ThisRef extends Reference { - - public ThisRef(SourcePosition posn) { - super(posn); - } - - @Override - public R visit(Visitor v, A o) { - return v.visitThisRef(this, o); - } - -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class ThisRef extends Reference { + + public ThisRef(SourcePosition posn) { + super(posn); + } + + @Override + public R visit(Visitor v, A o) { + return v.visitThisRef(this, o); + } + +} diff --git a/src/miniJava/AbstractSyntaxTrees/Type.java b/src/miniJava/AbstractSyntaxTrees/Type.java index ef45865..463bfb6 100644 --- a/src/miniJava/AbstractSyntaxTrees/Type.java +++ b/src/miniJava/AbstractSyntaxTrees/Type.java @@ -1,19 +1,19 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -abstract public class Type extends AST { - - public Type(TypeKind typ, SourcePosition posn) { - super(posn); - typeKind = typ; - } - - public TypeKind typeKind; - -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +abstract public class Type extends AST { + + public Type(TypeKind typ, SourcePosition posn) { + super(posn); + typeKind = typ; + } + + public TypeKind typeKind; + +} diff --git a/src/miniJava/AbstractSyntaxTrees/TypeKind.java b/src/miniJava/AbstractSyntaxTrees/TypeKind.java index 824ddbb..b9421bb 100644 --- a/src/miniJava/AbstractSyntaxTrees/TypeKind.java +++ b/src/miniJava/AbstractSyntaxTrees/TypeKind.java @@ -1,10 +1,10 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -public enum TypeKind { - VOID, INT, BOOLEAN, CLASS, ARRAY, UNSUPPORTED, ERROR, EQUALS, RELATIONAL; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +public enum TypeKind { + VOID, INT, BOOLEAN, CLASS, ARRAY, UNSUPPORTED, ERROR; +} diff --git a/src/miniJava/AbstractSyntaxTrees/UnaryExpr.java b/src/miniJava/AbstractSyntaxTrees/UnaryExpr.java index eeb8e56..ecf8504 100644 --- a/src/miniJava/AbstractSyntaxTrees/UnaryExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/UnaryExpr.java @@ -1,23 +1,23 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class UnaryExpr extends Expression { - public UnaryExpr(Operator o, Expression e, SourcePosition posn) { - super(posn); - operator = o; - expr = e; - } - - public R visit(Visitor v, A o) { - return v.visitUnaryExpr(this, o); - } - - public Operator operator; - public Expression expr; +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class UnaryExpr extends Expression { + public UnaryExpr(Operator o, Expression e, SourcePosition posn) { + super(posn); + operator = o; + expr = e; + } + + public R visit(Visitor v, A o) { + return v.visitUnaryExpr(this, o); + } + + public Operator operator; + public Expression expr; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/VarDecl.java b/src/miniJava/AbstractSyntaxTrees/VarDecl.java index 2be65c3..8231714 100644 --- a/src/miniJava/AbstractSyntaxTrees/VarDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/VarDecl.java @@ -1,19 +1,19 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class VarDecl extends LocalDecl { - - public VarDecl(Type t, String name, SourcePosition posn) { - super(name, t, posn); - } - - public R visit(Visitor v, A o) { - return v.visitVarDecl(this, o); - } -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class VarDecl extends LocalDecl { + + public VarDecl(Type t, String name, SourcePosition posn) { + super(name, t, posn); + } + + public R visit(Visitor v, A o) { + return v.visitVarDecl(this, o); + } +} diff --git a/src/miniJava/AbstractSyntaxTrees/VarDeclStmt.java b/src/miniJava/AbstractSyntaxTrees/VarDeclStmt.java index 3e74d70..56db252 100644 --- a/src/miniJava/AbstractSyntaxTrees/VarDeclStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/VarDeclStmt.java @@ -1,23 +1,23 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class VarDeclStmt extends Statement { - public VarDeclStmt(VarDecl vd, Expression e, SourcePosition posn) { - super(posn); - varDecl = vd; - initExp = e; - } - - public R visit(Visitor v, A o) { - return v.visitVardeclStmt(this, o); - } - - public VarDecl varDecl; - public Expression initExp; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class VarDeclStmt extends Statement { + public VarDeclStmt(VarDecl vd, Expression e, SourcePosition posn) { + super(posn); + varDecl = vd; + initExp = e; + } + + public R visit(Visitor v, A o) { + return v.visitVardeclStmt(this, o); + } + + public VarDecl varDecl; + public Expression initExp; +} diff --git a/src/miniJava/AbstractSyntaxTrees/Visitor.java b/src/miniJava/AbstractSyntaxTrees/Visitor.java index 2045d36..08c2541 100644 --- a/src/miniJava/AbstractSyntaxTrees/Visitor.java +++ b/src/miniJava/AbstractSyntaxTrees/Visitor.java @@ -1,80 +1,80 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -/** - * An implementation of the Visitor interface provides a method visitX for each - * non-abstract AST class X. - */ -public interface Visitor { - - // Package - public ResultType visitPackage(Package prog, ArgType arg); - - // Declarations - public ResultType visitClassDecl(ClassDecl cd, ArgType arg); - - public ResultType visitFieldDecl(FieldDecl fd, ArgType arg); - - public ResultType visitMethodDecl(MethodDecl md, ArgType arg); - - public ResultType visitParameterDecl(ParameterDecl pd, ArgType arg); - - public ResultType visitVarDecl(VarDecl decl, ArgType arg); - - // Types - public ResultType visitBaseType(BaseType type, ArgType arg); - - public ResultType visitClassType(ClassType type, ArgType arg); - - public ResultType visitArrayType(ArrayType type, ArgType arg); - - // Statements - public ResultType visitBlockStmt(BlockStmt stmt, ArgType arg); - - public ResultType visitVardeclStmt(VarDeclStmt stmt, ArgType arg); - - public ResultType visitAssignStmt(AssignStmt stmt, ArgType arg); - - public ResultType visitCallStmt(CallStmt stmt, ArgType arg); - - public ResultType visitIfStmt(IfStmt stmt, ArgType arg); - - public ResultType visitWhileStmt(WhileStmt stmt, ArgType arg); - - // Expressions - public ResultType visitUnaryExpr(UnaryExpr expr, ArgType arg); - - public ResultType visitBinaryExpr(BinaryExpr expr, ArgType arg); - - public ResultType visitRefExpr(RefExpr expr, ArgType arg); - - public ResultType visitCallExpr(CallExpr expr, ArgType arg); - - public ResultType visitLiteralExpr(LiteralExpr expr, ArgType arg); - - public ResultType visitNewObjectExpr(NewObjectExpr expr, ArgType arg); - - public ResultType visitNewArrayExpr(NewArrayExpr expr, ArgType arg); - - // References - public ResultType visitQualifiedRef(QualifiedRef ref, ArgType arg); - - public ResultType visitIndexedRef(IndexedRef ref, ArgType arg); - - public ResultType visitIdRef(IdRef ref, ArgType arg); - - public ResultType visitThisRef(ThisRef ref, ArgType arg); - - // Terminals - public ResultType visitIdentifier(Identifier id, ArgType arg); - - public ResultType visitOperator(Operator op, ArgType arg); - - public ResultType visitIntLiteral(IntLiteral num, ArgType arg); - - public ResultType visitBooleanLiteral(BooleanLiteral bool, ArgType arg); -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +/** + * An implementation of the Visitor interface provides a method visitX for each + * non-abstract AST class X. + */ +public interface Visitor { + + // Package + public ResultType visitPackage(Package prog, ArgType arg); + + // Declarations + public ResultType visitClassDecl(ClassDecl cd, ArgType arg); + + public ResultType visitFieldDecl(FieldDecl fd, ArgType arg); + + public ResultType visitMethodDecl(MethodDecl md, ArgType arg); + + public ResultType visitParameterDecl(ParameterDecl pd, ArgType arg); + + public ResultType visitVarDecl(VarDecl decl, ArgType arg); + + // Types + public ResultType visitBaseType(BaseType type, ArgType arg); + + public ResultType visitClassType(ClassType type, ArgType arg); + + public ResultType visitArrayType(ArrayType type, ArgType arg); + + // Statements + public ResultType visitBlockStmt(BlockStmt stmt, ArgType arg); + + public ResultType visitVardeclStmt(VarDeclStmt stmt, ArgType arg); + + public ResultType visitAssignStmt(AssignStmt stmt, ArgType arg); + + public ResultType visitCallStmt(CallStmt stmt, ArgType arg); + + public ResultType visitIfStmt(IfStmt stmt, ArgType arg); + + public ResultType visitWhileStmt(WhileStmt stmt, ArgType arg); + + // Expressions + public ResultType visitUnaryExpr(UnaryExpr expr, ArgType arg); + + public ResultType visitBinaryExpr(BinaryExpr expr, ArgType arg); + + public ResultType visitRefExpr(RefExpr expr, ArgType arg); + + public ResultType visitCallExpr(CallExpr expr, ArgType arg); + + public ResultType visitLiteralExpr(LiteralExpr expr, ArgType arg); + + public ResultType visitNewObjectExpr(NewObjectExpr expr, ArgType arg); + + public ResultType visitNewArrayExpr(NewArrayExpr expr, ArgType arg); + + // References + public ResultType visitQualifiedRef(QualifiedRef ref, ArgType arg); + + public ResultType visitIndexedRef(IndexedRef ref, ArgType arg); + + public ResultType visitIdRef(IdRef ref, ArgType arg); + + public ResultType visitThisRef(ThisRef ref, ArgType arg); + + // Terminals + public ResultType visitIdentifier(Identifier id, ArgType arg); + + public ResultType visitOperator(Operator op, ArgType arg); + + public ResultType visitIntLiteral(IntLiteral num, ArgType arg); + + public ResultType visitBooleanLiteral(BooleanLiteral bool, ArgType arg); +} diff --git a/src/miniJava/AbstractSyntaxTrees/WhileStmt.java b/src/miniJava/AbstractSyntaxTrees/WhileStmt.java index 3695b45..88d3a22 100644 --- a/src/miniJava/AbstractSyntaxTrees/WhileStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/WhileStmt.java @@ -1,23 +1,23 @@ -/** - * miniJava Abstract Syntax Tree classes - * @author prins - * @version COMP 520 (v2.2) - */ -package miniJava.AbstractSyntaxTrees; - -import miniJava.SyntacticAnalyzer.SourcePosition; - -public class WhileStmt extends Statement { - public WhileStmt(Expression b, Statement s, SourcePosition posn) { - super(posn); - cond = b; - body = s; - } - - public R visit(Visitor v, A o) { - return v.visitWhileStmt(this, o); - } - - public Expression cond; - public Statement body; -} +/** + * miniJava Abstract Syntax Tree classes + * @author prins + * @version COMP 520 (v2.2) + */ +package miniJava.AbstractSyntaxTrees; + +import miniJava.SyntacticAnalyzer.SourcePosition; + +public class WhileStmt extends Statement { + public WhileStmt(Expression b, Statement s, SourcePosition posn) { + super(posn); + cond = b; + body = s; + } + + public R visit(Visitor v, A o) { + return v.visitWhileStmt(this, o); + } + + public Expression cond; + public Statement body; +} diff --git a/src/miniJava/CodeGenerator/Code.java b/src/miniJava/CodeGenerator/Code.java new file mode 100644 index 0000000..fa32703 --- /dev/null +++ b/src/miniJava/CodeGenerator/Code.java @@ -0,0 +1,55 @@ +package miniJava.CodeGenerator; + +import mJAM.Machine; +import miniJava.AbstractSyntaxTrees.*; + +public class Code { + + public boolean addr; + public Declaration decl; + + /** + * If addr true, returns the address of the declaration. + * Otherwise, uses the size of the declaration in its place. + * @param op + * @param decl + * @param addr + */ + public Code(Declaration decl, boolean addr) { + this.decl = decl; + this.addr = addr; + } + + /** + * + * @param index + */ + public void modify(int instr) { + + // Setup size + switch(decl.type.typeKind) { + case ARRAY: + case CLASS: + Machine.code[instr].n = Machine.addressSize; + case INT: + Machine.code[instr].n = Machine.integerSize; + case BOOLEAN: + Machine.code[instr].n = Machine.booleanSize; + case VOID: + Machine.code[instr].n = 0; + default: + Machine.code[instr].n = -1; + } + + // Setup displacement + if(addr) { + Machine.code[instr].d += decl.entity.addr; + } else { + Machine.code[instr].d += decl.entity.size; + } + + // Setup register + Machine.code[instr].r = decl.entity.reg.ordinal(); + } + +} diff --git a/src/miniJava/CodeGenerator/Encoder.java b/src/miniJava/CodeGenerator/Encoder.java index 5773186..6ee76b6 100644 --- a/src/miniJava/CodeGenerator/Encoder.java +++ b/src/miniJava/CodeGenerator/Encoder.java @@ -1,94 +1,79 @@ package miniJava.CodeGenerator; +import java.util.HashMap; + import mJAM.Machine; import mJAM.Machine.*; import miniJava.AbstractSyntaxTrees.*; import miniJava.AbstractSyntaxTrees.Package; import miniJava.ContextualAnalyzer.Analyzer; -public class Encoder implements Visitor { +public class Encoder implements Visitor { - private int mdLBOffset = 0; - - // ///////////////////////////////////////////////////////////////////////////// - // - // Convenience Functions - // - // ///////////////////////////////////////////////////////////////////////////// + // Keeps track of variables placed on the stack + private int methodDataOffset = 0; + + // Maintains data to correct once completed traversal + private HashMap patches = new HashMap<>(); - /** - * Get size of type for declaration purposes. - * @param t - * @return - */ - private int getSize(Type t) { - switch(t.typeKind) { - case ARRAY: - case CLASS: - return Machine.addressSize; - case INT: - return Machine.integerSize; - case BOOLEAN: - return Machine.booleanSize; - case VOID: - return 0; - default: - return -1; - } - } - // ///////////////////////////////////////////////////////////////////////////// // // PACKAGE // // ///////////////////////////////////////////////////////////////////////////// - + @Override - public Integer visitPackage(Package prog, Integer arg) { + public Object visitPackage(Package prog, Integer arg) { - // Initialize static fields + Machine.initCodeGen(); + + // Initialize all static fields + int staticFieldsSize = 0; for(ClassDecl cd : prog.classDeclList) { for(int i = 0; i < cd.fieldDeclList.size(); i++) { - if(cd.fieldDeclList.get(i).isStatic) { - cd.fieldDeclList.get(i).visit(this, i); + FieldDecl fd = cd.fieldDeclList.get(i); + if(fd.isStatic) { + int size = getSize(fd.type); + fd.entity = new RuntimeEntity(size, staticFieldsSize, Reg.SB); + staticFieldsSize += size; } } } - int patch = Machine.nextInstrAddr(); - Machine.emit(Op.JUMP, Reg.CB, 0); - - // Initialize all classes and methods - for(ClassDecl cd : prog.classDeclList) { - cd.visit(this, 1); + if(staticFieldsSize > 0) { + Machine.emit(Op.PUSH, staticFieldsSize); } - // Link classes & build stack - Machine.patch(patch, Machine.nextInstrAddr()); + // Build Classes for(ClassDecl cd : prog.classDeclList) { int cdPatch = Machine.nextInstrAddr(); Machine.emit(Op.JUMP, Reg.CB, 0); - Machine.patch(cdPatch, cd.visit(this, 0)); + cd.visit(this, cdPatch); } // Build main function - mdLBOffset = Machine.linkDataSize; + methodDataOffset = Machine.linkDataSize; int mainPatch = Machine.nextInstrAddr(); Machine.emit(Op.JUMP, Reg.CB, 0); - Analyzer.mainMethod.visit(this, 0); - - + Analyzer.main.visit(this, null); + // Run main function int mainLabel = Machine.nextInstrAddr(); - RuntimeEntity main = Analyzer.mainMethod.entity; - + RuntimeEntity main = Analyzer.main.entity; + Machine.emit(Op.LOADL, Machine.nullRep); Machine.emit(Op.CALL, Reg.CB, main.addr); Machine.emit(Machine.Op.HALT, 0 ,0, 0); Machine.patch(mainPatch, mainLabel); - return 0; + // Patch up + for(Integer instr : patches.keySet()) { + Code c = patches.get(instr); + c.modify(instr); + } + + return null; } @@ -99,163 +84,128 @@ public class Encoder implements Visitor { // ///////////////////////////////////////////////////////////////////////////// @Override - public Integer visitClassDecl(ClassDecl cd, Integer init) { + public Object visitClassDecl(ClassDecl cd, Integer patch) { - /* Give an address to each method and class, so it can be referred - * to directly by jumping. - */ - if(init != 0) { - - // Get size of class - int size = 0; - for(FieldDecl fd : cd.fieldDeclList) { - if(!fd.isStatic) { - fd.visit(this, size); - size += getSize(fd.type); - } + // Get size of class + int size = 0; + for(FieldDecl fd : cd.fieldDeclList) { + if(!fd.isStatic) { + fd.visit(this, size); + size += fd.entity.size; } - - // Build Methods - for(MethodDecl md : cd.methodDeclList) { - md.visit(this, init); - } - - // Runtime Entity - int addr = Machine.nextInstrAddr(); - cd.entity = new RuntimeEntity(size, addr, Reg.CB, addr); - Machine.emit(Op.JUMP, Reg.CB, 0); - - return addr; - } + } // Build Instance Methods for(MethodDecl md : cd.methodDeclList) { - if(!md.isStatic) { - md.visit(this, 0); + if(md != Analyzer.main) { + md.visit(this, null); } } - // Build class descriptor - int label = Machine.nextInstrAddr(); - Machine.patch(cd.entity.instr, label); + // Build Class Descriptor + int addr = Machine.nextInstrAddr(); + Machine.patch(patch, addr); - Machine.emit(Op.LOADL, -1); // No superclasses allowed - Machine.emit(Op.LOADL, cd.entity.size); // Size of class - Machine.emit(Op.LOADA, Reg.CB, cd.entity.addr); // Address of class + Machine.emit(Op.LOADL, -1); // No superclasses allowed + Machine.emit(Op.LOADL, size); // Size of class + Machine.emit(Op.LOADA, Reg.CB, addr); // Address of class - return label; + // Save entity + cd.entity = new RuntimeEntity(size, addr, Reg.CB); + + return null; } @Override - public Integer visitFieldDecl(FieldDecl fd, Integer addr) { - + public Object visitFieldDecl(FieldDecl fd, Integer offset) { + + // Only non-static fields should ever reach this method int size = getSize(fd.type); - - // Static fields are placed onto the stack - if(fd.isStatic) { - fd.entity = new RuntimeEntity(size, addr, Reg.SB); - Machine.emit(Op.PUSH, size); - } else { - fd.entity = new RuntimeEntity(size, addr, Reg.OB); - } - - return 0; + fd.entity = new RuntimeEntity(size, offset, Reg.OB); + + return null; } - @Override - public Integer visitMethodDecl(MethodDecl md, Integer init) { + public Object visitMethodDecl(MethodDecl md, Integer arg) { - mdLBOffset = Machine.linkDataSize; + // Reset for next local LB + methodDataOffset = Machine.linkDataSize; - if(init != 0) { - int size = getSize(md.type); - int addr = Machine.nextInstrAddr(); - md.entity = new RuntimeEntity(size, addr, Reg.CB, addr); - Machine.emit(Op.JUMP, Reg.CB, 0); - } + // Save Entity + int size = getSize(md.type); + int addr = Machine.nextInstrAddr(); + md.entity = new RuntimeEntity(size, addr, Reg.CB); - else { - // Setup parameters - int paramS = 0; - for(ParameterDecl pd : md.parameterDeclList) { - paramS += getSize(md.type); - pd.visit(this, -paramS); - } - - // Setup body - int addr = Machine.nextInstrAddr(); - Machine.patch(md.entity.instr, addr); - for(Statement s : md.statementList) { - s.visit(this, 0); - } - - // Setup return statement - if(md.returnExp != null) { - md.returnExp.visit(this, 0); - } - - // Return from function - // Machine.emit(Op.HALT, 4, 0, 0); (See snapshot) - Machine.emit(Op.RETURN, md.entity.size, 0, paramS); + // Setup parameters + int parameterSize = 0; + for(ParameterDecl pd : md.parameterDeclList) { + parameterSize += getSize(pd.type); + pd.visit(this, -parameterSize); } - return 0; + // Build Body + for(Statement s : md.statementList) { + s.visit(this, null); + } + + // Setup Return + if(md.returnExp != null) { + md.returnExp.visit(this, null); + } + + Machine.emit(Op.RETURN, size, 0, parameterSize); + + return null; } - /** - * Note parameter addresses are negative to LB since they are - * placed onto the stack before emitting a CALL. - */ @Override - public Integer visitParameterDecl(ParameterDecl pd, Integer addr) { + public Object visitParameterDecl(ParameterDecl pd, Integer offset) { - // Builds runtime entity, offset at LB + // Builds runtime entity (should be negative of LB) int size = getSize(pd.type); - pd.entity = new RuntimeEntity(size, addr, Reg.LB); - - return 0; + pd.entity = new RuntimeEntity(size, offset, Reg.LB); + + return null; } - /** - * Variable declarations are never disposed (even in static closures). - */ @Override - public Integer visitVarDecl(VarDecl decl, Integer addr) { - + public Object visitVarDecl(VarDecl decl, Integer arg) { + // Builds runtime entity, offset at LB int size = getSize(decl.type); - decl.entity = new RuntimeEntity(size, addr, Reg.LB); + decl.entity = new RuntimeEntity(size, methodDataOffset, Reg.LB); // Allocates space on stack Machine.emit(Op.PUSH, size); - - return 0; + methodDataOffset += size; + + return null; } // ///////////////////////////////////////////////////////////////////////////// // // TYPES - // + // // ///////////////////////////////////////////////////////////////////////////// @Override - public Integer visitBaseType(BaseType type, Integer arg) { + public Object visitBaseType(BaseType type, Integer arg) { - return 0; + return null; } @Override - public Integer visitClassType(ClassType type, Integer arg) { + public Object visitClassType(ClassType type, Integer arg) { - return 0; + return null; } @Override - public Integer visitArrayType(ArrayType type, Integer arg) { + public Object visitArrayType(ArrayType type, Integer arg) { - return 0; + return null; } @@ -265,171 +215,187 @@ public class Encoder implements Visitor { // // ///////////////////////////////////////////////////////////////////////////// - /** - * We note a block statement may contain a variable declaration, - * that should go out of scope at the end of the statement. - * If the passed argument is 1, we indicate we want this to - * happen. - */ @Override - public Integer visitBlockStmt(BlockStmt stmt, Integer arg) { + public Object visitBlockStmt(BlockStmt stmt, Integer arg) { // Execute statements int size = 0; for(Statement s : stmt.sl) { - s.visit(this, 0); - - // Push variable declarations if necessary - if(arg == 1 && s instanceof VarDeclStmt) { - VarDeclStmt decl = (VarDeclStmt) s; - size += getSize(decl.varDecl.type); + s.visit(this, null); + if(s instanceof VarDeclStmt) { + VarDeclStmt vds = (VarDeclStmt) s; + size += vds.varDecl.entity.size; } } // Pop off variable declarations - Machine.emit(Op.POP, size); - - return 0; + if(size > 0) { + Machine.emit(Op.POP, size); + methodDataOffset -= size; + } + + return null; } - /** - * We declare the variable, place the RHS onto the stack, and - * replace the value of the variable with the top of the stack. - */ @Override - public Integer visitVardeclStmt(VarDeclStmt stmt, Integer arg) { - stmt.varDecl.visit(this, mdLBOffset); - stmt.initExp.visit(this, 0); + public Object visitVardeclStmt(VarDeclStmt stmt, Integer arg) { + + stmt.varDecl.visit(this, null); + stmt.initExp.visit(this, null); - // Assign value RuntimeEntity e = stmt.varDecl.entity; - Machine.emit(Op.STORE, e.size, e.register, e.addr); + Machine.emit(Op.STORE, e.size, e.reg, e.addr); - // Update position - mdLBOffset += getSize(stmt.varDecl.type); - - return 0; + return null; } @Override - public Integer visitAssignStmt(AssignStmt stmt, Integer arg) { + public Object visitAssignStmt(AssignStmt stmt, Integer arg) { - stmt.ref.visit(this, 0); + // Can potentially reach declaration directly + if(stmt.ref instanceof QualifiedRef) { + + QualifiedRef ref = (QualifiedRef) stmt.ref; + MemberDecl md = (MemberDecl) ref.id.decl; + + // Just access directly + if(md.isStatic) { + stmt.val.visit(this, null); + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.STORE, getSize(md.type), Reg.SB, 0); + + return null; + } + + // Access member directly + else if(ref.ref instanceof ThisRef) { + stmt.val.visit(this, null); + + int addr = Machine.nextInstrAddr(); + int size = getSize(ref.id.decl.type); + patches.put(addr, new Code(ref.id.decl, true)); + Machine.emit(Op.STORE, size, Reg.OB, 0); + + return null; + } + } + + // Must access member iteratively + stmt.ref.visit(this, 1); + stmt.val.visit(this, null); - // Setup - RuntimeEntity e = stmt.ref.entity; - - // Build code accordingly - if(stmt.ref instanceof QualifiedRef) { - e.parent.load(); - Machine.emit(Op.LOADL, e.addr); - stmt.val.visit(this, 0); + if(stmt.ref instanceof QualifiedRef) { Machine.emit(Prim.fieldupd); } else if(stmt.ref instanceof IndexedRef) { - IndexedRef ref = (IndexedRef) stmt.ref; - e.load(); - ref.indexExpr.visit(this, 0); - stmt.val.visit(this, 0); Machine.emit(Prim.arrayupd); } else if(stmt.ref instanceof IdRef) { - stmt.val.visit(this, 0); - Machine.emit(Op.STORE, e.size, e.register, e.addr); + int addr = Machine.nextInstrAddr(); + int size = getSize(stmt.ref.decl.type); + patches.put(addr, new Code(stmt.ref.decl, true)); + Machine.emit(Op.STORE, size, Reg.ZR, 0); } - return 0; + return null; } - /** - * The method in question can either be an instance or static - * function (it must be a MethodDecl). - */ @Override - public Integer visitCallStmt(CallStmt stmt, Integer arg) { + public Object visitCallStmt(CallStmt stmt, Integer arg) { MethodDecl md = (MethodDecl) stmt.methodRef.decl; // Request to print out if(md == Analyzer.println) { - stmt.argList.get(0).visit(this, 0); + stmt.argList.get(0).visit(this, null); Machine.emit(Prim.putintnl); - return 0; + return null; } // Push parameters on (must iterate in reverse order) for(int i = stmt.argList.size() - 1; i >= 0; i--) { - stmt.argList.get(i).visit(this, 0); + stmt.argList.get(i).visit(this, null); } - // Call Method - stmt.methodRef.visit(this, 0); + // Call method directly if(md.isStatic) { - Machine.emit(Op.CALL, Reg.CB, md.entity.addr); - } else { - stmt.methodRef.entity.call(); - Machine.emit(Op.CALLI, Reg.CB, md.entity.addr); + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.CALL, Reg.CB, 0); + } + + // Get address of qualified object + else { + if(stmt.methodRef instanceof QualifiedRef) { + QualifiedRef ref = (QualifiedRef) stmt.methodRef; + ref.ref.visit(this, null); + } else { + Machine.emit(Op.LOADA, Machine.addressSize, Reg.OB, 0); + } + + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.CALLI, Reg.CB, 0); } - return 0; + // Clear off stack if necessary + int returnSize = getSize(md.type); + if(returnSize > 0) { + Machine.emit(Op.POP, returnSize); + } + + return null; } @Override - public Integer visitIfStmt(IfStmt stmt, Integer arg) { + public Object visitIfStmt(IfStmt stmt, Integer arg) { - stmt.cond.visit(this, 0); + stmt.cond.visit(this, null); - // Build Then Statement + // Do not have to build as many jump instructions in this case + if(stmt.elseStmt == null) { + int ifPatch = Machine.nextInstrAddr(); + Machine.emit(Op.JUMPIF, Machine.falseRep, Reg.CB, 0); + + stmt.thenStmt.visit(this, null); + Machine.patch(ifPatch, Machine.nextInstrAddr()); + + return null; + } + + // Must jump out at end of 'if' clause int ifPatch = Machine.nextInstrAddr(); - Machine.emit(Op.JUMPIF, Machine.trueRep, Reg.CB, 0); - - int elsePatch = Machine.nextInstrAddr(); - Machine.emit(Op.JUMP, Reg.CB, 0); - - int thenLabel = Machine.nextInstrAddr(); - stmt.thenStmt.visit(this, 0); + Machine.emit(Op.JUMPIF, Machine.falseRep, Reg.CB, 0); + stmt.thenStmt.visit(this, null); int thenPatch = Machine.nextInstrAddr(); Machine.emit(Op.JUMP, Reg.CB, 0); - // Connect labels/patches - int endLabel = Machine.nextInstrAddr(); - Machine.patch(elsePatch, endLabel); + // Build 'else' clause + Machine.patch(ifPatch, Machine.nextInstrAddr()); + stmt.elseStmt.visit(this, null); + Machine.patch(thenPatch, Machine.nextInstrAddr()); - if(stmt.elseStmt != null) { - stmt.elseStmt.visit(this, 0); - endLabel = Machine.nextInstrAddr(); - } - - Machine.patch(ifPatch, thenLabel); - Machine.patch(thenPatch, endLabel); - - return 0; + return null; } - /** - * We note since the same declaration can be reached multiple times, we - * are forced to pop each declaration initialized. - */ @Override - public Integer visitWhileStmt(WhileStmt stmt, Integer arg) { + public Object visitWhileStmt(WhileStmt stmt, Integer arg) { // Must check the condition each loop int whileLabel = Machine.nextInstrAddr(); - stmt.cond.visit(this, 0); + stmt.cond.visit(this, null); // Jump out once condition fails int whileEndPatch = Machine.nextInstrAddr(); Machine.emit(Op.JUMPIF, Machine.falseRep, Reg.CB, 0); // Execute - stmt.body.visit(this, 1); + stmt.body.visit(this, null); Machine.emit(Op.JUMP, Reg.CB, whileLabel); Machine.patch(whileEndPatch, Machine.nextInstrAddr()); - - return 0; + + return null; } @@ -440,9 +406,9 @@ public class Encoder implements Visitor { // ///////////////////////////////////////////////////////////////////////////// @Override - public Integer visitUnaryExpr(UnaryExpr expr, Integer arg) { + public Object visitUnaryExpr(UnaryExpr expr, Integer arg) { - expr.expr.visit(this, 0); + expr.expr.visit(this, null); switch(expr.operator.spelling) { case "!": Machine.emit(Prim.not); @@ -452,115 +418,105 @@ public class Encoder implements Visitor { break; } - return 0; + return null; } @Override - public Integer visitBinaryExpr(BinaryExpr expr, Integer arg) { - expr.left.visit(this, 0); - expr.right.visit(this, 0); - expr.operator.visit(this, 0); + public Object visitBinaryExpr(BinaryExpr expr, Integer arg) { - return 0; - } - - @Override - public Integer visitRefExpr(RefExpr expr, Integer arg) { - - expr.ref.visit(this, 0); + String op = expr.operator.spelling; - // Build code accordingly - if(expr.ref instanceof QualifiedRef) { + if(op.equals("&&") || op.equals("||")) { + int rep = (op.equals("&&")) ? Machine.falseRep : Machine.trueRep; - // Must be requesting length of array - if(expr.ref.decl.type.typeKind == TypeKind.ARRAY) { - int size = Machine.integerSize; - int addr = expr.ref.entity.addr + size; - Machine.emit(Op.LOAD, size, Reg.LB, addr); - } else { - expr.ref.entity.load(); - } - } - - else if(expr.ref instanceof IndexedRef) { - IndexedRef ref = (IndexedRef) expr.ref; - ref.entity.load(); - ref.indexExpr.visit(this, 0); - Machine.emit(Prim.arrayref); - } - - else if(expr.ref instanceof ThisRef) { - RuntimeEntity e = expr.ref.entity; - Machine.emit(Op.LOADA, e.size, e.register, e.addr); + expr.left.visit(this, null); + int leftJump = Machine.nextInstrAddr(); + Machine.emit(Op.JUMPIF, rep, Reg.CB, 0); + + expr.right.visit(this, null); + expr.operator.visit(this, null); + + Machine.patch(leftJump, Machine.nextInstrAddr()); } else { - expr.ref.entity.load(); + expr.left.visit(this, null); + expr.right.visit(this, null); + expr.operator.visit(this, null); } - return 0; + return null; } @Override - public Integer visitCallExpr(CallExpr expr, Integer arg) { + public Object visitRefExpr(RefExpr expr, Integer arg) { + + expr.ref.visit(this, null); + + return null; + } + + @Override + public Object visitCallExpr(CallExpr expr, Integer arg) { + + MethodDecl md = (MethodDecl) expr.functionRef.decl; // Push parameters on (must iterate in reverse order) for(int i = expr.argList.size() - 1; i >= 0; i--) { - expr.argList.get(i).visit(this, 0); + expr.argList.get(i).visit(this, null); } - - // Call method - MethodDecl md = (MethodDecl) expr.functionRef.decl; - expr.functionRef.visit(this, 0); + + // Call Method if(md.isStatic) { - Machine.emit(Op.CALL, Reg.CB, md.entity.addr); + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.CALL, Reg.CB, 0); } else { - expr.functionRef.entity.call(); - Machine.emit(Op.CALLI, Reg.CB, md.entity.addr); + + if(expr.functionRef instanceof QualifiedRef) { + QualifiedRef ref = (QualifiedRef) expr.functionRef; + ref.ref.visit(this, null); + } else { + Machine.emit(Op.LOADA, Machine.addressSize, Reg.OB, 0); + } + + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.CALLI, Reg.CB, 0); } - return 0; + return null; } @Override - public Integer visitLiteralExpr(LiteralExpr expr, Integer arg) { + public Object visitLiteralExpr(LiteralExpr expr, Integer arg) { - expr.literal.visit(this, 0); + expr.literal.visit(this, null); - return 0; + return null; } @Override - public Integer visitNewObjectExpr(NewObjectExpr expr, Integer arg) { - - RuntimeEntity e = expr.classtype.className.decl.entity; - Machine.emit(Op.LOADA, e.register, e.addr); - Machine.emit(Op.LOADL, e.size); + public Object visitNewObjectExpr(NewObjectExpr expr, Integer arg) { + + Declaration decl = expr.classtype.className.decl; + + patches.put(Machine.nextInstrAddr(), new Code(decl, true)); + Machine.emit(Op.LOADA, Reg.CB, 0); + + patches.put(Machine.nextInstrAddr(), new Code(decl, false)); + Machine.emit(Op.LOADL, 0); + Machine.emit(Prim.newobj); - return 0; + return null; } - /** - * Returns the address where the new array's size is being - * stored (as it cannot be easily accessed otherwise). - */ @Override - public Integer visitNewArrayExpr(NewArrayExpr expr, Integer arg) { - - // Setup - int addr = mdLBOffset; - int size = Machine.integerSize; - mdLBOffset += Machine.integerSize; - - // Add to stack - expr.sizeExpr.visit(this, 0); - - // Create new array - Machine.emit(Op.LOAD, size, Reg.LB, addr); + public Object visitNewArrayExpr(NewArrayExpr expr, Integer arg) { + + expr.sizeExpr.visit(this, null); Machine.emit(Prim.newarr); - return addr; + return null; } @@ -571,49 +527,91 @@ public class Encoder implements Visitor { // ///////////////////////////////////////////////////////////////////////////// @Override - public Integer visitQualifiedRef(QualifiedRef ref, Integer arg) { + public Object visitQualifiedRef(QualifiedRef ref, Integer arg) { - ref.ref.visit(this, 0); - - // Must be accessing length of an array + // Array type always returns value if(ref.ref.decl.type.typeKind == TypeKind.ARRAY) { - ref.decl = ref.ref.decl; - ref.entity = ref.ref.entity; - } - - // Access class member - else { - ref.entity = ref.id.decl.entity; - ref.entity.parent = ref.ref.entity; + + // Get address of object + if(ref.ref instanceof QualifiedRef) { + ref.ref.visit(this, null); + } else if(ref.ref instanceof ThisRef) { + patches.put(Machine.nextInstrAddr(), new Code(ref.id.decl, true)); + Machine.emit(Op.STORE, getSize(ref.id.decl.type), Reg.OB, 0); + } else { + patches.put(Machine.nextInstrAddr(), new Code(ref.ref.decl, true)); + Machine.emit(Op.LOAD, Machine.addressSize, Reg.LB, 0); + } + + Machine.emit(Op.LOADL, 1); + Machine.emit(Prim.sub); + Machine.emit(Op.LOADI, Machine.integerSize); + + return null; } - return 0; + MemberDecl md = (MemberDecl) ref.id.decl; + + // Assigning + if(arg != null) { + ref.ref.visit(this, null); + patches.put(Machine.nextInstrAddr(), new Code(ref.id.decl, true)); + Machine.emit(Op.LOADL, 0); + } + + // Retrieving + else if(md.isStatic) { + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.LOAD, getSize(md.type), Reg.SB, 0); + } else { + ref.ref.visit(this, null); + int addr = Machine.nextInstrAddr(); + patches.put(addr, new Code(ref.decl, true)); + + Machine.emit(Op.LOADL, 0); + Machine.emit(Prim.fieldref); + } + + return null; } @Override - public Integer visitIndexedRef(IndexedRef ref, Integer arg) { + public Object visitIndexedRef(IndexedRef ref, Integer arg) { + + ref.ref.visit(this, null); + ref.indexExpr.visit(this, null); + + // Retrieving + if(arg == null) { + Machine.emit(Prim.arrayref); + } + + return null; + } + + @Override + public Object visitIdRef(IdRef ref, Integer arg) { ref.entity = ref.decl.entity; - return 0; + // Retrieving + if(arg == null) { + int size = getSize(ref.decl.type); + int addr = Machine.nextInstrAddr(); + patches.put(addr, new Code(ref.decl, true)); + + Machine.emit(Op.LOAD, size, Reg.ZR, 0); + } + + return null; } @Override - public Integer visitIdRef(IdRef ref, Integer arg) { - - ref.entity = ref.decl.entity; + public Object visitThisRef(ThisRef ref, Integer arg) { - return 0; - } - - @Override - public Integer visitThisRef(ThisRef ref, Integer arg) { + Machine.emit(Op.LOADA, Machine.addressSize, Reg.OB, 0); - RuntimeEntity e = ref.decl.entity; - ref.entity = new RuntimeEntity(e.size, 0, Reg.OB); - ref.entity.indirect = true; - - return 0; + return null; } @@ -624,15 +622,15 @@ public class Encoder implements Visitor { // ///////////////////////////////////////////////////////////////////////////// @Override - public Integer visitIdentifier(Identifier id, Integer arg) { + public Object visitIdentifier(Identifier id, Integer arg) { - return 0; + return null; } @Override - public Integer visitOperator(Operator op, Integer arg) { + public Object visitOperator(Operator op, Integer arg) { - switch(op.token.spelling) { + switch(op.spelling) { case "+": Machine.emit(Prim.add); break; @@ -671,20 +669,20 @@ public class Encoder implements Visitor { break; } - return 0; + return null; } @Override - public Integer visitIntLiteral(IntLiteral num, Integer arg) { + public Object visitIntLiteral(IntLiteral num, Integer arg) { Integer lit = Integer.parseInt(num.spelling); Machine.emit(Op.LOADL, lit.intValue()); - return 0; + return null; } @Override - public Integer visitBooleanLiteral(BooleanLiteral bool, Integer arg) { + public Object visitBooleanLiteral(BooleanLiteral bool, Integer arg) { if(bool.spelling.equals("true")) { Machine.emit(Op.LOADL, Machine.trueRep); @@ -692,7 +690,35 @@ public class Encoder implements Visitor { Machine.emit(Op.LOADL, Machine.falseRep); } - return 0; + return null; + } + + + // ///////////////////////////////////////////////////////////////////////////// + // + // Convenience Methods + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * Get size of type for declaration purposes. + * @param t + * @return + */ + private int getSize(Type t) { + switch(t.typeKind) { + case ARRAY: + case CLASS: + return Machine.addressSize; + case INT: + return Machine.integerSize; + case BOOLEAN: + return Machine.booleanSize; + case VOID: + return 0; + default: + return -1; + } } } diff --git a/src/miniJava/CodeGenerator/RuntimeEntity.java b/src/miniJava/CodeGenerator/RuntimeEntity.java index a05ebce..8571a10 100644 --- a/src/miniJava/CodeGenerator/RuntimeEntity.java +++ b/src/miniJava/CodeGenerator/RuntimeEntity.java @@ -1,52 +1,19 @@ package miniJava.CodeGenerator; -import mJAM.Machine; -import mJAM.Machine.Op; -import mJAM.Machine.Prim; import mJAM.Machine.Reg; public class RuntimeEntity { + + public Reg reg; + public int size; + public int addr; - public int size = -1; // Size of type - public int addr = -1; // Position relative to register - public int instr = -1; // Instruction relative to CB - public Reg register = Reg.ZR; // Register to offset by + RuntimeEntity parent = null; - // For use with nested elements - public boolean indirect = false; - public RuntimeEntity parent = null; - - public RuntimeEntity(int size, int addr, Reg register) { - this(size, addr, register, -1); - } - - public RuntimeEntity(int size, int addr, Reg register, int instr) { + public RuntimeEntity(int size, int addr, Reg reg) { + this.reg = reg; this.size = size; this.addr = addr; - this.register = register; - this.instr = instr; } - // Load entity into memory (if this, should call LOADA) - public void load() { - if(parent != null) { - parent.load(); - Machine.emit(Op.LOADL, addr); - Machine.emit(Prim.fieldref); - } else { - if(indirect) { - Machine.emit(Op.LOADA, size, register, addr); - } else { - Machine.emit(Op.LOAD, size, register, addr); - } - } - } - - public void call() { - if(parent != null) { - parent.load(); - } else { - Machine.emit(Op.LOADA, size, Reg.OB, 0); - } - } } diff --git a/src/miniJava/Compiler.java b/src/miniJava/Compiler.java index f137eb9..2059ca1 100644 --- a/src/miniJava/Compiler.java +++ b/src/miniJava/Compiler.java @@ -1,13 +1,21 @@ package miniJava; -import java.io.*; +import java.io.FileReader; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.FileNotFoundException; -import mJAM.*; -import miniJava.SyntacticAnalyzer.*; +import mJAM.Disassembler; +import mJAM.Interpreter; +import mJAM.ObjectFile; +import miniJava.SyntacticAnalyzer.Scanner; +import miniJava.SyntacticAnalyzer.Parser; import miniJava.AbstractSyntaxTrees.Package; -import miniJava.ContextualAnalyzer.Analyzer; +import miniJava.AbstractSyntaxTrees.ASTDisplay; import miniJava.CodeGenerator.Encoder; -import miniJava.Exceptions.*; +import miniJava.ContextualAnalyzer.IdTable; +import miniJava.ContextualAnalyzer.Analyzer; +import miniJava.ContextualAnalyzer.Reporter; public class Compiler { @@ -26,15 +34,22 @@ public class Compiler { Scanner scanner = new Scanner(new BufferedReader(input)); Parser parser = new Parser(scanner); Package p = parser.parse(); - - // Identification/Type Checking - Analyzer analyzer = new Analyzer(); - analyzer.visitPackage(p, null); - int analyzed = analyzer.validate(); - // Begin Compilation to mJAM - if(analyzed == 0) { + // Display + ASTDisplay display = new ASTDisplay(); + display.showTree(p); + + // Contextual Analyzer + IdTable table = new IdTable(); + Analyzer analyzer = new Analyzer(); + analyzer.visitPackage(p, table); + + // Compilation + if(Reporter.error) { + System.exit(rc); + } else { + // Build mJAM assembly Encoder encoder = new Encoder(); encoder.visitPackage(p, null); @@ -43,23 +58,36 @@ public class Compiler { String objectFileName = args[0].substring(0, pos) + ".mJAM"; ObjectFile objF = new ObjectFile(objectFileName); if(objF.write()) { - System.out.println("***Object File Failed."); + Reporter.emit("Object File Failed."); } + + // create asm file using disassembler + String asmCodeFileName = "test.asm"; + System.out.print("Writing assembly file ... "); + Disassembler d = new Disassembler(objectFileName); + if (d.disassemble()) { + System.out.println("FAILED!"); + return; + } + else + System.out.println("SUCCEEDED"); + + // run + System.out.println("Running code ... "); + Interpreter.debug(objectFileName, asmCodeFileName); + + System.out.println("*** mJAM execution completed"); } - System.exit(analyzed); + System.exit(0); } catch (FileNotFoundException e) { - System.out.println("***" + e.getMessage()); + Reporter.emit(e.getMessage()); } catch (IOException e) { - System.out.println("***" + e.getMessage()); - } catch (ScanningException e) { - System.out.println("***" + e.getMessage()); - } catch (ParsingException e) { - System.out.println("***" + e.getMessage()); + Reporter.emit(e.getMessage()); } System.exit(rc); } -} +} \ No newline at end of file diff --git a/src/miniJava/ContextualAnalyzer/Analyzer.java b/src/miniJava/ContextualAnalyzer/Analyzer.java index 9a23e8a..65f4bff 100644 --- a/src/miniJava/ContextualAnalyzer/Analyzer.java +++ b/src/miniJava/ContextualAnalyzer/Analyzer.java @@ -1,68 +1,38 @@ package miniJava.ContextualAnalyzer; -import java.util.*; +import java.io.IOException; +import java.util.ArrayList; import miniJava.Compiler; -import miniJava.Exceptions.*; -import miniJava.SyntacticAnalyzer.*; -import miniJava.SyntacticAnalyzer.Scanner; import miniJava.AbstractSyntaxTrees.*; import miniJava.AbstractSyntaxTrees.Package; +import miniJava.SyntacticAnalyzer.Parser; +import miniJava.SyntacticAnalyzer.Scanner; -public class Analyzer implements Visitor { - - public static MethodDecl mainMethod = null; - public static MethodDecl println = null; +public class Analyzer implements Visitor { - // Notifies if handling predefined as opposed to user defined code - private boolean predefinedGen = true; + public Reporter reporter = new Reporter(); - // Keeps track of declarations - private VarDecl currentVarDecl = null; - private ClassDecl currentClassDecl = null; - private MethodDecl currentMethodDecl = null; + // Required Methods + public static MethodDecl main; + public static MethodDecl println; - // Keeps track of identifcatoin - private IdentificationTable table = new IdentificationTable(); - - // Keep track of all predefined names to handle + // Predefined private static ArrayList predefined; static { predefined = new ArrayList(); - predefined.add("class _PrintStream { public void println(int n){} }"); - predefined.add("class System { public static _PrintStream out; }"); predefined.add("class String { }"); + predefined.add("class _PrintStream { public void println(int n){} }"); + predefined.add("class System { public static _PrintStream out; }"); } - - /** - * Adds predefined names to topmost table. These names should not be allowed - * redefinition and must be ordered such that no class refers to one - * undeclared yet. - */ - public Analyzer() throws ParsingException, ScanningException { - for (String s : predefined) { - Scanner scanner = new Scanner(s); - Parser parser = new Parser(scanner); - parser.parse().visit(this, table); - } - predefinedGen = false; - } - - /** - * Checks that contextual analysis was successful or not, returning the - * proper error code in either case. - * - * @return - */ - public int validate() { - // Exactly one public static void main(String[] args) function must be declared - if (mainMethod == null) - Reporter.report(ErrorType.MAIN_UNDECLARED, null, null); - - return (Reporter.error) ? Compiler.rc : 0; - } - + + // Keep Track Of Declarations + private IdTable top = null; + private VarDecl currentVarDecl = null; + private ClassDecl currentClassDecl = null; + private MethodDecl currentMethodDecl = null; + // ///////////////////////////////////////////////////////////////////////////// // @@ -70,40 +40,44 @@ public class Analyzer implements Visitor { // // ///////////////////////////////////////////////////////////////////////////// - public Type visitPackage(Package prog, IdentificationTable arg) { - - /* - * Since classes and static methods/fields can be referenced before the - * classes themselves are declared, we preprocess all classes and - * methods first. - */ - for (ClassDecl cd : prog.classDeclList) { - - IdentificationTable cdTable = table.openScope(cd); - - if (cdTable != null) { - - // Simply add fields to current scope - for (FieldDecl fd : cd.fieldDeclList) { - cdTable.setDeclarationAtScope(fd); - } - - // Just Add Declaration (also creates another identification table) - for (MethodDecl md : cd.methodDeclList) { - cdTable.openScope(md); - } + @Override + public Type visitPackage(Package prog, IdTable table) { + + top = table; + + // Begin predefinitions + try { + for(String pd : predefined) { + Scanner scanner = new Scanner(pd, true); + Parser parser = new Parser(scanner); + ClassDecl cd = parser.parseClassDeclaration(); + + addDeclarations(cd, table); + cd.visit(this, table); } + } catch(IOException e) { + Reporter.emit("System Predefinitions Error!"); + System.exit(Compiler.rc); } - - // Begin Traversal - for (ClassDecl cd : prog.classDeclList) { - currentClassDecl = cd; + + // Add all second level declarations + for(ClassDecl cd : prog.classDeclList) { + addDeclarations(cd, table); + } + + // Begin traversal + for(ClassDecl cd : prog.classDeclList) { cd.visit(this, table); } + + // Check a main exists + if(main == null) { + Reporter.emit("Main method undeclared."); + } return null; } - + // ///////////////////////////////////////////////////////////////////////////// // @@ -111,228 +85,283 @@ public class Analyzer implements Visitor { // // ///////////////////////////////////////////////////////////////////////////// - public Type visitClassDecl(ClassDecl cd, IdentificationTable arg) { - - IdentificationTable cdTable = arg.getScope(cd); - - if (cdTable != null) { - - for (FieldDecl fd : cd.fieldDeclList) { - fd.visit(this, cdTable); - } - - for (MethodDecl md : cd.methodDeclList) { - currentMethodDecl = md; - md.visit(this, cdTable); - } - } - - return cd.type; - } - - public Type visitFieldDecl(FieldDecl fd, IdentificationTable arg) { - - // Must check that the type of the field can be identified - if (!table.classExists(fd.type)) { - Reporter.report(ErrorType.UNDECLARED_TYPE, fd.type, null); - } else if(fd.type.typeKind == TypeKind.VOID) { - Reporter.report(ErrorType.VOID_TYPE, fd.type, null); - } - - return fd.type; - } - - public Type visitMethodDecl(MethodDecl md, IdentificationTable arg) { + @Override + public Type visitClassDecl(ClassDecl cd, IdTable table) { - if(predefinedGen && md.name.equals("println")) { + currentClassDecl = cd; + + for(FieldDecl fd : cd.fieldDeclList) { + fd.visit(this, cd.table); + } + + for(MethodDecl md : cd.methodDeclList) { + md.visit(this, cd.table); + } + + return null; + } + + @Override + public Type visitFieldDecl(FieldDecl fd, IdTable table) { + + fd.type.visit(this, table); + if(fd.type.typeKind == TypeKind.VOID) { + Reporter.emit("Field " + fd.name + " at " + fd.posn + " cannot have type 'void'"); + } + + return null; + } + + @Override + public Type visitMethodDecl(MethodDecl md, IdTable table) { + + currentMethodDecl = md; + + // Save println method + if(println == null && md.name.equals("println")) { println = md; } - - // Check if a valid entry point to program - if (IdentificationTable.isMainMethod(md)) { - if (mainMethod != null) - Reporter.report(ErrorType.MULTIPLE_MAIN, md, mainMethod); - else - mainMethod = md; + + // Save main method + if(isMain(md)) { + if(main != null) { + Reporter.emit("Main at " + md.posn + " previously defined at " + main.posn); + } else { + main = md; + } } - - // Must check that the type of the method can be identified - if (!table.classExists(md.type)) { - Reporter.report(ErrorType.UNDECLARED_TYPE, md.type, null); - } - + // Continue Traversal - IdentificationTable mdTable = arg.getScope(md); - if (mdTable != null) { - for (ParameterDecl pd : md.parameterDeclList) - pd.visit(this, mdTable); - for (Statement s : md.statementList) - s.visit(this, mdTable); - - // Check that return type matches expected type - if (md.returnExp == null && md.type.typeKind != TypeKind.VOID) { - Reporter.report(ErrorType.NO_RETURN, md, null); - } else if (md.returnExp != null) { - Type returnType = md.returnExp.visit(this, mdTable); - IdentificationTable.match(md.type, returnType, true); + md.type.visit(this, table); + + for(ParameterDecl pd : md.parameterDeclList) { + pd.visit(this, md.table); + } + + for(Statement s : md.statementList) { + s.visit(this, md.table); + } + + // Check return status + if(md.type.typeKind != TypeKind.VOID && md.returnExp == null) { + Reporter.emit("Method " + md.name + " at " + md.posn + " must have a return expression"); + } else if(md.type.typeKind == TypeKind.VOID && md.returnExp != null) { + Reporter.emit("Method " + md.name + " at " + md.posn + " cannot have a return expression"); + } + + if(md.returnExp != null) { + Type returnType = md.returnExp.visit(this, md.table); + if(!match(returnType, md.type)) { + Reporter.emit("Expected " + md.type + " but got " + returnType + " at " + md.returnExp.posn); } } - return md.type; + return null; } - public Type visitParameterDecl(ParameterDecl pd, IdentificationTable arg) { - arg.setDeclarationAtScope(pd); - if (!table.classExists(pd.type)) { - Reporter.report(ErrorType.UNDECLARED_TYPE, pd.type, null); - } else if(pd.type.typeKind == TypeKind.VOID) { - Reporter.report(ErrorType.VOID_TYPE, pd.type, null); - } - - return pd.type; - } - - public Type visitVarDecl(VarDecl decl, IdentificationTable arg) { - arg.setDeclarationAtScope(decl); - if (!table.classExists(decl.type)) { - Reporter.report(ErrorType.UNDECLARED_TYPE, decl.type, null); - } else if(decl.type.typeKind == TypeKind.VOID) { - Reporter.report(ErrorType.VOID_TYPE, decl.type, null); + @Override + public Type visitParameterDecl(ParameterDecl pd, IdTable table) { + + table.add(pd); + pd.type.visit(this, table); + if(pd.type.typeKind == TypeKind.VOID) { + Reporter.emit("Parameter " + pd.name + " at " + pd.posn + " cannot have type 'void'"); } - return decl.type; + return null; } - + @Override + public Type visitVarDecl(VarDecl decl, IdTable table) { + + table.add(decl); + decl.type.visit(this, table); + if(decl.type.typeKind == TypeKind.VOID) { + Reporter.emit("Variable " + decl.name + " at " + decl.posn + " cannot have type 'void'"); + } + + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// // // TYPES // // ///////////////////////////////////////////////////////////////////////////// - - public Type visitBaseType(BaseType type, IdentificationTable arg) { - + + @Override + public Type visitBaseType(BaseType type, IdTable table) { + return type; } - public Type visitClassType(ClassType type, IdentificationTable arg) { - type.className.visit(this, arg); + @Override + public Type visitClassType(ClassType type, IdTable table) { + + type.className.visit(this, table); + + // Must check that the type is valid + String cn = type.className.spelling; + if(top.getDeclarationAtScope(cn) == null) { + Reporter.emit("Class '" + cn + "' undeclared at " + type.posn); + } + return type; } - public Type visitArrayType(ArrayType type, IdentificationTable arg) { - type.eltType.visit(this, arg); + @Override + public Type visitArrayType(ArrayType type, IdTable table) { + + type.eltType.visit(this, table); + return type; } - + // ///////////////////////////////////////////////////////////////////////////// // // STATEMENTS // // ///////////////////////////////////////////////////////////////////////////// - public Type visitBlockStmt(BlockStmt stmt, IdentificationTable arg) { - arg.pushLevel(); - for (Statement s : stmt.sl) - s.visit(this, arg); - arg.popLevel(); - + @Override + public Type visitBlockStmt(BlockStmt stmt, IdTable table) { + + table.push(); + + for(Statement s : stmt.sl) { + s.visit(this, table); + } + + table.pop(); + return null; } - // The stmt of the vardecl may not refer to the variable itself - public Type visitVardeclStmt(VarDeclStmt stmt, IdentificationTable arg) { - Type varDeclType = stmt.varDecl.visit(this, arg); + @Override + public Type visitVardeclStmt(VarDeclStmt stmt, IdTable table) { + + stmt.varDecl.visit(this, table); currentVarDecl = stmt.varDecl; - Type initExpType = stmt.initExp.visit(this, arg); - IdentificationTable.match(varDeclType, initExpType, true); + Type exprType = stmt.initExp.visit(this, table); currentVarDecl = null; - // Can't have a class reference as the sole rhs - if(stmt.initExp instanceof RefExpr && initExpType.typeKind == TypeKind.CLASS) { - RefExpr re = (RefExpr)stmt.initExp; - Declaration decl = table.getDeclarationAtScope(re.ref.decl.name); - if(decl != null) Reporter.report(ErrorType.CLASS_IDENTIFER, stmt, null); + // Types must match + if(!match(stmt.varDecl.type, exprType)) { + Reporter.emit("Expected " + stmt.varDecl.type + " but got " + exprType + " at " + stmt.initExp.posn); } - - return varDeclType; + + return null; } - public Type visitAssignStmt(AssignStmt stmt, IdentificationTable arg) { - Type refType = stmt.ref.visit(this, arg); - Type valType = stmt.val.visit(this, arg); - IdentificationTable.match(valType, refType, true); + @Override + public Type visitAssignStmt(AssignStmt stmt, IdTable table) { - if(stmt.ref.decl instanceof MethodDecl) - Reporter.report(ErrorType.FUNCTION_ASSIGNMENT, stmt.ref.decl, null); - - return refType; - } - - public Type visitCallStmt(CallStmt stmt, IdentificationTable arg) { - - Type methodType = stmt.methodRef.visit(this, arg); + Type refType = stmt.ref.visit(this, table); + Type valType = stmt.val.visit(this, table); - if(methodType.typeKind != TypeKind.ERROR) { - - // Check that parameter count is correct and each type is correct - MethodDecl decl = (MethodDecl) stmt.methodRef.decl; - if (decl.parameterDeclList.size() != stmt.argList.size()) { - Reporter.report(ErrorType.INVALID_PARAM_COUNT, stmt, decl); - } else { - for (int i = 0; i < stmt.argList.size(); i++) { - Type exprType = stmt.argList.get(i).visit(this, arg); - Type pdType = decl.parameterDeclList.get(i).type; - IdentificationTable.match(pdType, exprType, true); - } + if(!match(refType, valType)) { + Reporter.emit("Expected " + refType + " but got " + valType + " at " + stmt.posn); + } + + // Should never assign 'this' to anything + if(stmt.ref instanceof ThisRef) { + Reporter.emit("Cannot assign 'this' to a value at " + stmt.posn); + } + + // Should never assign a method a value + if(stmt.ref.decl instanceof MethodDecl) { + Reporter.emit("Cannot assign a method a value at " + stmt.posn); + } + + // Cannot assign array length field + if(stmt.ref instanceof QualifiedRef) { + QualifiedRef ref = (QualifiedRef) stmt.ref; + if(ref.ref.decl.type.typeKind == TypeKind.ARRAY && ref.id.spelling.equals("length")) { + Reporter.emit("'length' field cannot be changed at " + stmt.posn); } } - - return methodType; + + return null; } - public Type visitIfStmt(IfStmt stmt, IdentificationTable arg) { + @Override + public Type visitCallStmt(CallStmt stmt, IdTable table) { + + stmt.methodRef.visit(this, table); + + // Check valid parameter count + MethodDecl md = (MethodDecl) stmt.methodRef.decl; + if(md.parameterDeclList.size() != stmt.argList.size()) { + Reporter.emit("Expected " + md.parameterDeclList.size() + " parameters at " + stmt.posn); + return null; + } + + // Check parameter types match + for (int i = 0; i < stmt.argList.size(); i++) { + Expression e = stmt.argList.get(i); + Type exprType = e.visit(this, table); + ParameterDecl pd = md.parameterDeclList.get(i); - // The conditional statment must be a boolean - Type condType = stmt.cond.visit(this, arg); - IdentificationTable.match(new BaseType(TypeKind.BOOLEAN, null), condType, true); - - // A single vardecl cannot exist after a conditional statement - if (stmt.thenStmt instanceof VarDeclStmt) { - Reporter.report(ErrorType.SINGLE_VARCOND, stmt.thenStmt, null); - } else { - stmt.thenStmt.visit(this, arg); - if (stmt.elseStmt != null) { - if (stmt.elseStmt instanceof VarDeclStmt) { - Reporter.report(ErrorType.SINGLE_VARCOND, stmt.elseStmt, - null); - } else { - stmt.elseStmt.visit(this, arg); - } + if(!match(pd.type, exprType)) { + Reporter.emit("Parameter " + pd.name + " is of type " + pd.type + " but got " + exprType + " at " + e.posn); } } return null; } - public Type visitWhileStmt(WhileStmt stmt, IdentificationTable arg) { - - // The conditional statment must be a boolean - Type condType = stmt.cond.visit(this, arg); - IdentificationTable.match(new BaseType(TypeKind.BOOLEAN, null), condType, true); - - // A single vardecl cannot exist after a conditional statement - if (stmt.body instanceof VarDeclStmt) { - Reporter.report(ErrorType.SINGLE_VARCOND, stmt.body, null); - } else { - stmt.body.visit(this, arg); + @Override + public Type visitIfStmt(IfStmt stmt, IdTable table) { + + // Conditional statement must have type boolean + Type condType = stmt.cond.visit(this, table); + if(condType.typeKind != TypeKind.BOOLEAN) { + Reporter.emit("Expected boolean but got " + condType + " at " + condType.posn); + } + + // A single variable declaration not allowed after conditional statement + if(stmt.thenStmt instanceof VarDeclStmt) { + Reporter.emit("Variable declaration not allowed solely in 'then' clause at " + stmt.thenStmt.posn); + return null; + } + + stmt.thenStmt.visit(this, table); + + // Check else statement + if (stmt.elseStmt != null) { + if (stmt.elseStmt instanceof VarDeclStmt) { + Reporter.emit("Variable declaration not allowed solely in 'else' clause at " + stmt.elseStmt.posn); + return null; + } + + stmt.elseStmt.visit(this, table); } return null; } + @Override + public Type visitWhileStmt(WhileStmt stmt, IdTable table) { + + // Conditional statement must have type boolean + Type condType = stmt.cond.visit(this, table); + if(condType.typeKind != TypeKind.BOOLEAN) { + Reporter.emit("Expected boolean but got " + condType + " at " + condType.posn); + } + + if(stmt.body instanceof VarDeclStmt) { + Reporter.emit("Variable declaration not allowed solely in 'while' clause at " + stmt.body.posn); + return null; + } + + stmt.body.visit(this, table); + + return null; + } + // ///////////////////////////////////////////////////////////////////////////// // @@ -340,85 +369,153 @@ public class Analyzer implements Visitor { // // ///////////////////////////////////////////////////////////////////////////// - public Type visitUnaryExpr(UnaryExpr expr, IdentificationTable arg) { - Type opType = expr.operator.visit(this, arg); - Type exprType = expr.expr.visit(this, arg); - IdentificationTable.match(opType, exprType, true); - + @Override + public Type visitUnaryExpr(UnaryExpr expr, IdTable table) { + + Type exprType = expr.expr.visit(this, table); + Type opType = expr.operator.visit(this, table); + if(!match(exprType, opType)) { + String op = expr.operator.spelling; + Reporter.emit("Operator " + op + " applies to " + opType + " but got " + exprType + " at " + expr.posn); + } + return opType; } - public Type visitBinaryExpr(BinaryExpr expr, IdentificationTable arg) { - Type opType = expr.operator.visit(this, arg); - Type leftType = expr.left.visit(this, arg); - Type rightType = expr.right.visit(this, arg); + @Override + public Type visitBinaryExpr(BinaryExpr expr, IdTable table) { - // Both sides must be the same - if(opType.typeKind == TypeKind.EQUALS) { - IdentificationTable.match(leftType, rightType, true); - return new BaseType(TypeKind.BOOLEAN, opType.posn); - } + Type lType = expr.left.visit(this, table); + Type rType = expr.right.visit(this, table); - // Both sides must be integers - else if(opType.typeKind == TypeKind.RELATIONAL) { - BaseType bt = new BaseType(TypeKind.INT, opType.posn); - IdentificationTable.match(bt, leftType, true); - IdentificationTable.match(bt, rightType, true); - return new BaseType(TypeKind.BOOLEAN, opType.posn); - } - - // Both sides must match operator type - IdentificationTable.match(leftType, opType, true); - IdentificationTable.match(rightType, opType, true); - return opType; - } - - public Type visitRefExpr(RefExpr expr, IdentificationTable arg) { - Type exprType = expr.ref.visit(this, arg); - return exprType; - } - - public Type visitCallExpr(CallExpr expr, IdentificationTable arg) { - Type functionRefType = expr.functionRef.visit(this, arg); - - if(expr.functionRef.decl instanceof MethodDecl) { + BaseType type = null; + String op = expr.operator.spelling; + switch(op) { - MethodDecl decl = (MethodDecl) expr.functionRef.decl; - - // Check that parameter count is correct and each type is correct - if (decl.parameterDeclList.size() != expr.argList.size()) { - Reporter.report(ErrorType.INVALID_PARAM_COUNT, expr, decl); - } else { - for (int i = 0; i < expr.argList.size(); i++) { - Type exprType = expr.argList.get(i).visit(this, arg); - Type pdType = decl.parameterDeclList.get(i).type; - IdentificationTable.match(pdType, exprType, true); + // Equality Operators + case "==": + case "!=": + if(!match(lType, rType)) { + Reporter.emit("Left hand side must be of right hand side's type " + rType + " at " + expr.posn); } + return new BaseType(TypeKind.BOOLEAN, expr.posn); + + // Boolean Operators + case "&&": + case "||": + type = new BaseType(TypeKind.BOOLEAN, expr.posn); + break; + + // Integer operators + case ">": + case "<": + case "+": + case "-": + case "*": + case "/": + case "<=": + case ">=": + type = new BaseType(TypeKind.INT, expr.posn); + break; + + default: + return new BaseType(TypeKind.ERROR, expr.posn); + } + + // Make sure types match + if(!match(lType, type)) { + Reporter.emit("Expected " + type + " but got " + lType + " at " + expr.posn); + } + + if(!match(rType, type)) { + Reporter.emit("Expected " + type + " but got " + lType + " at " + expr.posn); + } + + // Resulting type + return expr.operator.visit(this, table); + } + + @Override + public Type visitRefExpr(RefExpr expr, IdTable table) { + + Type refType = expr.ref.visit(this, table); + Declaration decl = table.getDeclaration(expr.ref.spelling); + + // Should never reference a class name + if(decl instanceof ClassDecl) { + Reporter.emit("Class declaration referenced at " + expr.posn); + } + + // Should never reference a method name + else if(decl instanceof MethodDecl) { + Reporter.emit("Method declaration referenced at " + expr.posn); + } + + // Cannot access instance members in static context + if(!(expr.ref instanceof QualifiedRef) && decl instanceof FieldDecl) { + FieldDecl fd = (FieldDecl) decl; + if(currentMethodDecl.isStatic && !fd.isStatic) { + Reporter.emit("Cannot access instance member in static context at " + expr.posn); } - } else { - Reporter.report(ErrorType.NONFUNCTION_CALL, expr, null); } - return functionRefType; + return refType; } - public Type visitLiteralExpr(LiteralExpr expr, IdentificationTable arg) { - Type literalType = expr.literal.visit(this, arg); - return literalType; + @Override + public Type visitCallExpr(CallExpr expr, IdTable table) { + + Type refType = expr.functionRef.visit(this, table); + + // Check parameter count matches + MethodDecl md = (MethodDecl) expr.functionRef.decl; + if(md.parameterDeclList.size() != expr.argList.size()) { + Reporter.emit("Expected " + md.parameterDeclList.size() + " parameters at " + expr.posn); + return refType; + } + + // Check parameter types match + for (int i = 0; i < expr.argList.size(); i++) { + Expression e = expr.argList.get(i); + Type exprType = e.visit(this, table); + ParameterDecl pd = md.parameterDeclList.get(i); + + if(!match(pd.type, exprType)) { + Reporter.emit("Parameter " + pd.name + " is of type " + pd.type + " but got " + exprType + " at " + e.posn); + } + } + + return refType; } - public Type visitNewObjectExpr(NewObjectExpr expr, IdentificationTable arg) { - Type objectType = expr.classtype.visit(this, arg); - return objectType; + @Override + public Type visitLiteralExpr(LiteralExpr expr, IdTable table) { + + return expr.literal.visit(this, table); } - public Type visitNewArrayExpr(NewArrayExpr expr, IdentificationTable arg) { - Type sizeExprType = expr.sizeExpr.visit(this, arg); - if (sizeExprType.typeKind != TypeKind.INT) { - Reporter.report(ErrorType.INVALID_INDEX, expr.sizeExpr, null); + @Override + public Type visitNewObjectExpr(NewObjectExpr expr, IdTable table) { + + return expr.classtype.visit(this, table); + } + + @Override + public Type visitNewArrayExpr(NewArrayExpr expr, IdTable table) { + + // Arrays only of classes and integers + Type eltType = expr.eltType.visit(this, table); + if(eltType.typeKind != TypeKind.INT && eltType.typeKind != TypeKind.CLASS) { + Reporter.emit("Cannot create array of type " + eltType + " at " + expr.posn); + } + + // Size must be an integer value + Type sizeType = expr.sizeExpr.visit(this, table); + if (sizeType.typeKind != TypeKind.INT) { + BaseType type = new BaseType(TypeKind.INT, expr.sizeExpr.posn); + Reporter.emit("Expected " + type + " but got " + sizeType + " at " + type.posn); } - Type eltType = expr.eltType.visit(this, arg); return new ArrayType(eltType, expr.posn); } @@ -428,171 +525,166 @@ public class Analyzer implements Visitor { // REFERENCES // // ///////////////////////////////////////////////////////////////////////////// - - public Type visitQualifiedRef(QualifiedRef ref, IdentificationTable arg) { - Type refType = ref.ref.visit(this, arg); + @Override + public Type visitQualifiedRef(QualifiedRef ref, IdTable table) { - // Array types only have the single 'length' field + Type refType = ref.ref.visit(this, table); + + // Should not try and access a method in qualified manner + if(ref.ref.decl instanceof MethodDecl) { + Reporter.emit("Cannot use method " + ref.ref.decl.name + " in qualified manner at " + ref.ref.posn); + return new BaseType(TypeKind.ERROR, ref.ref.posn); + } + + // Array types can have a length field if(refType.typeKind == TypeKind.ARRAY) { if(!ref.id.spelling.equals("length")) { - Reporter.report(ErrorType.LENGTH, ref.id, null); - return refType; + Reporter.emit(ref.id.spelling + " attribute not available with arrays at " + ref.id.posn); + return new BaseType(TypeKind.ERROR, ref.id.posn); } return new BaseType(TypeKind.INT, ref.id.posn); - } - - // Note qualified ref's only make sense in the context of classes - else if(refType.typeKind != TypeKind.CLASS) { - if(refType.typeKind != TypeKind.ERROR) // Don't need to report multiple times - Reporter.report(ErrorType.TYPE_MISMATCH, new BaseType(TypeKind.CLASS, null), refType); - - return refType; - } - - // Try to find qualified member - Declaration qualified = ref.ref.decl; - ClassType qualType = (ClassType) qualified.type; - Declaration qualClassDecl = table.getDeclaration(qualType.className.spelling); - if(qualClassDecl == null) { - Reporter.report(ErrorType.UNDECLARED_TYPE, qualified.type, null); - return new BaseType(TypeKind.ERROR, qualified.posn); } - // Get member - IdentificationTable cdTable = table.getScope(qualClassDecl); - MemberDecl md = (MemberDecl) cdTable.getDeclarationAtScope(ref.id.spelling); - - // Check the member exists at all + // Otherwise, should have a class type + if(refType.typeKind != TypeKind.CLASS) { + Reporter.emit("Qualified reference not of type class or array at " + ref.posn); + return new BaseType(TypeKind.ERROR, ref.posn); + } + + // Get member in question + ClassType ct = (ClassType) refType; + ClassDecl cd = (ClassDecl) top.getDeclarationAtScope(ct.className.spelling); + if(cd == null) { + Reporter.emit("Accessing non-existant class at " + ct.posn); + return new BaseType(TypeKind.ERROR, ref.posn); + } + + MemberDecl md = (MemberDecl) cd.table.getDeclarationAtScope(ref.id.spelling); if(md == null) { - Reporter.report(ErrorType.UNDEFINED, ref.id, null); - return new BaseType(TypeKind.ERROR, ref.id.posn); - } - - // If the qualifed ref is a class declaration, members must be static (must check for 'this') - else if(qualified instanceof ClassDecl && !(ref.ref instanceof ThisRef)) { - if(!md.isStatic) { - Reporter.report(ErrorType.STATIC, md, ref.id); - return new BaseType(TypeKind.ERROR, ref.id.posn); - } else if(md.isPrivate) { - Reporter.report(ErrorType.VISIBILITY, md, ref.id); - return new BaseType(TypeKind.ERROR, ref.id.posn); - } + Reporter.emit("Accessing non-existant field at " + ref.id.posn); + return new BaseType(TypeKind.ERROR, ref.posn); } - // The member should not be a method, as this is unsupported - else if(qualified instanceof MethodDecl) { - Reporter.report(ErrorType.UNDEFINED, ref.id, null); + // Check if static member + Declaration decl = table.getDeclaration(ref.ref.spelling); + if(decl instanceof ClassDecl && !md.isStatic) { + Reporter.emit("Cannot access non-static member at " + ref.id.posn); } - - // Otherwise, we can assume the object is a variable and attempt to access members - else if(md.isPrivate && currentClassDecl != qualClassDecl) { - Reporter.report(ErrorType.VISIBILITY, md, ref.id); - return new BaseType(TypeKind.ERROR, ref.id.posn); + + // Check Visibility Status + if(md.isPrivate && cd != currentClassDecl) { + Reporter.emit("Cannot access private member at " + ref.id.posn); } - - ref.id.decl = md; + ref.decl = md; + ref.id.decl = md; + ref.spelling = ref.id.spelling; + return md.type; } - public Type visitIndexedRef(IndexedRef ref, IdentificationTable arg) { - - ArrayType refType = (ArrayType) ref.ref.visit(this, arg); - - // Make sure index is an integer - Type indexExprType = ref.indexExpr.visit(this, arg); - if (indexExprType.typeKind != TypeKind.INT) { - Reporter.report(ErrorType.INVALID_INDEX, ref.indexExpr, null); + @Override + public Type visitIndexedRef(IndexedRef ref, IdTable table) { + + Type refType = ref.ref.visit(this, table); + ref.spelling = ref.ref.spelling; + + // Must be an array type + if(refType.typeKind != TypeKind.ARRAY) { + Reporter.emit("Trying to index " + refType + " at " + ref.ref.posn); + return refType; + } + + // Index must be an integer value + Type indexType = ref.indexExpr.visit(this, table); + if(indexType.typeKind != TypeKind.INT) { + BaseType type = new BaseType(TypeKind.INT, ref.indexExpr.posn); + Reporter.emit("Expected " + type + " but got " + indexType + " at " + type.posn); + } + + // Array types can be of either classes or ints + ArrayType at = (ArrayType) refType; + if(at.eltType.typeKind == TypeKind.CLASS) { + ClassType ct = (ClassType) at.eltType; + ref.decl = table.getDeclaration(ct.className.spelling); + return ref.decl.type; + } else { + ref.decl = null; + return new BaseType(TypeKind.INT, ref.posn); } - - ref.decl = ref.ref.decl; - return refType.eltType; } - public Type visitIdRef(IdRef ref, IdentificationTable arg) { - Type idType = ref.id.visit(this, arg); + @Override + public Type visitIdRef(IdRef ref, IdTable table) { + + ref.id.visit(this, table); ref.decl = ref.id.decl; - - return idType; + ref.spelling = ref.id.spelling; + + return ref.decl.type; } - public Type visitThisRef(ThisRef ref, IdentificationTable arg) { + @Override + public Type visitThisRef(ThisRef ref, IdTable table) { + + ref.spelling = "this"; ref.decl = currentClassDecl; if(currentMethodDecl.isStatic) { - Reporter.report(ErrorType.THIS, ref, currentMethodDecl); + Reporter.emit("'this' cannot be referenced in a static context at " + ref.posn); } return ref.decl.type; } - + // ///////////////////////////////////////////////////////////////////////////// // // TERMINALS // // ///////////////////////////////////////////////////////////////////////////// - - public Type visitIdentifier(Identifier id, IdentificationTable arg) { - // Must check identifier is not of the same type being declared + @Override + public Type visitIdentifier(Identifier id, IdTable table) { + + // An variable cannot be used in its declaration if(currentVarDecl != null && currentVarDecl.name.equals(id.spelling)) { - Reporter.report(ErrorType.VARDECL_USED, id, currentVarDecl); - return new BaseType(TypeKind.ERROR, id.posn); + Reporter.emit("Cannot use variable in declaration at " + id.posn); } - - // Check if identifier can be found in current scope - Declaration decl = arg.getDeclarationAtScope(id.spelling); - if (decl != null) { id.decl = decl; return decl.type; } - // Access member and check visibility properties - Declaration d = arg.getDeclaration(id.spelling); - if(d == null) { - Reporter.report(ErrorType.UNDEFINED, id, null); - return new BaseType(TypeKind.ERROR, id.posn); - } else { - - // Can only be a member at this point - if(d.type.typeKind != TypeKind.CLASS) { - MemberDecl md = (MemberDecl) d; - - // A static method cannot access instance members - if(currentMethodDecl.isStatic && !md.isStatic) { - Reporter.report(ErrorType.STATIC, md, id); - return new BaseType(TypeKind.ERROR, id.posn); - } - - // If a member declaration is private, it must be a member of the current class - else if(md.isPrivate) { - - // Check if member is part of the current class - IdentificationTable cdTable = table.getScope(currentClassDecl); - if(cdTable.getDeclarationAtScope(md.name) == null) { - Reporter.report(ErrorType.VISIBILITY, md, id); - return new BaseType(TypeKind.ERROR, id.posn); - } - } - } - - id.decl = d; - return d.type; + // Try to find declaration (and abort if not found) + id.decl = table.getDeclaration(id.spelling); + if(id.decl == null) { + Reporter.emit(id.spelling + " undefined at " + id.posn); + System.exit(Compiler.rc); } + + // Cannot access instance method from static context + if(id.decl instanceof MemberDecl) { + MemberDecl md = (MemberDecl) id.decl; + if(currentMethodDecl.isStatic && !md.isStatic) { + Reporter.emit("Cannot access instance member " + md.name + " in a static context at " + id.posn); + } + } + + return id.decl.type; + } - public Type visitOperator(Operator op, IdentificationTable arg) { - - switch (op.token.spelling) { + @Override + public Type visitOperator(Operator op, IdTable table) { + switch(op.spelling) { case "!": case "&&": case "||": - return new BaseType(TypeKind.BOOLEAN, op.posn); - case ">": case "<": case "<=": case ">=": - return new BaseType(TypeKind.RELATIONAL, op.posn); + case "==": + case "!=": + return new BaseType(TypeKind.BOOLEAN, op.posn); case "+": case "-": @@ -600,22 +692,107 @@ public class Analyzer implements Visitor { case "/": return new BaseType(TypeKind.INT, op.posn); - case "==": - case "!=": - return new BaseType(TypeKind.EQUALS, op.posn); + default: + return new BaseType(TypeKind.ERROR, op.posn); } - - return null; } - public Type visitIntLiteral(IntLiteral num, IdentificationTable arg) { - + @Override + public Type visitIntLiteral(IntLiteral num, IdTable table) { + return new BaseType(TypeKind.INT, num.posn); } - public Type visitBooleanLiteral(BooleanLiteral bool, IdentificationTable arg) { - + @Override + public Type visitBooleanLiteral(BooleanLiteral bool, IdTable table) { + return new BaseType(TypeKind.BOOLEAN, bool.posn); } + + // ///////////////////////////////////////////////////////////////////////////// + // + // Convenience Functions + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + * @param cd + * @param table + */ + private void addDeclarations(ClassDecl cd, IdTable table) { + + table.add(cd); + cd.table = new IdTable(table); + + for(FieldDecl fd : cd.fieldDeclList) { + cd.table.add(fd); + } + + for(MethodDecl md : cd.methodDeclList) { + cd.table.add(md); + md.table = new IdTable(cd.table); + } + } + + /** + * + * @param md + * @return + */ + private boolean isMain(MethodDecl md) { + + // Correct Signature + if(!md.isPrivate && md.isStatic) { + if(md.type.typeKind == TypeKind.VOID) { + if(md.name.equals("main") && md.parameterDeclList.size() == 1) { + + // Check parameter declaration + ParameterDecl pd = md.parameterDeclList.get(0); + if(pd.type.typeKind == TypeKind.ARRAY) { + ArrayType at = (ArrayType) pd.type; + if(at.eltType.typeKind == TypeKind.CLASS) { + ClassType ct = (ClassType) at.eltType; + + return ct.className.spelling.equals("String"); + } + } + } + } + } + + return false; + } + + /** + * + * @param t1 + * @param t2 + * @return + */ + private boolean match(Type t1, Type t2) { + + if(t1.typeKind != t2.typeKind) { + return false; + } + + // Check Class Types match + else if(t1.typeKind == TypeKind.CLASS) { + ClassType c1 = (ClassType) t1; + ClassType c2 = (ClassType) t2; + + return c1.className.spelling.equals(c2.className.spelling); + } + + // Check Array Types match + else if(t1.typeKind == TypeKind.ARRAY) { + ArrayType a1 = (ArrayType) t1; + ArrayType a2 = (ArrayType) t2; + + return match(a1.eltType, a2.eltType); + } + + return true; + } } diff --git a/src/miniJava/ContextualAnalyzer/IdTable.java b/src/miniJava/ContextualAnalyzer/IdTable.java new file mode 100644 index 0000000..50da518 --- /dev/null +++ b/src/miniJava/ContextualAnalyzer/IdTable.java @@ -0,0 +1,127 @@ +package miniJava.ContextualAnalyzer; + +import java.util.HashMap; +import java.util.ArrayList; +import miniJava.Compiler; + +import miniJava.AbstractSyntaxTrees.*; + +/** + * + */ +public class IdTable { + + private IdTable parent; + private ArrayList> scope; + + + // ///////////////////////////////////////////////////////////////////////////// + // + // CONSTRUCTORS + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + */ + public IdTable() { + this(null); + } + + /** + * + * @param parent + */ + public IdTable(IdTable parent) { + this.parent = parent; + this.scope = new ArrayList<>(); + push(); + } + + + // ///////////////////////////////////////////////////////////////////////////// + // + // ACTIVE SCOPE + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + */ + public void pop() { + int last = scope.size() - 1; + scope.remove(last); + } + + /** + * + */ + public void push() { + HashMap nested = new HashMap<>(); + scope.add(nested); + } + + /** + * + */ + public void add(Declaration decl) { + for(int i = 0; i < scope.size(); i++) { + HashMap nest = scope.get(i); + if(nest.containsKey(decl.name)) { + + Declaration prev = nest.get(decl.name); + + if(decl instanceof ClassDecl) { + Reporter.report(decl, prev, "Class"); + } else if(decl instanceof FieldDecl) { + Reporter.report(decl, prev, "Field"); + } else if(decl instanceof MethodDecl) { + Reporter.report(decl, prev, "Method"); + } else if(decl instanceof ParameterDecl) { + Reporter.report(decl, prev, "Parameter"); + } else if(decl instanceof VarDecl) { + Reporter.report(decl, prev, "Variable"); + } + + System.exit(Compiler.rc); + } + } + + scope.get(scope.size()-1).put(decl.name, decl); + } + + + // ///////////////////////////////////////////////////////////////////////////// + // + // GETTERS + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + * @param name + */ + public Declaration getDeclaration(String name) { + IdTable current = this; + while (current != null) { + Declaration decl = current.getDeclarationAtScope(name); + if (decl == null) current = current.parent; + else return decl; + } + + return null; + } + + /** + * + * @param name + */ + public Declaration getDeclarationAtScope(String name) { + for (int i = scope.size() - 1; i >= 0; i--) { + HashMap nest = scope.get(i); + if (nest.containsKey(name)) return nest.get(name); + } + + return null; + } +} diff --git a/src/miniJava/ContextualAnalyzer/IdentificationTable.java b/src/miniJava/ContextualAnalyzer/IdentificationTable.java deleted file mode 100644 index 6faa248..0000000 --- a/src/miniJava/ContextualAnalyzer/IdentificationTable.java +++ /dev/null @@ -1,221 +0,0 @@ -package miniJava.ContextualAnalyzer; - -import java.util.*; - -import miniJava.AbstractSyntaxTrees.*; - -public class IdentificationTable { - - private IdentificationTable parent; - private HashMap scope; - private ArrayList> table; - - /** - * - */ - public IdentificationTable() { - this(null); - } - - /** - * - * @param parent - */ - public IdentificationTable(IdentificationTable parent) { - this.parent = parent; - this.scope = new HashMap(); - this.table = new ArrayList>(); - this.table.add(new HashMap()); - } - - /** - * Adds another level for variables to be stored at - */ - public void popLevel() { - table.remove(table.size() - 1); - } - - /** - * Removes all variables declared at the current level - */ - public void pushLevel() { - table.add(new HashMap()); - } - - /** - * This method will only ever be called with class/method declarations. - * - * @param decl - * @return - */ - public IdentificationTable openScope(Declaration decl) { - Declaration current = getDeclarationAtScope(decl.name); - if (scope.containsKey(decl.name) || current != null) { - Reporter.report(ErrorType.REDEFINITION, decl, current); - return null; - } else { - table.get(table.size() - 1).put(decl.name, decl); - scope.put(decl.name, new IdentificationTable(this)); - return scope.get(decl.name); - } - } - - /** - * Return nested scope corresponding to declaration (or null if - * non-existant). - * - * @param decl - * @return - */ - public IdentificationTable getScope(Declaration decl) { - if (scope.containsKey(decl.name)) { - return scope.get(decl.name); - } - - return null; - } - - /** - * Iterates through all parents and tries to find the specified declaration - * by name. - * - * @param name - * @return - */ - public Declaration getDeclaration(String name) { - IdentificationTable current = this; - while (current != null) { - Declaration decl = current.getDeclarationAtScope(name); - if (decl == null) current = current.parent; - else return decl; - } - - return null; - } - - /** - * Iterates through levels (from higher to lower) for declaration, returning - * none if it does not exist. - * - * @param name - * @return - */ - public Declaration getDeclarationAtScope(String name) { - for (int i = table.size() - 1; i >= 0; i--) { - HashMap level = table.get(i); - if (level.containsKey(name)) return level.get(name); - } - - return null; - } - - /** - * Add declaration to current table's table member. - * - * @param name - */ - public void setDeclarationAtScope(Declaration decl) { - for (int i = 0; i < table.size(); i++) { - HashMap level = table.get(i); - if (level.containsKey(decl.name)) { - Declaration defined = level.get(decl.name); - Reporter.report(ErrorType.REDEFINITION, decl, defined); - return; - } - } - - table.get(table.size() - 1).put(decl.name, decl); - } - - /** - * Checks whether the specified class has been declared. - * - * @param t - * @return - */ - public boolean classExists(Type t) { - if (t.typeKind == TypeKind.CLASS) { - ClassType ct = (ClassType) t; - return getDeclaration(ct.className.spelling) != null; - } - - return true; - } - - /** - * Determines whether two types match. - * - * @param t1 - * @param t2 - * @return - */ - public static boolean match(Type t1, Type t2) { - return IdentificationTable.match(t1, t2, false); - } - - /** - * Determines whether two type match, reporting an error if they do not. - * - * @param t1 - * @param t2 - * @param report - * @return - */ - public static boolean match(Type t1, Type t2, boolean report) { - - if (t1.typeKind != t2.typeKind) { - if (report) Reporter.report(ErrorType.TYPE_MISMATCH, t1, t2); - return false; - } - - // Check Class Types match - else if (t1.typeKind == TypeKind.CLASS) { - ClassType c1 = (ClassType) t1; - ClassType c2 = (ClassType) t2; - if (!c1.className.spelling.equals(c2.className.spelling)) { - if (report) Reporter.report(ErrorType.TYPE_MISMATCH, t1, t2); - return false; - } - } - - // Check array types match - else if (t1.typeKind == TypeKind.ARRAY) { - ArrayType a1 = (ArrayType) t1; - ArrayType a2 = (ArrayType) t2; - if (!IdentificationTable.match(a1.eltType, a2.eltType)) { - if (report) Reporter.report(ErrorType.TYPE_MISMATCH, t1, t2); - return false; - } - } - - return true; - } - - /** - * Determines if the passed method is a valid entry point for the - * compilation phase. - * - * @param md - * @return - */ - public static boolean isMainMethod(MethodDecl md) { - - // Check Declaration - if (!md.isPrivate && md.isStatic && md.type.typeKind == TypeKind.VOID - && md.name.equals("main") && md.parameterDeclList.size() == 1) { - - // Check Parameter Declaration - ParameterDecl pd = md.parameterDeclList.get(0); - - if (pd.type.typeKind != TypeKind.ARRAY) return false; - ArrayType at = (ArrayType) pd.type; - - if (at.eltType.typeKind != TypeKind.CLASS) return false; - ClassType ct = (ClassType) at.eltType; - - return ct.className.spelling.equals("String"); - } - - return false; - } -} diff --git a/src/miniJava/ContextualAnalyzer/Reporter.java b/src/miniJava/ContextualAnalyzer/Reporter.java index 66fd900..0b65f4b 100644 --- a/src/miniJava/ContextualAnalyzer/Reporter.java +++ b/src/miniJava/ContextualAnalyzer/Reporter.java @@ -1,205 +1,27 @@ package miniJava.ContextualAnalyzer; -import miniJava.AbstractSyntaxTrees.*; - -enum ErrorType { - THIS, - LENGTH, - VOID_TYPE, - CLASS_IDENTIFER, - VARDECL_USED, - NONFUNCTION_CALL, - FUNCTION_ASSIGNMENT, - UNDEFINED, - STATIC, - VISIBILITY, - NO_RETURN, - TYPE_MISMATCH, - REDEFINITION, - MAIN_UNDECLARED, - INVALID_PARAM_COUNT, - MULTIPLE_MAIN, - UNDECLARED_TYPE, - SINGLE_VARCOND, - INVALID_INDEX -} +import miniJava.AbstractSyntaxTrees.Declaration; public class Reporter { - + public static boolean error = false; - + /** - * Convenience function for getting type names. - * - * @param t - * @return - */ - private static String getTypeName(Type t) { - if (t instanceof ClassType) { - ClassType ct = (ClassType) t; - return ct.className.spelling; - } else if (t instanceof ArrayType) { - ArrayType at = (ArrayType) t; - return getTypeName(at.eltType); - } - - return t.typeKind.toString(); - } - - /** - * Convenience method for formatting error message. * * @param message */ - private static void emit(String message) { + public static void emit(String message) { + error = true; System.out.println("***" + message); } - + /** - * Convenience function for managing all error types. - * - * @param type - * @param a1 - * @param a2 + * Redefinitions + * @param d1 + * @param d2 */ - public static void report(ErrorType type, AST a1, AST a2) { - - switch (type) { - - // Cannot access 'this' in a static method - case THIS: { - MethodDecl md = (MethodDecl) a2; - emit("Cannot reference 'this' " + a1.posn + " in static method '" + md.name + "' " + md.posn); - break; - } - - // Array types have the single field 'length' - case LENGTH: { - emit("Array types have only a single field 'length' (at " + a1.posn + ")."); - break; - } - - // Can't use a class as an identifier solely - case CLASS_IDENTIFER: { - emit("Cannot use class identifier outside of a qualified reference at " + a1.posn); - break; - } - - // Cannot have a parameter of type void - case VOID_TYPE: { - emit("Cannot have a parameter of type void at " + a1.posn); - break; - } - - // Attempting to call a non function as a function - case NONFUNCTION_CALL: { - emit("Not a valid function call at " + a1.posn); - break; - } - - // Cannot assign a value to a function - case FUNCTION_ASSIGNMENT: { - emit("Cannot assign a value to a function at " + a1.posn); - break; - } - - // Tried accessing a non-static member from a static method - case STATIC: { - MemberDecl md = (MemberDecl) a1; - Identifier ident = (Identifier) a2; - emit("'" + md.name + "' " + md.posn + " is an instance member and cannot be accessed at " + ident.posn); - break; - } - - // Tried accessing a private member of a different class - case VISIBILITY: { - MemberDecl md = (MemberDecl) a1; - Identifier ident = (Identifier) a2; - emit("'" + md.name + "' " + md.posn + " is a private member and cannot be accessed at " + ident.posn); - break; - } - - // Non-void function does not have a return statement - case NO_RETURN: { - MethodDecl md = (MethodDecl) a1; - emit("'" + md.name + "' " + md.posn + " must have a return statement"); - break; - } - - // The passed types are not the same - case TYPE_MISMATCH: { - String name1 = getTypeName((Type) a1); - String name2 = getTypeName((Type) a2); - if(a1 instanceof ArrayType) name1 += " Array"; - if(a2 instanceof ArrayType) name2 += " Array"; - emit("Expected type '" + name1 + "' but got '" + name2 + "' " + a2.posn); - break; - } - - // Attempting to redeclare a variable - case REDEFINITION: { - emit("Variable at " + a1.posn + " already declared earlier at " + a2.posn); - break; - } - - // Identifier could not be found - case UNDEFINED: { - Identifier ident = (Identifier) a1; - emit("Identifier '" + ident.spelling + "' " + ident.posn + " is undeclared."); - break; - } - - // A public static void main(String[] args) method was not declared - case MAIN_UNDECLARED: { - emit("A main function was not declared"); - break; - } - - // Parameter counts of an expression/statement do not match declaration - case INVALID_PARAM_COUNT: { - MethodDecl md = (MethodDecl) a2; - emit("Call to '" + md.name + "' " + a2.posn + " has an invalid parameter count at " + a1.posn); - break; - } - - // A public static void main(String[] args) was declared more than once - case MULTIPLE_MAIN: { - emit("Main function at " + a1.posn + " already declared previously at " + a2.posn); - break; - } - - // A reference has been made to a non-existant type - case UNDECLARED_TYPE: { - if(a1 instanceof Type) { - String typeName = getTypeName((Type) a1); - emit("'" + typeName + "' " + a1.posn + " has not been declared previously"); - } else { - emit("Identifier at " + a1.posn + " could not be identified"); - } - - break; - } - - // A Variable Declaration Statement was made as the only statement of a condition - case SINGLE_VARCOND: { - emit("Conditional statment cannot be followed by a variable declaration statement exclusively " + a1.posn); - break; - } - - // An indexed expression must be of an int type - case INVALID_INDEX: { - emit("Index expression is not of type int " + a1.posn); - break; - } - - // A variable declaration identifier was used in a var decl statement - case VARDECL_USED: { - emit("Identifier at " + a1.posn + " cannot refer to the variable declaration at " + a2.posn); - break; - } - } - - error = true; + public static void report(Declaration d1, Declaration d2, String prefix) { + emit(prefix + " at " + d1.posn + " previously defined at " + d2.posn); } } diff --git a/src/miniJava/Exceptions/IdentificationException.java b/src/miniJava/Exceptions/IdentificationException.java deleted file mode 100644 index 167ee93..0000000 --- a/src/miniJava/Exceptions/IdentificationException.java +++ /dev/null @@ -1,10 +0,0 @@ -package miniJava.Exceptions; - -public class IdentificationException extends Exception { - - private static final long serialVersionUID = 1L; - - public IdentificationException() { - super("Identification Error!"); - } -} diff --git a/src/miniJava/Exceptions/ParsingException.java b/src/miniJava/Exceptions/ParsingException.java deleted file mode 100644 index f655358..0000000 --- a/src/miniJava/Exceptions/ParsingException.java +++ /dev/null @@ -1,17 +0,0 @@ -package miniJava.Exceptions; - -import miniJava.SyntacticAnalyzer.Token; - -public class ParsingException extends Exception { - - private static final long serialVersionUID = 1L; - - public ParsingException() { - super("Unidentified parsing error!"); - } - - public ParsingException(Token t) { - super("Parsing error with " + t.spelling + " at " + t.posn.toString()); - } - -} diff --git a/src/miniJava/Exceptions/ScanningException.java b/src/miniJava/Exceptions/ScanningException.java deleted file mode 100644 index a24b2e2..0000000 --- a/src/miniJava/Exceptions/ScanningException.java +++ /dev/null @@ -1,11 +0,0 @@ -package miniJava.Exceptions; - -public class ScanningException extends Exception { - - private static final long serialVersionUID = 1L; - - public ScanningException(int col, int line) { - super("Scanning error at Column: " + col + ", Line: " + line); - } - -} diff --git a/src/miniJava/SyntacticAnalyzer/Parser.java b/src/miniJava/SyntacticAnalyzer/Parser.java index b06176b..524163f 100644 --- a/src/miniJava/SyntacticAnalyzer/Parser.java +++ b/src/miniJava/SyntacticAnalyzer/Parser.java @@ -1,28 +1,94 @@ package miniJava.SyntacticAnalyzer; +import java.io.IOException; import java.util.LinkedList; import miniJava.AbstractSyntaxTrees.*; import miniJava.AbstractSyntaxTrees.Package; -import miniJava.Exceptions.*; +/** + * Stratified Grammar (original grammar in PA1): + * + * Program ::= (ClassDeclaration)* eot + * + * ClassDeclaration ::= + * class id { + * (Declarators id (; | MethodDeclaration))* + * } + * + * MethodDeclaration ::= + * (ParameterList?) { + * Statement* (return Expression ;)? + * } + * + * Declarators ::= (public | private)? static? Type + * + * Type ::= boolean | void | int ([])? | id ([])? + * + * ParameterList ::= Type id (, Type id)* + * + * ArgumentList ::= Expression (, Expression)* + * + * Reference ::= BaseRef (. id ([ Expression])?)* + * + * BaseRef ::= this | id ([ Expression])? + * + * Statement ::= + * {Statement*} + * | Type id = Expression; + * | Reference = Expression; + * | Reference ( ArgumentList? ); + * | if (Expression) Statement (else Statement)? + * | while (Expression) Statement + * + * Expression ::= + * num | true | false + * | ( Expression ) + * | new (id() | int [ Expression ] | id [ Expression ] ) + * | Reference ((ArgumentList?))? + * | DExpression + * + * DExpression ::= CExpression (|| CExpression)* + * + * CExpression ::= EExpression (&& EExpression)* + * + * EExpression ::= RExpression ((==|!=) RExpression)* + * + * RExpression ::= AExpression ((<=|<|>|>=) AExpression)* + * + * AExpression ::= MExpression ((+|-) MExpression)* + * + * MExpression ::= Expression ((*|/) Expression)* + * +*/ public class Parser { - + private Scanner scanner; private LinkedList stream; - + + /** + * + * @param scanner + */ public Parser(Scanner scanner) { this.scanner = scanner; this.stream = new LinkedList(); } - + + + // ///////////////////////////////////////////////////////////////////////////// + // + // Package + // + // ///////////////////////////////////////////////////////////////////////////// + /** - * Program ::= (ClassDeclaration)* eot + * * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - public Package parse() throws ParsingException, ScanningException { + public Package parse() throws IOException { + ClassDeclList decls = new ClassDeclList(); while (peek(1).type == Token.TYPE.CLASS) { decls.add(parseClassDeclaration()); @@ -31,469 +97,557 @@ public class Parser { accept(Token.TYPE.EOT); return new Package(decls, new SourcePosition(0, 0)); } + + + // ///////////////////////////////////////////////////////////////////////////// + // + // DECLARATIONS + // + // ///////////////////////////////////////////////////////////////////////////// /** - * ClassDeclaration ::= class id { (Declarators id (; | MethodDeclaration))* } + * * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private ClassDecl parseClassDeclaration() throws ParsingException, - ScanningException { - + public ClassDecl parseClassDeclaration() throws IOException { + // Class Header Token classToken = accept(Token.TYPE.CLASS); - String cn = accept(Token.TYPE.ID).spelling; + String className = accept(Token.TYPE.ID).spelling; + + // Class Body accept(Token.TYPE.LBRACKET); - - // Setup + FieldDeclList fdl = new FieldDeclList(); MethodDeclList mdl = new MethodDeclList(); - - // Class Body + + // Haven't reached end of body while (peek(1).type != Token.TYPE.RBRACKET) { Declarators d = parseDeclarators(); - String name = accept(Token.TYPE.ID).spelling; - FieldDecl f = new FieldDecl(d.isPrivate, d.isStatic, d.mt, name, - d.posn); - - // Field Declarations - if (peek(1).type == Token.TYPE.SEMICOLON) { + String memberName = accept(Token.TYPE.ID).spelling; + + // Field Declaration + FieldDecl fd = new FieldDecl(d, memberName); + if(peek(1).type == Token.TYPE.SEMICOLON) { accept(Token.TYPE.SEMICOLON); - fdl.add(f); + fdl.add(fd); + } + + // Method Declaration + else { + MethodDecl md = parseMethodDeclaration(fd); + mdl.add(md); } - - // Method Declarations - else - mdl.add(parseMethodDeclaration(f)); } - + accept(Token.TYPE.RBRACKET); - return new ClassDecl(cn, fdl, mdl, classToken.posn); + + // Build Class + ClassDecl decl = new ClassDecl(className, fdl, mdl, classToken.posn); + Identifier ident = new Identifier(className, classToken.posn); + decl.type = new ClassType(ident, classToken.posn); + + return decl; } - + /** - * Declarators ::= (public | private)? static? Type + * * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Declarators parseDeclarators() throws ParsingException, - ScanningException { - - // Visibility - SourcePosition start = null; + private Declarators parseDeclarators() throws IOException { + + boolean isStatic = false; boolean isPrivate = false; - + SourcePosition start = peek(1).posn; + + // Visibility if (peek(1).type == Token.TYPE.PUBLIC) { - start = accept(Token.TYPE.PUBLIC).posn; + accept(Token.TYPE.PUBLIC); } else if (peek(1).type == Token.TYPE.PRIVATE) { isPrivate = true; - start = accept(Token.TYPE.PRIVATE).posn; + accept(Token.TYPE.PRIVATE); } - - // Class Methods - boolean isStatic = false; + + // Static if (peek(1).type == Token.TYPE.STATIC) { isStatic = true; - if (start == null) { - start = accept(Token.TYPE.STATIC).posn; - } else { - accept(Token.TYPE.STATIC); - } + accept(Token.TYPE.STATIC); } - Type t = parseType(); - if (start == null) { - start = t.posn; - } - - return new Declarators(isPrivate, isStatic, t, start); + return new Declarators(isPrivate, isStatic, parseType(), start); } - + /** - * MethodDeclaration ::= (ParameterList?) { Statement* (return Expression;)? } + * * @param f * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private MethodDecl parseMethodDeclaration(FieldDecl f) - throws ParsingException, ScanningException { - - // Method Header + private MethodDecl parseMethodDeclaration(FieldDecl f) throws IOException { + + Expression returnExpr = null; + StatementList stl = new StatementList(); + + // Parameters accept(Token.TYPE.LPAREN); - - // Parameter List + ParameterDeclList pdl = new ParameterDeclList(); - if (peek(1).type != Token.TYPE.RPAREN) + if (peek(1).type != Token.TYPE.RPAREN) { pdl = parseParameterList(); + } accept(Token.TYPE.RPAREN); - accept(Token.TYPE.LBRACKET); - + // Method Body - Expression re = null; - StatementList stl = new StatementList(); + accept(Token.TYPE.LBRACKET); + while (peek(1).type != Token.TYPE.RBRACKET) { - if (peek(1).type == Token.TYPE.RETURN) { accept(Token.TYPE.RETURN); - re = parseExpression(); + returnExpr = parseExpression(); accept(Token.TYPE.SEMICOLON); break; } - + stl.add(parseStatement()); } - + accept(Token.TYPE.RBRACKET); - return new MethodDecl(f, pdl, stl, re, f.posn); + + return new MethodDecl(f, pdl, stl, returnExpr, f.posn); } + + + // ///////////////////////////////////////////////////////////////////////////// + // + // TYPES + // + // ///////////////////////////////////////////////////////////////////////////// /** - * Type ::= boolean | void | int ([])? | id ([])? + * * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Type parseType() throws ParsingException, ScanningException { - - SourcePosition posn = null; - - switch (peek(1).type) { - - case BOOLEAN: - posn = accept(Token.TYPE.BOOLEAN).posn; - return new BaseType(TypeKind.BOOLEAN, posn); - - case VOID: - posn = accept(Token.TYPE.VOID).posn; - return new BaseType(TypeKind.VOID, posn); - - case INT: { - posn = accept(Token.TYPE.INT).posn; - BaseType b = new BaseType(TypeKind.INT, posn); - - if (peek(1).type == Token.TYPE.LSQUARE) { - accept(Token.TYPE.LSQUARE); - accept(Token.TYPE.RSQUARE); - return new ArrayType(b, posn); + private Type parseType() throws IOException { + + switch(peek(1).type) { + + case VOID: { + Token next = accept(Token.TYPE.VOID); + return new BaseType(TypeKind.VOID, next.posn); } - - return b; - } - - case ID: { - Token id = accept(peek(1).type); - Identifier i = new Identifier(id.spelling, id.posn); - ClassType c = new ClassType(i, id.posn); - - if (peek(1).type == Token.TYPE.LSQUARE) { - accept(Token.TYPE.LSQUARE); - accept(Token.TYPE.RSQUARE); - return new ArrayType(c, id.posn); + + case BOOLEAN: { + Token next = accept(Token.TYPE.BOOLEAN); + return new BaseType(TypeKind.BOOLEAN, next.posn); + } + + case INT: { + Token next = accept(Token.TYPE.INT); + BaseType bt = new BaseType(TypeKind.INT, next.posn); + + if (peek(1).type == Token.TYPE.LSQUARE) { + accept(Token.TYPE.LSQUARE); + accept(Token.TYPE.RSQUARE); + return new ArrayType(bt, next.posn); + } + + return bt; + } + + case ID: { + Token next = accept(Token.TYPE.ID); + Identifier ident = new Identifier(next.spelling, next.posn); + ClassType ct = new ClassType(ident, ident.posn); + + if (peek(1).type == Token.TYPE.LSQUARE) { + accept(Token.TYPE.LSQUARE); + accept(Token.TYPE.RSQUARE); + return new ArrayType(ct, ident.posn); + } + + return ct; + } + + default: { + Token next = peek(1); + throw new ParsingException(next.posn); } - - return c; - } - - default: - throw new ParsingException(); } } - + + + // ///////////////////////////////////////////////////////////////////////////// + // + // Arguments + // + // ///////////////////////////////////////////////////////////////////////////// + /** - * ParameterList ::= Type id (, Type id)* + * * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private ParameterDeclList parseParameterList() throws ParsingException, ScanningException { - + private ParameterDeclList parseParameterList() throws IOException { + ParameterDeclList decls = new ParameterDeclList(); // First Parameter - Type t = parseType(); - Token id = accept(Token.TYPE.ID); - decls.add(new ParameterDecl(t, id.spelling, id.posn)); + Type fpt = parseType(); + Token next = accept(Token.TYPE.ID); + decls.add(new ParameterDecl(fpt, next.spelling, fpt.posn)); // Remainder of List - while (peek(1).type == Token.TYPE.COMMA) { + while(peek(1).type == Token.TYPE.COMMA) { accept(Token.TYPE.COMMA); - Type nextType = parseType(); - Token nextId = accept(Token.TYPE.ID); - decls.add(new ParameterDecl(nextType, nextId.spelling, nextId.posn)); + Type type = parseType(); + Token id = accept(Token.TYPE.ID); + decls.add(new ParameterDecl(type, id.spelling, type.posn)); } return decls; } /** - * ArgumentList ::= Expression (, Expression)* + * * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private ExprList parseArgumentList() throws ParsingException, ScanningException { - ExprList e = new ExprList(); - e.add(parseExpression()); - while (peek(1).type == Token.TYPE.COMMA) { + private ExprList parseArgumentList() throws IOException { + + ExprList el = new ExprList(); + el.add(parseExpression()); + + // Rest of argument list + while(peek(1).type == Token.TYPE.COMMA) { accept(Token.TYPE.COMMA); - e.add(parseExpression()); + el.add(parseExpression()); } - return e; + return el; } + + + // ///////////////////////////////////////////////////////////////////////////// + // + // REFERENCES + // + // ///////////////////////////////////////////////////////////////////////////// /** - * Reference ::= BaseRef (. BaseRef)* + * * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Reference parseReference() throws ParsingException, ScanningException { - Reference r = parseBaseRef(); + private Reference parseReference() throws IOException { + + Reference ref = parseBaseRef(); + while (peek(1).type == Token.TYPE.PERIOD) { accept(Token.TYPE.PERIOD); - Token tokenId = accept(Token.TYPE.ID); - Identifier id = new Identifier(tokenId.spelling, tokenId.posn); - r = new QualifiedRef(r, id, tokenId.posn); + Token next = accept(Token.TYPE.ID); + Identifier ident = new Identifier(next.spelling, next.posn); + ref = new QualifiedRef(ref, ident, next.posn); + // Must be indexed if (peek(1).type == Token.TYPE.LSQUARE) { accept(Token.TYPE.LSQUARE); - Expression e = parseExpression(); + Expression expr = parseExpression(); accept(Token.TYPE.RSQUARE); - r = new IndexedRef(r, e, tokenId.posn); + ref = new IndexedRef(ref, expr, next.posn); } } - return r; + return ref; } /** - * BaseRef ::= this | id ([ Expression])? + * * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Reference parseBaseRef() throws ParsingException, ScanningException { - - switch (peek(1).type) { - case THIS: { - Token thisToken = accept(Token.TYPE.THIS); - return new ThisRef(thisToken.posn); - } - - // id ([ Expression])? - default: { - Token id = accept(Token.TYPE.ID); - Identifier i = new Identifier(id.spelling, id.posn); - IdRef r = new IdRef(i, id.posn); - - if (peek(1).type == Token.TYPE.LSQUARE) { - accept(Token.TYPE.LSQUARE); - Expression e = parseExpression(); - accept(Token.TYPE.RSQUARE); - return new IndexedRef(r, e, id.posn); - } - - return r; - } + private Reference parseBaseRef() throws IOException { + + if(peek(1).type == Token.TYPE.THIS) { + Token next = accept(Token.TYPE.THIS); + return new ThisRef(next.posn); } + + Token next = accept(Token.TYPE.ID); + Identifier ident = new Identifier(next.spelling, next.posn); + IdRef ref = new IdRef(ident, ident.posn); + + // Must be indexed + if (peek(1).type == Token.TYPE.LSQUARE) { + accept(Token.TYPE.LSQUARE); + Expression expr = parseExpression(); + accept(Token.TYPE.RSQUARE); + return new IndexedRef(ref, expr, next.posn); + } + + return ref; } - + + + // ///////////////////////////////////////////////////////////////////////////// + // + // STATEMENTS + // + // ///////////////////////////////////////////////////////////////////////////// + /** - * Statement ::= {Statement*} | Type id = Expression; | Reference = - * Expression; | Reference ( ArgumentList? ); | if (Expression) Statement - * (else Statement)? | while (Expression) Statement + * * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Statement parseStatement() throws ParsingException, ScanningException { + private Statement parseBlockStatement() throws IOException { + + StatementList stl = new StatementList(); + Token left = accept(Token.TYPE.LBRACKET); + + while(peek(1).type != Token.TYPE.RBRACKET) { + stl.add(parseStatement()); + } + + accept(Token.TYPE.RBRACKET); + + return new BlockStmt(stl, left.posn); + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseIfStatement() throws IOException { + + Token next = accept(Token.TYPE.IF); + + // Conditional + accept(Token.TYPE.LPAREN); + Expression expr = parseExpression(); + accept(Token.TYPE.RPAREN); + + // Body + Statement s1 = parseStatement(); + + // Else Statement + if (peek(1).type == Token.TYPE.ELSE) { + accept(Token.TYPE.ELSE); + Statement s2 = parseStatement(); + return new IfStmt(expr, s1, s2, next.posn); + } + return new IfStmt(expr, s1, next.posn); + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseWhileStatement() throws IOException { + + Token next = accept(Token.TYPE.WHILE); + + // Conditional + accept(Token.TYPE.LPAREN); + Expression e = parseExpression(); + accept(Token.TYPE.RPAREN); + + // Body + Statement s = parseStatement(); + + return new WhileStmt(e, s, next.posn); + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseVarDeclStatement() throws IOException { + + Type type = parseType(); + String name = accept(Token.TYPE.ID).spelling; + VarDecl v = new VarDecl(type, name, type.posn); + + accept(Token.TYPE.EQUALS); + Expression expr = parseExpression(); + accept(Token.TYPE.SEMICOLON); + + return new VarDeclStmt(v, expr, type.posn); + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseReferenceStatement() throws IOException { + + Statement stmt = null; + Reference ref = parseReference(); + + // Reference ( ArgumentList? ) ; + if (peek(1).type == Token.TYPE.LPAREN) { + ExprList el = new ExprList(); + accept(Token.TYPE.LPAREN); + if(peek(1).type != Token.TYPE.RPAREN) { + el = parseArgumentList(); + } + accept(Token.TYPE.RPAREN); + stmt = new CallStmt(ref, el, ref.posn); + } + + // Reference = Expression; + else { + accept(Token.TYPE.EQUALS); + Expression expr = parseExpression(); + stmt = new AssignStmt(ref, expr, ref.posn); + } + + accept(Token.TYPE.SEMICOLON); + return stmt; + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseStatement() throws IOException { + switch (peek(1).type) { - + // { Statement* } case LBRACKET: { - Token leftToken = accept(Token.TYPE.LBRACKET); - StatementList stl = new StatementList(); - while (peek(1).type != Token.TYPE.RBRACKET) { - stl.add(parseStatement()); - } - accept(Token.TYPE.RBRACKET); - - return new BlockStmt(stl, leftToken.posn); + return parseBlockStatement(); } - + // if (Expression) Statement (else Statement)? case IF: { - Token ifToken = accept(Token.TYPE.IF); - accept(Token.TYPE.LPAREN); - Expression e = parseExpression(); - accept(Token.TYPE.RPAREN); - Statement s1 = parseStatement(); - if (peek(1).type == Token.TYPE.ELSE) { - accept(Token.TYPE.ELSE); - Statement s2 = parseStatement(); - return new IfStmt(e, s1, s2, ifToken.posn); - } - - return new IfStmt(e, s1, ifToken.posn); + return parseIfStatement(); } - + // while (Expression) Statement case WHILE: { - Token whileToken = accept(Token.TYPE.WHILE); - accept(Token.TYPE.LPAREN); - Expression e = parseExpression(); - accept(Token.TYPE.RPAREN); - Statement s = parseStatement(); - - return new WhileStmt(e, s, whileToken.posn); + return parseWhileStatement(); } - - // Type id = Expression ; + + // Type id = Expression; case BOOLEAN: case VOID: case INT: case ID: { - - // Must be a type though there is a possibility of a reference - if (peek(1).type != Token.TYPE.ID - || peek(2).type == Token.TYPE.ID - || (peek(2).type == Token.TYPE.LSQUARE && peek(3).type == Token.TYPE.RSQUARE)) { - Type t = parseType(); - String name = accept(Token.TYPE.ID).spelling; - VarDecl v = new VarDecl(t, name, t.posn); - - accept(Token.TYPE.EQUALS); - Expression e = parseExpression(); - accept(Token.TYPE.SEMICOLON); - - return new VarDeclStmt(v, e, t.posn); + + Token.TYPE fst = peek(1).type; + Token.TYPE snd = peek(2).type; + Token.TYPE thd = peek(3).type; + + if(fst != Token.TYPE.ID || snd == Token.TYPE.ID) { + return parseVarDeclStatement(); + } else if(snd == Token.TYPE.LSQUARE && thd == Token.TYPE.RSQUARE) { + return parseVarDeclStatement(); } - + /* Fall Through */ } - + default: { - Statement s = null; - Reference r = parseReference(); - - // Reference ( ArgumentList? ) ; - if (peek(1).type == Token.TYPE.LPAREN) { - ExprList e = new ExprList(); - accept(Token.TYPE.LPAREN); - if (peek(1).type != Token.TYPE.RPAREN) { - e = parseArgumentList(); - } - accept(Token.TYPE.RPAREN); - s = new CallStmt(r, e, r.posn); - } - - // Reference = Expression ; - else { - accept(Token.TYPE.EQUALS); - Expression e = parseExpression(); - s = new AssignStmt(r, e, r.posn); - } - - accept(Token.TYPE.SEMICOLON); - return s; + return parseReferenceStatement(); } } } + + + // ///////////////////////////////////////////////////////////////////////////// + // + // EXPRESSIONS + // + // ///////////////////////////////////////////////////////////////////////////// - /** - * Expression ::= Reference | Reference ( ArgumentList? ) | unop Expression - * | ( Expression ) | num | true | false | new (id() | int [ Expression ] | - * id [ Expression ] ) - * - * @return - * @throws ScanningException - */ - private Expression parseSingleExpression() throws ParsingException, ScanningException { + private Expression parseSingleExpression() throws IOException { - Expression e = null; switch (peek(1).type) { - - // num + case NUM: { - Token number = accept(Token.TYPE.NUM); - IntLiteral i = new IntLiteral(number.spelling, number.posn); - e = new LiteralExpr(i, number.posn); - break; + Token next = accept(Token.TYPE.NUM); + IntLiteral il = new IntLiteral(next.spelling, next.posn); + return new LiteralExpr(il, next.posn); } - // true | false case TRUE: case FALSE: { - Token bool = accept(peek(1).type); - BooleanLiteral b = new BooleanLiteral(bool.spelling, bool.posn); - e = new LiteralExpr(b, bool.posn); - break; + Token next = accept(peek(1).type); + BooleanLiteral bl = new BooleanLiteral(next.spelling, next.posn); + return new LiteralExpr(bl, next.posn); } // ( Expression ) case LPAREN: { accept(Token.TYPE.LPAREN); - e = parseExpression(); + Expression expr = parseExpression(); accept(Token.TYPE.RPAREN); - break; + + return expr; } // unop Expression case UNOP: case BINOP: { if (peek(1).spelling.equals("!") || peek(1).spelling.equals("-")) { - Token opToken = accept(peek(1).type); - Operator o = new Operator(opToken, opToken.posn); - e = new UnaryExpr(o, parseSingleExpression(), opToken.posn); - } else - throw new ParsingException(); - break; + Token next = accept(peek(1).type); + Operator o = new Operator(next, next.posn); + Expression expr = parseSingleExpression(); + return new UnaryExpr(o, expr, next.posn); + } else { + throw new ParsingException(peek(1).posn); + } } // new ( int [ Expression ] | id ( ) | id [ Expression ] ) case NEW: { - Token newToken = accept(Token.TYPE.NEW); + + Token next = accept(Token.TYPE.NEW); if (peek(1).type == Token.TYPE.INT) { accept(Token.TYPE.INT); accept(Token.TYPE.LSQUARE); - Expression e2 = parseExpression(); + Expression expr = parseExpression(); accept(Token.TYPE.RSQUARE); - BaseType b = new BaseType(TypeKind.INT, newToken.posn); - e = new NewArrayExpr(b, e2, newToken.posn); + BaseType b = new BaseType(TypeKind.INT, next.posn); + return new NewArrayExpr(b, expr, next.posn); } else { Token id = accept(Token.TYPE.ID); - Identifier i = new Identifier(id.spelling, id.posn); - ClassType c = new ClassType(i, id.posn); + Identifier ident = new Identifier(id.spelling, id.posn); + ClassType ct = new ClassType(ident, id.posn); if (peek(1).type == Token.TYPE.LPAREN) { accept(Token.TYPE.LPAREN); accept(Token.TYPE.RPAREN); - e = new NewObjectExpr(c, id.posn); + return new NewObjectExpr(ct, next.posn); } else { accept(Token.TYPE.LSQUARE); - Expression e2 = parseExpression(); + Expression expr = parseExpression(); accept(Token.TYPE.RSQUARE); - e = new NewArrayExpr(c, e2, id.posn); + return new NewArrayExpr(ct, expr, next.posn); } } - - break; } // Reference ((ArgumentList?))? case THIS: case ID: { - Reference r = parseReference(); + + Reference ref = parseReference(); + if (peek(1).type == Token.TYPE.LPAREN) { accept(Token.TYPE.LPAREN); ExprList el = new ExprList(); @@ -501,138 +655,139 @@ public class Parser { el = parseArgumentList(); } accept(Token.TYPE.RPAREN); - e = new CallExpr(r, el, r.posn); + return new CallExpr(ref, el, ref.posn); } else { - e = new RefExpr(r, r.posn); + return new RefExpr(ref, ref.posn); } - - break; } - default: - throw new ParsingException(peek(1)); + default: throw new ParsingException(peek(1).posn); } - - return e; } /** - * Disjunction & Initial Call: Expression ::= Expression binop Expression + * Disjunctive * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Expression parseExpression() throws ParsingException, ScanningException { - - Expression e = parseCExpression(); + private Expression parseExpression() throws IOException { + + Expression expr = parseCExpression(); + while (peek(1).spelling.equals("||")) { - Token opToken = accept(Token.TYPE.BINOP); - Operator o = new Operator(opToken, opToken.posn); - e = new BinaryExpr(o, e, parseCExpression(), e.posn); + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseCExpression(), expr.posn); } - return e; + return expr; } /** - * Conjunction + * Conjunctive * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Expression parseCExpression() throws ParsingException, ScanningException { + private Expression parseCExpression() throws IOException { - Expression e = parseEExpression(); + Expression expr = parseEExpression(); + while (peek(1).spelling.equals("&&")) { - Token opToken = accept(Token.TYPE.BINOP); - Operator o = new Operator(opToken, opToken.posn); - e = new BinaryExpr(o, e, parseEExpression(), e.posn); + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseEExpression(), expr.posn); } - return e; + return expr; } /** * Equality * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Expression parseEExpression() throws ParsingException, ScanningException { + private Expression parseEExpression() throws IOException { - Expression e = parseRExpression(); + Expression expr = parseRExpression(); + while (peek(1).spelling.equals("==") || peek(1).spelling.equals("!=")) { - Token opToken = accept(Token.TYPE.BINOP); - Operator o = new Operator(opToken, opToken.posn); - e = new BinaryExpr(o, e, parseRExpression(), e.posn); + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseRExpression(), expr.posn); } - return e; + return expr; } - + /** * Relational * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Expression parseRExpression() throws ParsingException, ScanningException { + private Expression parseRExpression() throws IOException { - Expression e = parseAExpression(); - while (peek(1).spelling.equals("<") || peek(1).spelling.equals("<=") - || peek(1).spelling.equals(">") - || peek(1).spelling.equals(">=")) { - Token opToken = accept(Token.TYPE.BINOP); - Operator o = new Operator(opToken, opToken.posn); - e = new BinaryExpr(o, e, parseAExpression(), e.posn); + Expression expr = parseAExpression(); + + while(peek(1).spelling.equals("<") || peek(1).spelling.equals("<=") + || peek(1).spelling.equals(">") || peek(1).spelling.equals(">=")) { + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseAExpression(), expr.posn); } - return e; + return expr; } /** * Additive * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Expression parseAExpression() throws ParsingException, ScanningException { + private Expression parseAExpression() throws IOException { - Expression e = parseMExpression(); + Expression expr = parseMExpression(); + while (peek(1).spelling.equals("+") || peek(1).spelling.equals("-")) { - Token opToken = accept(Token.TYPE.BINOP); - Operator o = new Operator(opToken, opToken.posn); - e = new BinaryExpr(o, e, parseMExpression(), e.posn); + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseMExpression(), expr.posn); } - return e; + return expr; } /** * Multiplicative * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Expression parseMExpression() throws ParsingException, ScanningException { - - Expression e = parseSingleExpression(); + private Expression parseMExpression() throws IOException { + + Expression expr = parseSingleExpression(); + while (peek(1).spelling.equals("*") || peek(1).spelling.equals("/")) { - Token opToken = accept(Token.TYPE.BINOP); - Operator o = new Operator(opToken, opToken.posn); - e = new BinaryExpr(o, e, parseSingleExpression(), e.posn); + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseSingleExpression(), expr.posn); } - return e; + return expr; } - + + + // ///////////////////////////////////////////////////////////////////////////// + // + // Convenience Methods + // + // ///////////////////////////////////////////////////////////////////////////// + /** - * Sees what the next token is, caching the result. + * * @param lookahead * @return - * @throws ScanningException + * @throws IOException */ - private Token peek(int lookahead) throws ScanningException { + private Token peek(int lookahead) throws IOException { // Cache tokens while (stream.size() < lookahead) { @@ -644,16 +799,16 @@ public class Parser { } /** - * Consumes token or throws exception. + * * @param type * @return - * @throws ParsingException - * @throws ScanningException + * @throws IOException */ - private Token accept(Token.TYPE type) throws ParsingException, ScanningException { + private Token accept(Token.TYPE type) throws IOException { + Token next = peek(1); if(next.type == type) stream.poll(); - else throw new ParsingException(next); + else throw new ParsingException(next.posn); return next; } diff --git a/src/miniJava/SyntacticAnalyzer/ParsingException.java b/src/miniJava/SyntacticAnalyzer/ParsingException.java new file mode 100644 index 0000000..635e52d --- /dev/null +++ b/src/miniJava/SyntacticAnalyzer/ParsingException.java @@ -0,0 +1,16 @@ +package miniJava.SyntacticAnalyzer; + +import java.io.IOException; + +/** + * + */ +public class ParsingException extends IOException { + + private static final long serialVersionUID = 1L; + + public ParsingException(SourcePosition posn) { + super("Parsing error at " + posn); + } + +} \ No newline at end of file diff --git a/src/miniJava/SyntacticAnalyzer/Scanner.java b/src/miniJava/SyntacticAnalyzer/Scanner.java index 3cd0aa8..e3ff840 100644 --- a/src/miniJava/SyntacticAnalyzer/Scanner.java +++ b/src/miniJava/SyntacticAnalyzer/Scanner.java @@ -1,313 +1,306 @@ package miniJava.SyntacticAnalyzer; import java.io.*; -import miniJava.Exceptions.*; public class Scanner { private int col = 1; private int line = 1; + private boolean predefined; private BufferedReader input; - - public Scanner(BufferedReader input) { - this.input = input; - } - - public Scanner(String input) { - StringReader reader = new StringReader(input); - this.input = new BufferedReader(reader); - } - + + /** + * + * @param input + */ + public Scanner(BufferedReader input) { + this(input, false); + } + + /** + * + * @param input + * @param predefined + */ + public Scanner(String input, boolean predefined) { + this(new BufferedReader(new StringReader(input)), predefined); + } + + /** + * + * @param input + * @param predefined + */ + public Scanner(BufferedReader input, boolean predefined) { + this.input = input; + this.predefined = predefined; + } + + + // ///////////////////////////////////////////////////////////////////////////// + // + // Scanning + // + // ///////////////////////////////////////////////////////////////////////////// + /** - * Scans in input, returning next token. * * @return * @throws IOException */ - public Token scan() throws ScanningException { - - String attr = ""; + public Token scan() throws IOException { Token token = null; - + String spelling = ""; + while (token == null) { - - // Check for EOF + int c = read(); - if (c == -1) - return new Token("", Token.TYPE.EOT); + SourcePosition posn = new SourcePosition(col, line); + + if(c == -1) { + token = new Token("", Token.TYPE.EOT, posn); + } else { + spelling += (char) c; + + switch(c) { - // Setup - attr += (char) c; - - switch (c) { - - // Operators - case '*': - token = new Token(attr, Token.TYPE.BINOP); - break; - - case '+': - if (peek('+')) - throw new ScanningException(col, line); - token = new Token(attr, Token.TYPE.BINOP); - break; - - case '-': - if (peek('-')) - throw new ScanningException(col, line); - token = new Token(attr, Token.TYPE.BINOP); - break; - - // Check for comment - case '/': - if (peek('*')) { - read(); - readComment(); - attr = ""; - } else if (peek('/')) { - readLine(); - attr = ""; - } else - token = new Token(attr, Token.TYPE.BINOP); - break; - - // Check for c or c= - case '>': - case '<': - if (peek('=')) - attr += (char) read(); - token = new Token(attr, Token.TYPE.BINOP); - break; - - // Check for ! or != - case '!': - if (!peek('=')) - token = new Token(attr, Token.TYPE.UNOP); - else { - attr += (char) read(); - token = new Token(attr, Token.TYPE.BINOP); - } - break; - - // Check for && or || - case '&': - case '|': - if (!peek((char) c)) - throw new ScanningException(col, line); - else { - attr += (char) read(); - token = new Token(attr, Token.TYPE.BINOP); - } - break; - - // Other Operators - case '=': - if (!peek('=')) - token = new Token(attr, Token.TYPE.EQUALS); - else { - attr += (char) read(); - token = new Token(attr, Token.TYPE.BINOP); - } - break; - - case '.': - token = new Token(attr, Token.TYPE.PERIOD); - break; - - case ',': - token = new Token(attr, Token.TYPE.COMMA); - break; - - case '[': - token = new Token(attr, Token.TYPE.LSQUARE); - break; - - case ']': - token = new Token(attr, Token.TYPE.RSQUARE); - break; - - case '{': - token = new Token(attr, Token.TYPE.LBRACKET); - break; - - case '}': - token = new Token(attr, Token.TYPE.RBRACKET); - break; - - case '(': - token = new Token(attr, Token.TYPE.LPAREN); - break; - - case ')': - token = new Token(attr, Token.TYPE.RPAREN); - break; - - case ';': - token = new Token(attr, Token.TYPE.SEMICOLON); - break; - - default: - - // Identifier or Keyword - if (isAlpha((char) c)) { - for (char n = peek(); isAlpha(n) || isDigit(n);) { - attr += (char) read(); - n = peek(); + // Operators + case '*': + case '+': + case '-': { + if(peek(c)) throw new ScanningException(posn); + token = new Token(spelling, Token.TYPE.BINOP, posn); + break; } + + // Comment + case '/': { + if(peek('*')) { + read(); + readMultiLineComment(); + spelling = ""; + } else if(peek('/')) { + readSingleLineComment(); + spelling = ""; + } else { + token = new Token(spelling, Token.TYPE.BINOP, posn); + } + + break; + } + + // Relational + case '>': + case '<': { + if (peek('=')) spelling += (char) read(); + token = new Token(spelling, Token.TYPE.BINOP, posn); + break; + } + + // Negation + case '!': { + if(peek('=')) { + spelling += (char) read(); + token = new Token(spelling, Token.TYPE.BINOP, posn); + } else { + token = new Token(spelling, Token.TYPE.UNOP, posn); + } + + break; + } + + // Logical + case '&': + case '|': { + if(!peek(c)) { + throw new ScanningException(posn); + } else { + spelling += (char) read(); + token = new Token(spelling, Token.TYPE.BINOP, posn); + } + + break; + } + + // Other Operators + case '=': { + if(peek('=')) { + spelling += (char) read(); + token = new Token(spelling, Token.TYPE.BINOP, posn); + } else { + token = new Token(spelling, Token.TYPE.EQUALS, posn); + } + + break; + } + + // Miscellaneous + case '.': + case ',': + case '[': + case ']': + case '{': + case '}': + case '(': + case ')': + case ';': { + token = new Token(spelling, Token.symbols.get(c), posn); + break; + } + + default: { + + // Identifier or keyword + if(isAlpha(c)) { + int next = peek(); + while(isAlpha(next) || isDigit(next) || next == '_') { + spelling += (char) read(); + next = peek(); + } + + if(Token.keywords.containsKey(spelling)) { + token = new Token(spelling, Token.keywords.get(spelling), posn); + } else { + token = new Token(spelling, Token.TYPE.ID, posn); + } + } + + // Number + else if(isDigit(c)) { + int next = peek(); + while(isDigit(next)) { + spelling += (char) read(); + next = peek(); + } - if (Token.keywords.containsKey(attr)) { - token = new Token(attr, Token.keywords.get(attr)); - } else { - token = new Token(attr, Token.TYPE.ID); + token = new Token(spelling, Token.TYPE.NUM, posn); + } + + // Whitespace + else if(isWhitespace(c)) { + spelling = ""; + } + + // Unrecognized Character + else { + throw new ScanningException(posn); + } } } - - // Number - else if (isDigit((char) c)) { - for (char n = peek(); isDigit(n);) { - attr += (char) read(); - n = peek(); - } - - token = new Token(attr, Token.TYPE.NUM); - } - - // Whitespace - else if (isWhitespace((char) c)) { - attr = ""; - } - - // Unrecognized Character - else - throw new ScanningException(col, line); - ; - - break; } } - token.posn = new SourcePosition(line, col - token.spelling.length()); return token; } + + + // ///////////////////////////////////////////////////////////////////////////// + // + // Convenience Methods + // + // ///////////////////////////////////////////////////////////////////////////// + /** - * Looks at next character in stream without consuming. - * - * @return - * @throws IOException - */ - private char peek() throws ScanningException { - try { - input.mark(1); - int next = input.read(); - input.reset(); - - return next == -1 ? '\0' : (char) next; - } catch (IOException e) { - throw new ScanningException(col, line); - } - } - - /** - * Returns whether passed character is next in stream. - * - * @param c - * @return - * @throws IOException - */ - private boolean peek(char c) throws ScanningException { - try { - input.mark(1); - int next = input.read(); - input.reset(); - - return c == next; - } catch (IOException e) { - throw new ScanningException(col, line); - } - } - - /** - * Alternative reading that keeps track of position. - * - * @return - * @throws IOException - */ - private int read() throws ScanningException { - try { - int next = input.read(); - if (next != '\n' && next != '\r') - col += 1; - else { - col = 1; - line += 1; - if (peek('\r') || peek('\n')) - next = input.read(); - } - - return next; - } catch (IOException e) { - throw new ScanningException(col, line); - } - } - - /** - * Consumes input until an end of comment has been reached. - * - * @throws IOException - */ - private void readComment() throws ScanningException { - char prev = '\0', current = '\0'; - while (prev != '*' || current != '/') { - - prev = current; - - int next = read(); - if (next == -1) - throw new ScanningException(col, line); - else - current = (char) next; - } - } - - /** - * Consumes input until the end of line is reached - * - * @throws IOException - */ - private void readLine() throws ScanningException { - for (int n = 0; n != '\n' && n != '\r' && n != -1; n = read()) { - } - } - - /** - * Tells whether character is alphabetical. * * @param c * @return */ - private boolean isAlpha(char c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; + private boolean isAlpha(int c) { + return (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (predefined && c == '_'); } - + /** - * Tells whether character is numerical. * * @param c * @return */ - private boolean isDigit(char c) { + private boolean isDigit(int c) { return c >= '0' && c <= '9'; } - + /** - * Tells wheter character is whitespace. * * @param c * @return */ - private boolean isWhitespace(char c) { + private boolean isWhitespace(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t'; } + + /** + * + * @return + * @throws IOException + */ + private int peek() throws IOException { + input.mark(1); + int next = input.read(); + input.reset(); + return next; + } + + /** + * + * @param c + * @return + * @throws IOException + */ + private boolean peek(int c) throws IOException { + input.mark(1); + int next = input.read(); + input.reset(); + + return c == next; + } + + /** + * + * @return + * @throws IOException + */ + private int read() throws IOException { + int next = input.read(); + if(next == '\n' || next == '\r') { + col = 1; + line += 1; + } else { + col += 1; + } + + return next; + } + + /** + * + * @throws IOException + */ + private void readSingleLineComment() throws IOException { + col = 1; + line += 1; + input.readLine(); + } + + /** + * + * @throws IOException + */ + private void readMultiLineComment() throws IOException { + int prev = '\0'; + int current = '\0'; + + while(prev != '*' || current != '/') { + prev = current; + current = read(); + + // Unterminated + if(current == -1) { + SourcePosition posn = new SourcePosition(line, col); + throw new ScanningException(posn); + } + } + } } diff --git a/src/miniJava/SyntacticAnalyzer/ScanningException.java b/src/miniJava/SyntacticAnalyzer/ScanningException.java new file mode 100644 index 0000000..6f29677 --- /dev/null +++ b/src/miniJava/SyntacticAnalyzer/ScanningException.java @@ -0,0 +1,16 @@ +package miniJava.SyntacticAnalyzer; + +import java.io.IOException; + +/** + * + */ +public class ScanningException extends IOException { + + private static final long serialVersionUID = 1L; + + public ScanningException(SourcePosition posn) { + super("Scanning error at " + posn); + } + +} diff --git a/src/miniJava/SyntacticAnalyzer/SourcePosition.java b/src/miniJava/SyntacticAnalyzer/SourcePosition.java index 272acc4..072d8fe 100644 --- a/src/miniJava/SyntacticAnalyzer/SourcePosition.java +++ b/src/miniJava/SyntacticAnalyzer/SourcePosition.java @@ -1,11 +1,14 @@ package miniJava.SyntacticAnalyzer; +/** + * + */ public class SourcePosition { public final int col; public final int line; - public SourcePosition(int line, int col) { + public SourcePosition(int col, int line) { this.col = col; this.line = line; } diff --git a/src/miniJava/SyntacticAnalyzer/Token.java b/src/miniJava/SyntacticAnalyzer/Token.java index 08f5abb..ddd35f1 100644 --- a/src/miniJava/SyntacticAnalyzer/Token.java +++ b/src/miniJava/SyntacticAnalyzer/Token.java @@ -2,26 +2,51 @@ package miniJava.SyntacticAnalyzer; import java.util.HashMap; +/** + * + */ public class Token { public enum TYPE { - - // Possible Terminals - ID, NUM, UNOP, BINOP, + + // Terminals + ID, + NUM, + UNOP, + BINOP, + EQUALS, + PERIOD, + COMMA, + LPAREN, + RPAREN, + LSQUARE, + RSQUARE, + LBRACKET, + RBRACKET, + SEMICOLON, // Keywords - IF, ELSE, NEW, INT, VOID, THIS, TRUE, FALSE, CLASS, WHILE, RETURN, BOOLEAN, - - // Declarators - STATIC, PUBLIC, PRIVATE, - - // Other Terminals - EQUALS, PERIOD, COMMA, LPAREN, RPAREN, LSQUARE, RSQUARE, LBRACKET, RBRACKET, SEMICOLON, + IF, + ELSE, + NEW, + INT, + VOID, + THIS, + TRUE, + FALSE, + CLASS, + WHILE, + RETURN, + BOOLEAN, + STATIC, + PUBLIC, + PRIVATE, // End of Token Stream EOT }; + // Pair words with enumeration public final static HashMap keywords; static { keywords = new HashMap(); @@ -41,14 +66,29 @@ public class Token { keywords.put("false", TYPE.FALSE); keywords.put("new", TYPE.NEW); } + + // Pair symbols with enumeration + public final static HashMap symbols; + static { + symbols = new HashMap(); + symbols.put((int) '.', TYPE.PERIOD); + symbols.put((int) ',', TYPE.COMMA); + symbols.put((int) '[', TYPE.LSQUARE); + symbols.put((int) ']', TYPE.RSQUARE); + symbols.put((int) '{', TYPE.LBRACKET); + symbols.put((int) '}', TYPE.RBRACKET); + symbols.put((int) '(', TYPE.LPAREN); + symbols.put((int) ')', TYPE.RPAREN); + symbols.put((int) ';', TYPE.SEMICOLON); + } public final TYPE type; - public SourcePosition posn; public final String spelling; + public final SourcePosition posn; - public Token(String spelling, TYPE type) { + public Token(String spelling, TYPE type, SourcePosition posn) { this.type = type; - this.posn = null; + this.posn = posn; this.spelling = spelling; } } diff --git a/src/tester/Checkpoint1.java b/src/tester/Checkpoint1.java new file mode 100644 index 0000000..64410e8 --- /dev/null +++ b/src/tester/Checkpoint1.java @@ -0,0 +1,71 @@ +package tester; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Scanner; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/* Automated regression tester for Checkpoint 1 tests + * Created by Max Beckman-Harned + * Put your tests in "tests/pa1_tests" folder in your Eclipse workspace directory + */ +public class Checkpoint1 { + + static ExecutorService threadPool = Executors.newCachedThreadPool(); + + public static void main(String[] args) throws IOException, InterruptedException { + File testDir = new File(System.getProperty("java.class.path") + + "/../tests/pa1_tests"); + int failures = 0; + for (File x : testDir.listFiles()) { + int returnCode = runTest(x); + if (x.getName().indexOf("pass") != -1) { + if (returnCode == 0) + System.out.println(x.getName() + " passed successfully!"); + else { + failures++; + System.err.println(x.getName() + + " failed but should have passed!"); + } + } else { + if (returnCode == 4) + System.out.println(x.getName() + " failed successfully!"); + else { + System.err.println(x.getName() + " did not fail properly!"); + failures++; + } + } + } + System.out.println(failures + " failures in all."); + } + + private static int runTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()).directory(new File(System.getProperty("java.class.path"))); + Process p = pb.start(); + threadPool.execute(new ProcessOutputter(p.getInputStream(), false)); + p.waitFor(); + return p.exitValue(); + } + + static class ProcessOutputter implements Runnable { + private Scanner processOutput; + private boolean output; + + public ProcessOutputter(InputStream _processStream, boolean _output) { + processOutput = new Scanner(_processStream); + output = _output; + } + @Override + public void run() { + while(processOutput.hasNextLine()) { + String line = processOutput.nextLine(); + if (output) + System.out.println(line); + } + } + + + } +} diff --git a/src/tester/Checkpoint2.java b/src/tester/Checkpoint2.java new file mode 100644 index 0000000..d9d7711 --- /dev/null +++ b/src/tester/Checkpoint2.java @@ -0,0 +1,98 @@ +package tester; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.FileInputStream; +import java.util.Scanner; + +/* Automated regression tester for Checkpoint 2 tests + * Created by Max Beckman-Harned + * Put your tests in "tests/pa2_tests" folder in your Eclipse workspace directory + * If you preface your error messages / exceptions with ERROR or *** then they will be displayed if they appear during processing + */ + +public class Checkpoint2 { + + private static class ReturnInfo { + int returnCode; + String ast; + public ReturnInfo(int _returnCode, String _ast) { + returnCode = _returnCode; + ast = _ast; + } + } + + public static void main(String[] args) throws IOException, InterruptedException { + File testDir = new File(System.getProperty("java.class.path") + + "/../tests/pa2_tests"); + int failures = 0; + for (File x : testDir.listFiles()) { + if (x.getName().endsWith("out") || x.getName().startsWith(".")) + continue; + ReturnInfo info = runTest(x); + int returnCode = info.returnCode; + String ast = info.ast; + if (x.getName().indexOf("pass") != -1) { + if (returnCode == 0) { + String actualAST = getAST(new FileInputStream(x.getPath() + ".out")); + if (actualAST.equals(ast)) + System.out.println(x.getName() + " parsed successfully and has a correct AST!"); + else { + System.err.println(x.getName() + " parsed successfully but has an incorrect AST!"); + failures++; + } + } + else { + failures++; + System.err.println(x.getName() + + " failed to be parsed!"); + } + } else { + if (returnCode == 4) + System.out.println(x.getName() + " failed successfully!"); + else { + System.err.println(x.getName() + " did not fail properly!"); + failures++; + } + } + } + System.out.println(failures + " failures in all."); + } + + private static ReturnInfo runTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()).directory(new File(System.getProperty("java.class.path"))); + pb.redirectErrorStream(true); + Process p = pb.start(); + + String ast = getAST(p.getInputStream()); + p.waitFor(); + int exitValue = p.exitValue(); + return new ReturnInfo(exitValue, ast); + } + + + public static String getAST(InputStream stream) { + Scanner scan = new Scanner(stream); + String ast = null; + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.equals("======= AST Display =========================")) { + line = scan.nextLine(); + while(scan.hasNext() && !line.equals("=============================================")) { + ast += line + "\n"; + line = scan.nextLine(); + } + } + if (line.startsWith("*** ")) + System.out.println(line); + if (line.startsWith("ERROR")) { + System.out.println(line); + while(scan.hasNext()) + System.out.println(scan.next()); + } + } + scan.close(); + return ast; + } +} diff --git a/src/tester/Checkpoint3.java b/src/tester/Checkpoint3.java new file mode 100644 index 0000000..760e1f1 --- /dev/null +++ b/src/tester/Checkpoint3.java @@ -0,0 +1,73 @@ +package tester; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Scanner; + + +/* Automated regression tester for Checkpoint 3 tests + * Created by Max Beckman-Harned + * Put your tests in "tests/pa3_tests" folder in your Eclipse workspace directory + * If you preface your error messages / exceptions with ERROR or *** then they will be displayed if they appear during processing + */ + +public class Checkpoint3 { + + + public static void main(String[] args) throws IOException, InterruptedException { + File testDir = new File(System.getProperty("java.class.path") + + "/../tests/pa3_tests"); + int failures = 0; + for (File x : testDir.listFiles()) { + if (x.getName().endsWith("out") || x.getName().startsWith(".") || x.getName().endsWith("mJAM") || x.getName().endsWith("asm")) + continue; + int returnCode = runTest(x); + if (x.getName().indexOf("pass") != -1) { + if (returnCode == 0) { + System.out.println(x.getName() + " processed successfully!"); + } + else { + failures++; + System.err.println(x.getName() + + " failed to be processed!"); + } + } else { + if (returnCode == 4) + System.out.println(x.getName() + " failed successfully!"); + else { + System.err.println(x.getName() + " did not fail properly!"); + failures++; + } + } + } + System.out.println(failures + " failures in all."); + } + + private static int runTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()).directory(new File(System.getProperty("java.class.path"))); + pb.redirectErrorStream(true); + Process p = pb.start(); + + processStream(p.getInputStream()); + p.waitFor(); + int exitValue = p.exitValue(); + return exitValue; + } + + + public static void processStream(InputStream stream) { + Scanner scan = new Scanner(stream); + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.startsWith("*** ")) + System.out.println(line); + if (line.startsWith("ERROR")) { + System.out.println(line); + //while(scan.hasNext()) + //System.out.println(scan.next()); + } + } + scan.close(); + } +} diff --git a/src/tester/Checkpoint4.java b/src/tester/Checkpoint4.java new file mode 100644 index 0000000..9ff8089 --- /dev/null +++ b/src/tester/Checkpoint4.java @@ -0,0 +1,112 @@ +package tester; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Scanner; + + +/* Automated regression tester for Checkpoint 4 tests + * Created by Max Beckman-Harned + * Put your tests in "tests/pa4_tests" folder in your Eclipse workspace directory + * If you preface your compiler error messages / exceptions with ERROR or *** then they will be displayed if they appear during processing + */ + +public class Checkpoint4 { + + + public static void main(String[] args) throws IOException, InterruptedException { + File testDir = new File(System.getProperty("java.class.path") + + "/../tests/pa4_tests"); + int failures = 0; + for (File x : testDir.listFiles()) { + if (x.getName().startsWith(".") || x.getName().endsWith("mJAM") || x.getName().endsWith("asm")) + continue; + int returnCode = runTest(x); + if (x.getName().indexOf("pass") != -1) { + if (returnCode == 0) { + try { + int val = executeTest(x); + int expected = Integer.parseInt(x.getName().substring(5,7)); + if (val == expected) + System.out.println(x.getName() + " ran successfully!"); + else { + failures++; + System.err.println(x.getName() + " compiled but did not run successfully--got output " + val); + } + } + catch(Exception ex) { + failures++; + System.err.println(x.getName() + " did not output correctly."); + } + } + else { + failures++; + System.err.println(x.getName() + + " failed to be processed!"); + } + } else { + if (returnCode == 4) + System.out.println(x.getName() + " failed successfully!"); + else { + System.err.println(x.getName() + " did not fail properly!"); + failures++; + } + } + } + System.out.println(failures + " failures in all."); + } + + private static int runTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()).directory(new File(System.getProperty("java.class.path"))); + pb.redirectErrorStream(true); + Process p = pb.start(); + + processStream(p.getInputStream()); + p.waitFor(); + int exitValue = p.exitValue(); + return exitValue; + } + + private static int executeTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "mJAM.Interpreter", x.getPath().replace(".java", ".mJAM")).directory(new File(System.getProperty("java.class.path"))); + Process process = pb.start(); + + Scanner scan = new Scanner(process.getInputStream()); + int num = -1; + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.startsWith(">>> ")) { + num = Integer.parseInt(line.substring(4)); + System.out.println("Result = " + num); + break; + } + } + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.startsWith("*** ")) { + System.out.println(line); + break; + } + } + scan.close(); + + return num; + } + + + public static void processStream(InputStream stream) { + Scanner scan = new Scanner(stream); + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.startsWith("*** ")) + System.out.println(line); + if (line.startsWith("ERROR")) { + System.out.println(line); + //while(scan.hasNext()) + //System.out.println(scan.next()); + } + } + scan.close(); + } +} \ No newline at end of file