1
Fork 0

Type Checking

Completed type checking as well as formatted files.
master
Joshua Potter 2014-03-22 21:01:40 -04:00
parent 83c72019f5
commit 3517e9648c
61 changed files with 2046 additions and 1807 deletions

View File

@ -9,19 +9,19 @@ import miniJava.SyntacticAnalyzer.SourcePosition;
public abstract class AST { public abstract class AST {
public AST (SourcePosition posn) { public AST(SourcePosition posn) {
this.posn = 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 <A,R> R visit(Visitor<A,R> v, A o); 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 SourcePosition posn; public abstract <A, R> R visit(Visitor<A, R> v, A o);
public SourcePosition posn;
} }

View File

@ -16,338 +16,343 @@ package miniJava.AbstractSyntaxTrees;
* *
* implements Visitor<argtype,resulttype> * implements Visitor<argtype,resulttype>
*/ */
public class ASTDisplay implements Visitor<String,Object> { public class ASTDisplay implements Visitor<String, Object> {
public static boolean showPosition = false; public static boolean showPosition = false;
/** /**
* print text representation of AST to stdout * print text representation of AST to stdout
* @param ast root node of AST *
*/ * @param ast
public void showTree(AST ast){ * root node of AST
System.out.println("======= AST Display ========================="); */
ast.visit(this, ""); public void showTree(AST ast) {
System.out.println("============================================="); System.out.println("======= AST Display =========================");
} ast.visit(this, "");
System.out.println("=============================================");
// methods to format output }
/** // methods to format output
* display arbitrary text for a node
* @param prefix spacing to indicate depth in AST /**
* @param text preformatted node display * display arbitrary text for a node
*/ *
private void show(String prefix, String text) { * @param prefix
System.out.println(prefix + text); * spacing to indicate depth in AST
} * @param text
* preformatted node display
/** */
* display AST node by name private void show(String prefix, String text) {
* @param prefix spacing to indicate depth in AST System.out.println(prefix + text);
* @param node AST node, will be shown by name }
*/
private void show(String prefix, AST node) { /**
System.out.println(prefix + node.toString()); * display AST node by name
} *
* @param prefix
/** * spacing to indicate depth in AST
* quote a string * @param node
* @param text string to quote * AST node, will be shown by name
*/ */
private String quote(String text) { private void show(String prefix, AST node) {
return ("\"" + text + "\""); System.out.println(prefix + node.toString());
} }
/** /**
* increase depth in AST * quote a string
* @param prefix current spacing to indicate depth in AST *
* @return new spacing * @param text
*/ * string to quote
private String indent(String prefix) { */
return prefix + " "; 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 // PACKAGE
// //
/////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////
public Object visitPackage(Package prog, String arg){ public Object visitPackage(Package prog, String arg) {
show(arg, prog); show(arg, prog);
ClassDeclList cl = prog.classDeclList; ClassDeclList cl = prog.classDeclList;
show(arg," ClassDeclList [" + cl.size() + "]"); show(arg, " ClassDeclList [" + cl.size() + "]");
String pfx = arg + " . "; String pfx = arg + " . ";
for (ClassDecl c: prog.classDeclList){ for (ClassDecl c : prog.classDeclList) {
c.visit(this, pfx); c.visit(this, pfx);
} }
return null; return null;
} }
// /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// DECLARATIONS // DECLARATIONS
// //
/////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////
public Object visitClassDecl(ClassDecl clas, String arg){ public Object visitClassDecl(ClassDecl clas, String arg) {
show(arg, clas); show(arg, clas);
show(indent(arg), quote(clas.name) + " classname"); show(indent(arg), quote(clas.name) + " classname");
show(arg," FieldDeclList [" + clas.fieldDeclList.size() + "]"); show(arg, " FieldDeclList [" + clas.fieldDeclList.size() + "]");
String pfx = arg + " . "; String pfx = arg + " . ";
for (FieldDecl f: clas.fieldDeclList) for (FieldDecl f : clas.fieldDeclList)
f.visit(this, pfx); f.visit(this, pfx);
show(arg," MethodDeclList [" + clas.methodDeclList.size() + "]"); show(arg, " MethodDeclList [" + clas.methodDeclList.size() + "]");
for (MethodDecl m: clas.methodDeclList) for (MethodDecl m : clas.methodDeclList)
m.visit(this, pfx); m.visit(this, pfx);
return null; return null;
} }
public Object visitFieldDecl(FieldDecl f, String arg){ public Object visitFieldDecl(FieldDecl f, String arg) {
show(arg, "(" + (f.isPrivate ? "private": "public") show(arg, "(" + (f.isPrivate ? "private" : "public")
+ (f.isStatic ? " static) " :") ") + f.toString()); + (f.isStatic ? " static) " : ") ") + f.toString());
f.type.visit(this, indent(arg)); f.type.visit(this, indent(arg));
show(indent(arg), quote(f.name) + " fieldname"); show(indent(arg), quote(f.name) + " fieldname");
return null; return null;
} }
public Object visitMethodDecl(MethodDecl m, String arg){ public Object visitMethodDecl(MethodDecl m, String arg) {
show(arg, "(" + (m.isPrivate ? "private": "public") show(arg, "(" + (m.isPrivate ? "private" : "public")
+ (m.isStatic ? " static) " :") ") + m.toString()); + (m.isStatic ? " static) " : ") ") + m.toString());
m.type.visit(this, indent(arg)); m.type.visit(this, indent(arg));
show(indent(arg), quote(m.name) + " methodname"); show(indent(arg), quote(m.name) + " methodname");
ParameterDeclList pdl = m.parameterDeclList; ParameterDeclList pdl = m.parameterDeclList;
show(arg, " ParameterDeclList [" + pdl.size() + "]"); show(arg, " ParameterDeclList [" + pdl.size() + "]");
String pfx = ((String) arg) + " . "; String pfx = ((String) arg) + " . ";
for (ParameterDecl pd: pdl) { for (ParameterDecl pd : pdl) {
pd.visit(this, pfx); pd.visit(this, pfx);
} }
StatementList sl = m.statementList; StatementList sl = m.statementList;
show(arg, " StmtList [" + sl.size() + "]"); show(arg, " StmtList [" + sl.size() + "]");
for (Statement s: sl) { for (Statement s : sl) {
s.visit(this, pfx); s.visit(this, pfx);
} }
if (m.returnExp != null) { if (m.returnExp != null) {
m.returnExp.visit(this, indent(arg)); m.returnExp.visit(this, indent(arg));
} }
return null; return null;
} }
public Object visitParameterDecl(ParameterDecl pd, String arg){ public Object visitParameterDecl(ParameterDecl pd, String arg) {
show(arg, pd); show(arg, pd);
pd.type.visit(this, indent(arg)); pd.type.visit(this, indent(arg));
show(indent(arg), quote(pd.name) + "parametername "); show(indent(arg), quote(pd.name) + "parametername ");
return null; return null;
} }
public Object visitVarDecl(VarDecl vd, String arg){ public Object visitVarDecl(VarDecl vd, String arg) {
show(arg, vd); show(arg, vd);
vd.type.visit(this, indent(arg)); vd.type.visit(this, indent(arg));
show(indent(arg), quote(vd.name) + " varname"); show(indent(arg), quote(vd.name) + " varname");
return null; return null;
} }
// /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// TYPES // TYPES
// //
/////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////
public Object visitBaseType(BaseType type, String arg){ public Object visitBaseType(BaseType type, String arg) {
show(arg, type.typeKind + " " + type.toString()); show(arg, type.typeKind + " " + type.toString());
return null; return null;
} }
public Object visitClassType(ClassType type, String arg){ public Object visitClassType(ClassType type, String arg) {
show(arg, type); show(arg, type);
show(indent(arg), quote(type.className.spelling) + " classname"); show(indent(arg), quote(type.className.spelling) + " classname");
return null; return null;
} }
public Object visitArrayType(ArrayType type, String arg){ public Object visitArrayType(ArrayType type, String arg) {
show(arg, type); show(arg, type);
type.eltType.visit(this, indent(arg)); type.eltType.visit(this, indent(arg));
return null; return null;
} }
// /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// STATEMENTS // STATEMENTS
// //
/////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////
public Object visitBlockStmt(BlockStmt stmt, String arg){ public Object visitBlockStmt(BlockStmt stmt, String arg) {
show(arg, stmt); show(arg, stmt);
StatementList sl = stmt.sl; StatementList sl = stmt.sl;
show(arg," StatementList [" + sl.size() + "]"); show(arg, " StatementList [" + sl.size() + "]");
String pfx = arg + " . "; String pfx = arg + " . ";
for (Statement s: sl) { for (Statement s : sl) {
s.visit(this, pfx); s.visit(this, pfx);
} }
return null; 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;
}
/////////////////////////////////////////////////////////////////////////////// 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 // EXPRESSIONS
// //
/////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////
public Object visitUnaryExpr(UnaryExpr expr, String arg){ public Object visitUnaryExpr(UnaryExpr expr, String arg) {
show(arg, expr); show(arg, expr);
expr.operator.visit(this, indent(arg)); expr.operator.visit(this, indent(arg));
expr.expr.visit(this, indent(indent(arg))); expr.expr.visit(this, indent(indent(arg)));
return null; 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;
}
/////////////////////////////////////////////////////////////////////////////// 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 // REFERENCES
// //
/////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////
public Object visitQualifiedRef(QualifiedRef qr, String arg) { public Object visitQualifiedRef(QualifiedRef qr, String arg) {
show(arg, qr); show(arg, qr);
qr.id.visit(this, indent(arg)); qr.id.visit(this, indent(arg));
qr.ref.visit(this, indent(arg)); qr.ref.visit(this, indent(arg));
return null; return null;
} }
public Object visitIndexedRef(IndexedRef ir, String arg) { public Object visitIndexedRef(IndexedRef ir, String arg) {
show(arg, ir); show(arg, ir);
ir.indexExpr.visit(this, indent(arg)); ir.indexExpr.visit(this, indent(arg));
ir.ref.visit(this, indent(arg)); ir.ref.visit(this, indent(arg));
return null; return null;
} }
public Object visitIdRef(IdRef ref, String arg) { public Object visitIdRef(IdRef ref, String arg) {
show(arg,ref); show(arg, ref);
ref.id.visit(this, indent(arg)); ref.id.visit(this, indent(arg));
return null; return null;
} }
public Object visitThisRef(ThisRef ref, String arg) { public Object visitThisRef(ThisRef ref, String arg) {
show(arg,ref); show(arg, ref);
return null; return null;
} }
// /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// TERMINALS // TERMINALS
// //
/////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////
public Object visitIdentifier(Identifier id, String arg){ public Object visitIdentifier(Identifier id, String arg) {
show(arg, quote(id.spelling) + " " + id.toString()); show(arg, quote(id.spelling) + " " + id.toString());
return null; return null;
} }
public Object visitOperator(Operator op, String arg){ public Object visitOperator(Operator op, String arg) {
show(arg, quote(op.spelling) + " " + op.toString()); show(arg, quote(op.spelling) + " " + op.toString());
return null; return null;
} }
public Object visitIntLiteral(IntLiteral num, String arg){ public Object visitIntLiteral(IntLiteral num, String arg) {
show(arg, quote(num.spelling) + " " + num.toString()); show(arg, quote(num.spelling) + " " + num.toString());
return null; return null;
} }
public Object visitBooleanLiteral(BooleanLiteral bool, String arg){ public Object visitBooleanLiteral(BooleanLiteral bool, String arg) {
show(arg, quote(bool.spelling) + " " + bool.toString()); show(arg, quote(bool.spelling) + " " + bool.toString());
return null; return null;
} }
} }

View File

@ -10,15 +10,14 @@ import miniJava.SyntacticAnalyzer.SourcePosition;
public class ArrayType extends Type { public class ArrayType extends Type {
public ArrayType(Type eltType, SourcePosition posn){ public ArrayType(Type eltType, SourcePosition posn) {
super(TypeKind.ARRAY, posn); super(TypeKind.ARRAY, posn);
this.eltType = eltType; this.eltType = eltType;
}
public <A,R> R visit(Visitor<A,R> v, A o) {
return v.visitArrayType(this, o);
}
public Type eltType;
} }
public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitArrayType(this, o);
}
public Type eltType;
}

View File

@ -7,18 +7,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class AssignStmt extends Statement public class AssignStmt extends Statement {
{ public AssignStmt(Reference r, Expression e, SourcePosition posn) {
public AssignStmt(Reference r, Expression e, SourcePosition posn){ super(posn);
super(posn); ref = r;
ref = r; val = e;
val = e; }
}
public <A, R> R visit(Visitor<A, R> v, A o) {
public <A,R> R visit(Visitor<A,R> v, A o) { return v.visitAssignStmt(this, o);
return v.visitAssignStmt(this, o); }
}
public Reference ref;
public Reference ref; public Expression val;
public Expression val;
} }

View File

@ -7,13 +7,12 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class BaseType extends Type public class BaseType extends Type {
{ public BaseType(TypeKind t, SourcePosition posn) {
public BaseType(TypeKind t, SourcePosition posn){ super(t, posn);
super(t, posn); }
}
public <A, R> R visit(Visitor<A, R> v, A o) {
public <A,R> R visit(Visitor<A,R> v, A o) { return v.visitBaseType(this, o);
return v.visitBaseType(this, o); }
}
} }

View File

@ -7,20 +7,20 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class BinaryExpr extends Expression public class BinaryExpr extends Expression {
{ public BinaryExpr(Operator o, Expression e1, Expression e2,
public BinaryExpr(Operator o, Expression e1, Expression e2, SourcePosition posn){ SourcePosition posn) {
super(posn); super(posn);
operator = o; operator = o;
left = e1; left = e1;
right = e2; right = e2;
} }
public <A,R> R visit(Visitor<A,R> v, A o) { public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitBinaryExpr(this, o); return v.visitBinaryExpr(this, o);
} }
public Operator operator; public Operator operator;
public Expression left; public Expression left;
public Expression right; public Expression right;
} }

View File

@ -7,16 +7,15 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class BlockStmt extends Statement public class BlockStmt extends Statement {
{ public BlockStmt(StatementList sl, SourcePosition posn) {
public BlockStmt(StatementList sl, SourcePosition posn){ super(posn);
super(posn); this.sl = sl;
this.sl = sl; }
}
public <A, R> R visit(Visitor<A, R> v, A o) {
public <A,R> R visit(Visitor<A,R> v, A o) { return v.visitBlockStmt(this, o);
return v.visitBlockStmt(this, o); }
}
public StatementList sl;
public StatementList sl;
} }

View File

@ -9,11 +9,11 @@ import miniJava.SyntacticAnalyzer.SourcePosition;
public class BooleanLiteral extends Literal { public class BooleanLiteral extends Literal {
public BooleanLiteral(String spelling, SourcePosition posn) { public BooleanLiteral(String spelling, SourcePosition posn) {
super (spelling,posn); super(spelling, posn);
} }
public <A,R> R visit(Visitor<A,R> v, A o) { public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitBooleanLiteral(this, o); return v.visitBooleanLiteral(this, o);
} }
} }

View File

@ -7,18 +7,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class CallExpr extends Expression public class CallExpr extends Expression {
{ public CallExpr(Reference f, ExprList el, SourcePosition posn) {
public CallExpr(Reference f, ExprList el, SourcePosition posn){ super(posn);
super(posn); functionRef = f;
functionRef = f; argList = el;
argList = el; }
}
public <A, R> R visit(Visitor<A, R> v, A o) {
public <A,R> R visit(Visitor<A,R> v, A o) { return v.visitCallExpr(this, o);
return v.visitCallExpr(this, o); }
}
public Reference functionRef;
public Reference functionRef; public ExprList argList;
public ExprList argList;
} }

View File

@ -7,18 +7,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class CallStmt extends Statement public class CallStmt extends Statement {
{ public CallStmt(Reference m, ExprList el, SourcePosition posn) {
public CallStmt(Reference m, ExprList el, SourcePosition posn){ super(posn);
super(posn); methodRef = m;
methodRef = m; argList = el;
argList = el; }
}
public <A, R> R visit(Visitor<A, R> v, A o) {
public <A,R> R visit(Visitor<A,R> v, A o) { return v.visitCallStmt(this, o);
return v.visitCallStmt(this, o); }
}
public Reference methodRef;
public Reference methodRef; public ExprList argList;
public ExprList argList;
} }

View File

@ -5,20 +5,23 @@
*/ */
package miniJava.AbstractSyntaxTrees; package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class ClassDecl extends Declaration { public class ClassDecl extends Declaration {
public ClassDecl(String cn, FieldDeclList fdl, MethodDeclList mdl, SourcePosition posn) { public ClassDecl(String cn, FieldDeclList fdl, MethodDeclList mdl, SourcePosition posn) {
super(cn, null, posn); super(cn, null, posn);
fieldDeclList = fdl; fieldDeclList = fdl;
methodDeclList = mdl; methodDeclList = mdl;
}
Identifier ident = new Identifier(cn, posn);
public <A,R> R visit(Visitor<A, R> v, A o) { type = new ClassType(ident, posn);
return v.visitClassDecl(this, o); }
}
public <A, R> R visit(Visitor<A, R> v, A o) {
public FieldDeclList fieldDeclList; return v.visitClassDecl(this, o);
public MethodDeclList methodDeclList; }
public FieldDeclList fieldDeclList;
public MethodDeclList methodDeclList;
} }

View File

@ -7,17 +7,16 @@ package miniJava.AbstractSyntaxTrees;
import java.util.*; import java.util.*;
public class ClassDeclList implements Iterable<ClassDecl> public class ClassDeclList implements Iterable<ClassDecl> {
{
public ClassDeclList() { public ClassDeclList() {
classDeclList = new ArrayList<ClassDecl>(); classDeclList = new ArrayList<ClassDecl>();
} }
public void add(ClassDecl cd){ public void add(ClassDecl cd) {
classDeclList.add(cd); classDeclList.add(cd);
} }
public ClassDecl get(int i){ public ClassDecl get(int i) {
return classDeclList.get(i); return classDeclList.get(i);
} }
@ -31,4 +30,3 @@ public class ClassDeclList implements Iterable<ClassDecl>
private List<ClassDecl> classDeclList; private List<ClassDecl> classDeclList;
} }

View File

@ -7,16 +7,15 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class ClassType extends Type public class ClassType extends Type {
{ public ClassType(Identifier cn, SourcePosition posn) {
public ClassType(Identifier cn, SourcePosition posn){ super(TypeKind.CLASS, posn);
super(TypeKind.CLASS, posn); className = cn;
className = cn; }
}
public <A,R> R visit(Visitor<A,R> v, A o) {
return v.visitClassType(this, o);
}
public Identifier className; public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitClassType(this, o);
}
public Identifier className;
} }

View File

@ -8,22 +8,23 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public abstract class Declaration extends AST { public abstract class Declaration extends AST {
public Declaration(String name, Type type, SourcePosition posn) { public Declaration(String name, Type type, SourcePosition posn) {
super(posn); super(posn);
this.name = name; this.name = name;
this.type = type; this.type = type;
} }
@Override @Override
public String toString() { public String toString() {
if(posn != null) { if (posn != null) {
return this.name + "(Line: " + posn.line + ", Column: " + posn.col + ")"; return this.name + "(Line: " + posn.line + ", Column: " + posn.col
+ ")";
} else { } else {
return super.toString(); return super.toString();
} }
} }
public String name; public String name;
public Type type; public Type type;
} }

View File

@ -3,16 +3,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class Declarators { public class Declarators {
public Declarators(boolean isPrivate, boolean isStatic, Type mt, SourcePosition posn) { public Declarators(boolean isPrivate, boolean isStatic, Type mt,
SourcePosition posn) {
this.isPrivate = isPrivate; this.isPrivate = isPrivate;
this.isStatic = isStatic; this.isStatic = isStatic;
this.mt = mt; this.mt = mt;
this.posn = posn; this.posn = posn;
} }
public boolean isPrivate; public boolean isPrivate;
public boolean isStatic; public boolean isStatic;
public Type mt; public Type mt;
public SourcePosition posn; public SourcePosition posn;
} }

View File

@ -7,27 +7,26 @@ package miniJava.AbstractSyntaxTrees;
import java.util.*; import java.util.*;
public class ExprList implements Iterable<Expression> public class ExprList implements Iterable<Expression> {
{ public ExprList() {
public ExprList() { elist = new ArrayList<Expression>();
elist = new ArrayList<Expression>(); }
}
public void add(Expression e) {
public void add(Expression e){ elist.add(e);
elist.add(e); }
}
public Expression get(int i) {
public Expression get(int i){ return elist.get(i);
return elist.get(i); }
}
public int size() {
public int size() { return elist.size();
return elist.size(); }
}
public Iterator<Expression> iterator() {
public Iterator<Expression> iterator() { return elist.iterator();
return elist.iterator(); }
}
private List<Expression> elist;
private List<Expression> elist;
} }

View File

@ -5,12 +5,12 @@
*/ */
package miniJava.AbstractSyntaxTrees; package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public abstract class Expression extends AST { public abstract class Expression extends AST {
public Expression(SourcePosition posn) { public Expression(SourcePosition posn) {
super (posn); super(posn);
} }
} }

View File

@ -8,17 +8,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class FieldDecl extends MemberDecl { 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 <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitFieldDecl(this, o);
}
}
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 <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitFieldDecl(this, o);
}
}

View File

@ -7,22 +7,21 @@ package miniJava.AbstractSyntaxTrees;
import java.util.*; import java.util.*;
public class FieldDeclList implements Iterable<FieldDecl> public class FieldDeclList implements Iterable<FieldDecl> {
{
public FieldDeclList() { public FieldDeclList() {
fieldDeclList = new ArrayList<FieldDecl>(); fieldDeclList = new ArrayList<FieldDecl>();
} }
public FieldDeclList(FieldDecl f) { public FieldDeclList(FieldDecl f) {
fieldDeclList = new ArrayList<FieldDecl>(); fieldDeclList = new ArrayList<FieldDecl>();
fieldDeclList.add(f); fieldDeclList.add(f);
} }
public void add(FieldDecl cd){ public void add(FieldDecl cd) {
fieldDeclList.add(cd); fieldDeclList.add(cd);
} }
public FieldDecl get(int i){ public FieldDecl get(int i) {
return fieldDeclList.get(i); return fieldDeclList.get(i);
} }
@ -36,4 +35,3 @@ public class FieldDeclList implements Iterable<FieldDecl>
private List<FieldDecl> fieldDeclList; private List<FieldDecl> fieldDeclList;
} }

View File

@ -8,13 +8,13 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class IdRef extends Reference { public class IdRef extends Reference {
public IdRef(Identifier id, SourcePosition posn){ public IdRef(Identifier id, SourcePosition posn) {
super(posn); super(posn);
this.id = id; this.id = id;
} }
public <A,R> R visit(Visitor<A,R> v, A o) { public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitIdRef(this, o); return v.visitIdRef(this, o);
} }

View File

@ -8,14 +8,14 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class Identifier extends Terminal { public class Identifier extends Terminal {
public Identifier (String s, SourcePosition posn) {
super (s,posn);
}
public <A,R> R visit(Visitor<A,R> v, A o) { public Identifier(String s, SourcePosition posn) {
return v.visitIdentifier(this, o); super(s, posn);
} }
public Declaration decl = null; public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitIdentifier(this, o);
}
public Declaration decl = null;
} }

View File

@ -7,27 +7,26 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class IfStmt extends Statement public class IfStmt extends Statement {
{ public IfStmt(Expression b, Statement t, Statement e, SourcePosition posn) {
public IfStmt(Expression b, Statement t, Statement e, SourcePosition posn){ super(posn);
super(posn); cond = b;
cond = b; thenStmt = t;
thenStmt = t; elseStmt = e;
elseStmt = e; }
}
public IfStmt(Expression b, Statement t, SourcePosition posn) {
public IfStmt(Expression b, Statement t, SourcePosition posn){ super(posn);
super(posn); cond = b;
cond = b; thenStmt = t;
thenStmt = t; elseStmt = null;
elseStmt = null; }
}
public <A, R> R visit(Visitor<A, R> v, A o) {
public <A,R> R visit(Visitor<A,R> v, A o) { return v.visitIfStmt(this, o);
return v.visitIfStmt(this, o); }
}
public Expression cond;
public Expression cond; public Statement thenStmt;
public Statement thenStmt; public Statement elseStmt;
public Statement elseStmt;
} }

View File

@ -8,17 +8,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class IndexedRef extends Reference { public class IndexedRef extends Reference {
public IndexedRef(Reference ref, Expression expr, SourcePosition posn){ public IndexedRef(Reference ref, Expression expr, SourcePosition posn) {
super(posn); super(posn);
this.ref = ref; this.ref = ref;
this.indexExpr = expr; this.indexExpr = expr;
} }
public <A,R> R visit(Visitor<A,R> v, A o){ public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitIndexedRef(this, o); return v.visitIndexedRef(this, o);
} }
public Reference ref; public Reference ref;
public Expression indexExpr; public Expression indexExpr;
} }

View File

@ -9,11 +9,11 @@ import miniJava.SyntacticAnalyzer.SourcePosition;
public class IntLiteral extends Literal { public class IntLiteral extends Literal {
public IntLiteral(String s, SourcePosition posn) { public IntLiteral(String s, SourcePosition posn) {
super(s, posn); super(s, posn);
} }
public <A,R> R visit(Visitor<A,R> v, A o) { public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitIntLiteral(this, o); return v.visitIntLiteral(this, o);
} }
} }

View File

@ -7,16 +7,15 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class LiteralExpr extends Expression public class LiteralExpr extends Expression {
{ public LiteralExpr(Literal c, SourcePosition posn) {
public LiteralExpr(Literal c, SourcePosition posn){ super(posn);
super(posn); literal = c;
literal = c; }
}
public <A,R> R visit(Visitor<A,R> v, A o){
return v.visitLiteralExpr(this, o);
}
public Literal literal; public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitLiteralExpr(this, o);
}
public Literal literal;
} }

View File

@ -8,9 +8,9 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public abstract class LocalDecl extends Declaration { public abstract class LocalDecl extends Declaration {
public LocalDecl(String name, Type t, SourcePosition posn){ public LocalDecl(String name, Type t, SourcePosition posn) {
super(name,t,posn); super(name, t, posn);
} }
} }

View File

@ -9,18 +9,19 @@ import miniJava.SyntacticAnalyzer.SourcePosition;
abstract public class MemberDecl extends Declaration { abstract public class MemberDecl extends Declaration {
public MemberDecl(boolean isPrivate, boolean isStatic, Type mt, String name, SourcePosition posn) { public MemberDecl(boolean isPrivate, boolean isStatic, Type mt,
super(name, mt, posn); String name, SourcePosition posn) {
this.isPrivate = isPrivate; super(name, mt, posn);
this.isStatic = isStatic; this.isPrivate = isPrivate;
} this.isStatic = isStatic;
}
public MemberDecl(MemberDecl md, SourcePosition posn){
super(md.name, md.type, posn); public MemberDecl(MemberDecl md, SourcePosition posn) {
this.isPrivate = md.isPrivate; super(md.name, md.type, posn);
this.isStatic = md.isStatic; this.isPrivate = md.isPrivate;
} this.isStatic = md.isStatic;
}
public boolean isPrivate;
public boolean isStatic; public boolean isPrivate;
public boolean isStatic;
} }

View File

@ -8,18 +8,19 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class MethodDecl extends MemberDecl { public class MethodDecl extends MemberDecl {
public MethodDecl(MemberDecl md, ParameterDeclList pl, StatementList sl, Expression e, SourcePosition posn){ public MethodDecl(MemberDecl md, ParameterDeclList pl, StatementList sl,
super(md,posn); Expression e, SourcePosition posn) {
parameterDeclList = pl; super(md, posn);
statementList = sl; parameterDeclList = pl;
returnExp = e; statementList = sl;
returnExp = e;
} }
public <A, R> R visit(Visitor<A, R> v, A o) { public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitMethodDecl(this, o); return v.visitMethodDecl(this, o);
} }
public ParameterDeclList parameterDeclList; public ParameterDeclList parameterDeclList;
public StatementList statementList; public StatementList statementList;
public Expression returnExp; public Expression returnExp;

View File

@ -7,22 +7,21 @@ package miniJava.AbstractSyntaxTrees;
import java.util.*; import java.util.*;
public class MethodDeclList implements Iterable<MethodDecl> public class MethodDeclList implements Iterable<MethodDecl> {
{
public MethodDeclList() { public MethodDeclList() {
methodDeclList = new ArrayList<MethodDecl>(); methodDeclList = new ArrayList<MethodDecl>();
} }
public MethodDeclList(MethodDecl m) { public MethodDeclList(MethodDecl m) {
methodDeclList = new ArrayList<MethodDecl>(); methodDeclList = new ArrayList<MethodDecl>();
methodDeclList.add(m); methodDeclList.add(m);
} }
public void add(MethodDecl cd){ public void add(MethodDecl cd) {
methodDeclList.add(cd); methodDeclList.add(cd);
} }
public MethodDecl get(int i){ public MethodDecl get(int i) {
return methodDeclList.get(i); return methodDeclList.get(i);
} }
@ -36,4 +35,3 @@ public class MethodDeclList implements Iterable<MethodDecl>
private List<MethodDecl> methodDeclList; private List<MethodDecl> methodDeclList;
} }

View File

@ -7,18 +7,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class NewArrayExpr extends NewExpr public class NewArrayExpr extends NewExpr {
{ public NewArrayExpr(Type et, Expression e, SourcePosition posn) {
public NewArrayExpr(Type et, Expression e, SourcePosition posn){ super(posn);
super(posn); eltType = et;
eltType = et; sizeExpr = e;
sizeExpr = e; }
}
public <A,R> R visit(Visitor<A,R> v, A o) {
return v.visitNewArrayExpr(this, o);
}
public Type eltType; public <A, R> R visit(Visitor<A, R> v, A o) {
public Expression sizeExpr; return v.visitNewArrayExpr(this, o);
}
public Type eltType;
public Expression sizeExpr;
} }

View File

@ -8,8 +8,8 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public abstract class NewExpr extends Expression { public abstract class NewExpr extends Expression {
public NewExpr(SourcePosition posn) { public NewExpr(SourcePosition posn) {
super (posn); super(posn);
} }
} }

View File

@ -7,16 +7,15 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class NewObjectExpr extends NewExpr public class NewObjectExpr extends NewExpr {
{ public NewObjectExpr(ClassType ct, SourcePosition posn) {
public NewObjectExpr(ClassType ct, SourcePosition posn){ super(posn);
super(posn); classtype = ct;
classtype = ct; }
}
public <A, R> R visit(Visitor<A, R> v, A o) {
public <A,R> R visit(Visitor<A,R> v, A o) { return v.visitNewObjectExpr(this, o);
return v.visitNewObjectExpr(this, o); }
}
public ClassType classtype;
public ClassType classtype;
} }

View File

@ -10,13 +10,14 @@ import miniJava.SyntacticAnalyzer.Token;
public class Operator extends Terminal { public class Operator extends Terminal {
public Operator (Token t, SourcePosition posn) { public Operator(Token t, SourcePosition posn) {
super (t.spelling, posn); super(t.spelling, posn);
} token = t;
}
public <A,R> R visit(Visitor<A,R> v, A o) { public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitOperator(this, o); return v.visitOperator(this, o);
} }
public Token token; public Token token;
} }

View File

@ -9,14 +9,14 @@ import miniJava.SyntacticAnalyzer.SourcePosition;
public class Package extends AST { public class Package extends AST {
public Package(ClassDeclList cdl, SourcePosition posn) { public Package(ClassDeclList cdl, SourcePosition posn) {
super(posn); super(posn);
classDeclList = cdl; classDeclList = cdl;
} }
public <A,R> R visit(Visitor<A,R> v, A o) {
return v.visitPackage(this, o);
}
public ClassDeclList classDeclList; public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitPackage(this, o);
}
public ClassDeclList classDeclList;
} }

View File

@ -8,13 +8,12 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class ParameterDecl extends LocalDecl { public class ParameterDecl extends LocalDecl {
public ParameterDecl(Type t, String name, SourcePosition posn){ public ParameterDecl(Type t, String name, SourcePosition posn) {
super(name, t, posn); super(name, t, posn);
} }
public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitParameterDecl(this, o);
}
}
public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitParameterDecl(this, o);
}
}

View File

@ -7,32 +7,31 @@ package miniJava.AbstractSyntaxTrees;
import java.util.*; import java.util.*;
public class ParameterDeclList implements Iterable<ParameterDecl> public class ParameterDeclList implements Iterable<ParameterDecl> {
{ public ParameterDeclList() {
public ParameterDeclList() { parameterDeclList = new ArrayList<ParameterDecl>();
parameterDeclList = new ArrayList<ParameterDecl>(); }
}
public ParameterDeclList(ParameterDecl p) {
public ParameterDeclList(ParameterDecl p) { parameterDeclList = new ArrayList<ParameterDecl>();
parameterDeclList = new ArrayList<ParameterDecl>(); parameterDeclList.add(p);
parameterDeclList.add(p); }
}
public void add(ParameterDecl s) {
public void add(ParameterDecl s){ parameterDeclList.add(s);
parameterDeclList.add(s); }
}
public ParameterDecl get(int i) {
public ParameterDecl get(int i){ return parameterDeclList.get(i);
return parameterDeclList.get(i); }
}
public int size() {
public int size() { return parameterDeclList.size();
return parameterDeclList.size(); }
}
public Iterator<ParameterDecl> iterator() {
public Iterator<ParameterDecl> iterator() { return parameterDeclList.iterator();
return parameterDeclList.iterator(); }
}
private List<ParameterDecl> parameterDeclList;
private List<ParameterDecl> parameterDeclList;
} }

View File

@ -8,11 +8,11 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class QualifiedRef extends Reference { public class QualifiedRef extends Reference {
public QualifiedRef(Reference ref, Identifier id, SourcePosition posn){ public QualifiedRef(Reference ref, Identifier id, SourcePosition posn) {
super(posn); super(posn);
this.ref = ref; this.ref = ref;
this.id = id; this.id = id;
} }
@Override @Override

View File

@ -7,16 +7,15 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class RefExpr extends Expression public class RefExpr extends Expression {
{ public RefExpr(Reference r, SourcePosition posn) {
public RefExpr(Reference r, SourcePosition posn){ super(posn);
super(posn); ref = r;
ref = r; }
}
public <A,R> R visit(Visitor<A,R> v, A o) {
return v.visitRefExpr(this, o);
}
public Reference ref; public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitRefExpr(this, o);
}
public Reference ref;
} }

View File

@ -7,11 +7,10 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public abstract class Reference extends AST public abstract class Reference extends AST {
{ public Reference(SourcePosition posn) {
public Reference(SourcePosition posn){
super(posn); super(posn);
} }
public Declaration decl; public Declaration decl;
} }

View File

@ -5,12 +5,12 @@
*/ */
package miniJava.AbstractSyntaxTrees; package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public abstract class Statement extends AST { public abstract class Statement extends AST {
public Statement(SourcePosition posn) { public Statement(SourcePosition posn) {
super (posn); super(posn);
} }
} }

View File

@ -7,27 +7,26 @@ package miniJava.AbstractSyntaxTrees;
import java.util.*; import java.util.*;
public class StatementList implements Iterable<Statement> public class StatementList implements Iterable<Statement> {
{ public StatementList() {
public StatementList() { slist = new ArrayList<Statement>();
slist = new ArrayList<Statement>(); }
}
public void add(Statement s) {
public void add(Statement s){ slist.add(s);
slist.add(s); }
}
public Statement get(int i) {
public Statement get(int i){ return slist.get(i);
return slist.get(i); }
}
public int size() {
public int size() { return slist.size();
return slist.size(); }
}
public Iterator<Statement> iterator() {
public Iterator<Statement> iterator() { return slist.iterator();
return slist.iterator(); }
}
private List<Statement> slist;
private List<Statement> slist;
} }

View File

@ -9,10 +9,10 @@ import miniJava.SyntacticAnalyzer.SourcePosition;
abstract public class Terminal extends AST { abstract public class Terminal extends AST {
public Terminal (String s, SourcePosition posn) { public Terminal(String s, SourcePosition posn) {
super(posn); super(posn);
spelling = s; spelling = s;
} }
public String spelling; public String spelling;
} }

View File

@ -8,7 +8,7 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class ThisRef extends Reference { public class ThisRef extends Reference {
public ThisRef(SourcePosition posn) { public ThisRef(SourcePosition posn) {
super(posn); super(posn);
} }
@ -17,5 +17,5 @@ public class ThisRef extends Reference {
public <A, R> R visit(Visitor<A, R> v, A o) { public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitThisRef(this, o); return v.visitThisRef(this, o);
} }
} }

View File

@ -8,14 +8,12 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
abstract public class Type extends AST { abstract public class Type extends AST {
public Type(TypeKind typ, SourcePosition posn){
super(posn);
typeKind = typ;
}
public TypeKind typeKind;
}
public Type(TypeKind typ, SourcePosition posn) {
super(posn);
typeKind = typ;
}
public TypeKind typeKind;
}

View File

@ -6,12 +6,5 @@
package miniJava.AbstractSyntaxTrees; package miniJava.AbstractSyntaxTrees;
public enum TypeKind { public enum TypeKind {
VOID, VOID, INT, BOOLEAN, CLASS, ARRAY, UNSUPPORTED, ERROR, EQUALS, RELATIONAL;
INT,
BOOLEAN,
CLASS,
ARRAY,
UNSUPPORTED,
ERROR,
VALID;
} }

View File

@ -7,18 +7,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class UnaryExpr extends Expression public class UnaryExpr extends Expression {
{ public UnaryExpr(Operator o, Expression e, SourcePosition posn) {
public UnaryExpr(Operator o, Expression e, SourcePosition posn){ super(posn);
super(posn); operator = o;
operator = o; expr = e;
expr = e; }
}
public <A,R> R visit(Visitor<A,R> v, A o) {
return v.visitUnaryExpr(this, o);
}
public Operator operator; public <A, R> R visit(Visitor<A, R> v, A o) {
public Expression expr; return v.visitUnaryExpr(this, o);
}
public Operator operator;
public Expression expr;
} }

View File

@ -8,12 +8,12 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class VarDecl extends LocalDecl { public class VarDecl extends LocalDecl {
public VarDecl(Type t, String name, SourcePosition posn) { public VarDecl(Type t, String name, SourcePosition posn) {
super(name, t, posn); super(name, t, posn);
} }
public <A,R> R visit(Visitor<A,R> v, A o) { public <A, R> R visit(Visitor<A, R> v, A o) {
return v.visitVarDecl(this, o); return v.visitVarDecl(this, o);
} }
} }

View File

@ -7,18 +7,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class VarDeclStmt extends Statement public class VarDeclStmt extends Statement {
{ public VarDeclStmt(VarDecl vd, Expression e, SourcePosition posn) {
public VarDeclStmt(VarDecl vd, Expression e, SourcePosition posn){ super(posn);
super(posn); varDecl = vd;
varDecl = vd; initExp = e;
initExp = e; }
}
public <A,R> R visit(Visitor<A,R> v, A o) {
return v.visitVardeclStmt(this, o);
}
public VarDecl varDecl; public <A, R> R visit(Visitor<A, R> v, A o) {
public Expression initExp; return v.visitVardeclStmt(this, o);
}
public VarDecl varDecl;
public Expression initExp;
} }

View File

@ -6,52 +6,75 @@
package miniJava.AbstractSyntaxTrees; package miniJava.AbstractSyntaxTrees;
/** /**
* An implementation of the Visitor interface provides a method visitX * An implementation of the Visitor interface provides a method visitX for each
* for each non-abstract AST class X. * non-abstract AST class X.
*/ */
public interface Visitor<ArgType,ResultType> { public interface Visitor<ArgType, ResultType> {
// Package // Package
public ResultType visitPackage(Package prog, ArgType arg); public ResultType visitPackage(Package prog, ArgType arg);
// Declarations // Declarations
public ResultType visitClassDecl(ClassDecl cd, ArgType arg); 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 visitFieldDecl(FieldDecl fd, ArgType arg);
public ResultType visitIdentifier(Identifier id, ArgType arg);
public ResultType visitOperator(Operator op, ArgType arg); public ResultType visitMethodDecl(MethodDecl md, ArgType arg);
public ResultType visitIntLiteral(IntLiteral num, ArgType arg);
public ResultType visitBooleanLiteral(BooleanLiteral bool, 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);
} }

View File

@ -7,18 +7,17 @@ package miniJava.AbstractSyntaxTrees;
import miniJava.SyntacticAnalyzer.SourcePosition; import miniJava.SyntacticAnalyzer.SourcePosition;
public class WhileStmt extends Statement public class WhileStmt extends Statement {
{ public WhileStmt(Expression b, Statement s, SourcePosition posn) {
public WhileStmt(Expression b, Statement s, SourcePosition posn){ super(posn);
super(posn); cond = b;
cond = b; body = s;
body = s; }
}
public <A,R> R visit(Visitor<A,R> v, A o) {
return v.visitWhileStmt(this, o);
}
public Expression cond; public <A, R> R visit(Visitor<A, R> v, A o) {
public Statement body; return v.visitWhileStmt(this, o);
}
public Expression cond;
public Statement body;
} }

View File

@ -3,25 +3,24 @@ package miniJava;
import java.io.*; import java.io.*;
import miniJava.SyntacticAnalyzer.*; import miniJava.SyntacticAnalyzer.*;
import miniJava.AbstractSyntaxTrees.ASTDisplay; // import miniJava.AbstractSyntaxTrees.ASTDisplay;
import miniJava.AbstractSyntaxTrees.Package; import miniJava.AbstractSyntaxTrees.Package;
import miniJava.ContextualAnalyzer.Analyzer; import miniJava.ContextualAnalyzer.Analyzer;
import miniJava.ContextualAnalyzer.Reporter;
import miniJava.Exceptions.*; import miniJava.Exceptions.*;
public class Compiler { public class Compiler {
private static final int rc = 4; public static final int rc = 4;
public static void main(String[] args) { public static void main(String[] args) {
if(args.length == 0) { if (args.length == 0) {
System.out.println("No file specified"); System.out.println("No file specified");
System.exit(rc); System.exit(rc);
} }
try(FileReader input = new FileReader(args[0])) { try (FileReader input = new FileReader(args[0])) {
// Setup // Setup
Scanner scanner = new Scanner(new BufferedReader(input)); Scanner scanner = new Scanner(new BufferedReader(input));
Parser parser = new Parser(scanner); Parser parser = new Parser(scanner);
@ -30,24 +29,22 @@ public class Compiler {
// Display // Display
// ASTDisplay display = new ASTDisplay(); // ASTDisplay display = new ASTDisplay();
// display.showTree(p); // display.showTree(p);
// Identification/Type Checking // Identification/Type Checking
Analyzer analyzer = new Analyzer(); Analyzer analyzer = new Analyzer();
analyzer.visitPackage(p, null); analyzer.visitPackage(p, null);
if(Reporter.error) System.exit(rc); System.exit(analyzer.validate());
System.exit(0); } catch (FileNotFoundException e) {
} catch(FileNotFoundException e) {
System.out.println("***" + e.getMessage()); System.out.println("***" + e.getMessage());
} catch(IOException e) { } catch (IOException e) {
System.out.println("***" + e.getMessage()); System.out.println("***" + e.getMessage());
}catch(ScanningException e) { } catch (ScanningException e) {
System.out.println("***" + e.getMessage()); System.out.println("***" + e.getMessage());
} catch(ParsingException e) { } catch (ParsingException e) {
System.out.println("***" + e.getMessage()); System.out.println("***" + e.getMessage());
} }
System.exit(rc); System.exit(rc);
} }

View File

@ -1,454 +1,568 @@
package miniJava.ContextualAnalyzer; package miniJava.ContextualAnalyzer;
import java.util.*;
import miniJava.Compiler;
import miniJava.Exceptions.*;
import miniJava.SyntacticAnalyzer.*;
import miniJava.SyntacticAnalyzer.Scanner;
import miniJava.AbstractSyntaxTrees.*; import miniJava.AbstractSyntaxTrees.*;
import miniJava.AbstractSyntaxTrees.Package; import miniJava.AbstractSyntaxTrees.Package;
import miniJava.SyntacticAnalyzer.Parser;
import miniJava.SyntacticAnalyzer.Scanner;
import miniJava.Exceptions.*;
// Check types
// Ensure static members
// Check for main function
public class Analyzer implements Visitor<IdentificationTable, Type> { public class Analyzer implements Visitor<IdentificationTable, Type> {
// Topmost Identification Table private MethodDecl mainMethod = null;
private ClassDecl currentClassDecl = null;
private MethodDecl currentMethodDecl = null;
private IdentificationTable table = new IdentificationTable(); private IdentificationTable table = new IdentificationTable();
// Current class decl is for use with the 'this' keyword // Keep track of all predefined names to handle
private Declaration currentClassDecl = null; private static ArrayList<String> predefined;
static
{
predefined = new ArrayList<String>();
predefined.add("class _PrintStream { public void println(int n){} }");
predefined.add("class System { public static _PrintStream out; }");
predefined.add("class String { }");
}
/** /**
* Adds predefined names to identification table. * 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() { public Analyzer() throws ParsingException, ScanningException {
try { for (String s : predefined) {
String __PrintStream = "class _PrintStream { public void println(int n){} }"; Scanner scanner = new Scanner(s);
new Parser(new Scanner(__PrintStream)).parse().visit(this, table); Parser parser = new Parser(scanner);
parser.parse().visit(this, table);
String _System = "class System { public static _PrintStream out; }";
new Parser(new Scanner(_System)).parse().visit(this, table);
String _String = "class String { }";
new Parser(new Scanner(_String)).parse().visit(this, table);
} catch(ParsingException e) {
System.out.println("Predefined declarations parsing error!");
} catch(ScanningException e) {
System.out.println("Predefined declarations scanning error!");
} }
} }
/** /**
* Check that two types match. * Checks that contextual analysis was successful or not, returning the
* @param t1 * proper error code in either case.
* @param t2 *
* @return * @return
*/ */
private void match(Type t1, Type t2) { public int validate() {
// Exactly one public static void main(String[] args) function must be declared
// Check class types match if (mainMethod == null)
if(t1.typeKind == TypeKind.CLASS) { Reporter.report(ErrorType.MAIN_UNDECLARED, null, null);
if(t2.typeKind != TypeKind.CLASS) {
Reporter.report(ErrorType.TYPE_MISMATCH, t1, t2); return (Reporter.error) ? Compiler.rc : 0;
} else {
ClassType c1 = (ClassType) t1;
ClassType c2 = (ClassType) t2;
if(!c1.className.spelling.equals(c2.className.spelling)) {
Reporter.report(ErrorType.TYPE_CLASS_MISMATCH, t1, t2);
}
}
}
// Check array types match
else if(t1.typeKind == TypeKind.ARRAY) {
if(t2.typeKind != TypeKind.ARRAY) {
Reporter.report(ErrorType.TYPE_MISMATCH, t1, t2);
} else {
ArrayType a1 = (ArrayType) t1;
ArrayType a2 = (ArrayType) t2;
if(a1.eltType.typeKind != a2.eltType.typeKind) {
Reporter.report(ErrorType.TYPE_ARRAY_MISMATCH, t1, t2);
}
}
}
// Check primitive types match
else if(t1.typeKind != t2.typeKind) {
Reporter.report(ErrorType.TYPE_MISMATCH, t1, t2);
}
} }
@Override
// /////////////////////////////////////////////////////////////////////////////
//
// PACKAGE
//
// /////////////////////////////////////////////////////////////////////////////
public Type visitPackage(Package prog, IdentificationTable arg) { public Type visitPackage(Package prog, IdentificationTable arg) {
/* Since classes and static methods/fields can be referenced /*
* before the classes themselves are declared, we preprocess * Since classes and static methods/fields can be referenced before the
* all classes and methods first. * classes themselves are declared, we preprocess all classes and
* methods first.
*/ */
for(ClassDecl cd : prog.classDeclList) { for (ClassDecl cd : prog.classDeclList) {
IdentificationTable cdTable = table.openScope(cd); IdentificationTable cdTable = table.openScope(cd);
if(cdTable != null) {
if (cdTable != null) {
// Simply add fields to current scope // Simply add fields to current scope
for(FieldDecl fd : cd.fieldDeclList) { for (FieldDecl fd : cd.fieldDeclList) {
cdTable.setDeclarationAtScope(fd); cdTable.setDeclarationAtScope(fd);
} }
// Just Add Declaration (also creates another identification table) // Just Add Declaration (also creates another identification table)
for(MethodDecl md : cd.methodDeclList) { for (MethodDecl md : cd.methodDeclList) {
cdTable.openScope(md); cdTable.openScope(md);
} }
} }
} }
// Begin Traversal // Begin Traversal
for(ClassDecl cd : prog.classDeclList) { for (ClassDecl cd : prog.classDeclList) {
currentClassDecl = cd; currentClassDecl = cd;
cd.visit(this, table); cd.visit(this, table);
} }
return null; return null;
} }
@Override
// /////////////////////////////////////////////////////////////////////////////
//
// DECLARATIONS
//
// /////////////////////////////////////////////////////////////////////////////
public Type visitClassDecl(ClassDecl cd, IdentificationTable arg) { public Type visitClassDecl(ClassDecl cd, IdentificationTable arg) {
IdentificationTable cdTable = arg.getScope(cd); IdentificationTable cdTable = arg.getScope(cd);
if(cdTable != null) {
if (cdTable != null) {
for(FieldDecl fd : cd.fieldDeclList) {
for (FieldDecl fd : cd.fieldDeclList) {
fd.visit(this, cdTable); fd.visit(this, cdTable);
} }
for(MethodDecl md : cd.methodDeclList) { for (MethodDecl md : cd.methodDeclList) {
currentMethodDecl = md;
md.visit(this, cdTable); md.visit(this, cdTable);
} }
} }
return cd.type; return cd.type;
} }
@Override
public Type visitFieldDecl(FieldDecl fd, IdentificationTable arg) { public Type visitFieldDecl(FieldDecl fd, IdentificationTable arg) {
// Must check that the type of the field can be identified // Must check that the type of the field can be identified
table.validateClassId(fd.type); if (!table.classExists(fd.type)) {
Reporter.report(ErrorType.UNDECLARED_TYPE, fd.type, null);
}
return fd.type; return fd.type;
} }
@Override
public Type visitMethodDecl(MethodDecl md, IdentificationTable arg) { public Type visitMethodDecl(MethodDecl md, IdentificationTable arg) {
IdentificationTable mdTable = arg.getScope(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;
}
// Must check that the type of the method can be identified // Must check that the type of the method can be identified
table.validateClassId(md.type); if (!table.classExists(md.type)) {
Reporter.report(ErrorType.UNDECLARED_TYPE, md.type, null);
}
// Continue Traversal // Continue Traversal
if(mdTable != null) { IdentificationTable mdTable = arg.getScope(md);
for(ParameterDecl pd : md.parameterDeclList) { if (mdTable != null) {
for (ParameterDecl pd : md.parameterDeclList)
pd.visit(this, mdTable); pd.visit(this, mdTable);
} for (Statement s : md.statementList)
for(Statement s : md.statementList) {
s.visit(this, mdTable); s.visit(this, mdTable);
}
// Check that return type matches expected type // Check that return type matches expected type
if(md.returnExp != null) { 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); Type returnType = md.returnExp.visit(this, mdTable);
match(md.type, returnType); IdentificationTable.match(md.type, returnType, true);
} else if(md.type.typeKind != TypeKind.VOID) {
Reporter.report(ErrorType.NO_RETURN_EXPRESSION, md.type);
} }
} }
return md.type; return md.type;
} }
@Override
public Type visitParameterDecl(ParameterDecl pd, IdentificationTable arg) { public Type visitParameterDecl(ParameterDecl pd, IdentificationTable arg) {
arg.setDeclarationAtScope(pd); arg.setDeclarationAtScope(pd);
table.validateClassId(pd.type); if (!table.classExists(pd.type)) {
Reporter.report(ErrorType.UNDECLARED_TYPE, pd.type, null);
}
return pd.type; return pd.type;
} }
@Override
public Type visitVarDecl(VarDecl decl, IdentificationTable arg) { public Type visitVarDecl(VarDecl decl, IdentificationTable arg) {
arg.setDeclarationAtScope(decl); arg.setDeclarationAtScope(decl);
table.validateClassId(decl.type); if (!table.classExists(decl.type)) {
Reporter.report(ErrorType.UNDECLARED_TYPE, decl.type, null);
}
return decl.type; return decl.type;
} }
// /////////////////////////////////////////////////////////////////////////////
//
// TYPES
//
// /////////////////////////////////////////////////////////////////////////////
@Override
public Type visitBaseType(BaseType type, IdentificationTable arg) { public Type visitBaseType(BaseType type, IdentificationTable arg) {
return type; return type;
} }
@Override
public Type visitClassType(ClassType type, IdentificationTable arg) { public Type visitClassType(ClassType type, IdentificationTable arg) {
type.className.visit(this, arg); type.className.visit(this, arg);
return type; return type;
} }
@Override
public Type visitArrayType(ArrayType type, IdentificationTable arg) { public Type visitArrayType(ArrayType type, IdentificationTable arg) {
type.eltType.visit(this, arg); type.eltType.visit(this, arg);
return type; return type;
} }
// /////////////////////////////////////////////////////////////////////////////
//
// STATEMENTS
//
// /////////////////////////////////////////////////////////////////////////////
@Override
public Type visitBlockStmt(BlockStmt stmt, IdentificationTable arg) { public Type visitBlockStmt(BlockStmt stmt, IdentificationTable arg) {
arg.pushLevel(); arg.pushLevel();
for(Statement s : stmt.sl) { for (Statement s : stmt.sl)
s.visit(this, arg); s.visit(this, arg);
}
arg.popLevel(); arg.popLevel();
return null; return null;
} }
@Override // The stmt of the vardecl may not refer to the variable itself so we check the stmt first
public Type visitVardeclStmt(VarDeclStmt stmt, IdentificationTable arg) { public Type visitVardeclStmt(VarDeclStmt stmt, IdentificationTable arg) {
// The stmt of the vardecl may not refer to the variable itself so we check the stmt first
Type initExpType = stmt.initExp.visit(this, arg); Type initExpType = stmt.initExp.visit(this, arg);
Type varDeclType = stmt.varDecl.visit(this, arg); Type varDeclType = stmt.varDecl.visit(this, arg);
match(varDeclType, initExpType); IdentificationTable.match(varDeclType, initExpType, true);
return varDeclType; return varDeclType;
} }
@Override
public Type visitAssignStmt(AssignStmt stmt, IdentificationTable arg) { public Type visitAssignStmt(AssignStmt stmt, IdentificationTable arg) {
Type valType = stmt.val.visit(this, arg); Type valType = stmt.val.visit(this, arg);
Type refType = stmt.ref.visit(this, arg); Type refType = stmt.ref.visit(this, arg);
match(valType, refType); IdentificationTable.match(valType, refType, true);
return refType; return refType;
} }
@Override
public Type visitCallStmt(CallStmt stmt, IdentificationTable arg) { public Type visitCallStmt(CallStmt stmt, IdentificationTable arg) {
Type methodType = stmt.methodRef.visit(this, arg); Type methodType = stmt.methodRef.visit(this, arg);
// Check that parameter count is correct and each type is correct // Check that parameter count is correct and each type is correct
MethodDecl decl = (MethodDecl) stmt.methodRef.decl; MethodDecl decl = (MethodDecl) stmt.methodRef.decl;
if(decl.parameterDeclList.size() != stmt.argList.size()) { if (decl.parameterDeclList.size() != stmt.argList.size()) {
Reporter.report(ErrorType.INVALID_PARAM_COUNT, stmt); Reporter.report(ErrorType.INVALID_PARAM_COUNT, stmt, decl);
} else { } else {
for(int i = 0; i < stmt.argList.size(); i++) { for (int i = 0; i < stmt.argList.size(); i++) {
Type exprType = stmt.argList.get(i).visit(this, arg); Type exprType = stmt.argList.get(i).visit(this, arg);
Type pdType = decl.parameterDeclList.get(i).type; Type pdType = decl.parameterDeclList.get(i).type;
match(pdType, exprType); IdentificationTable.match(pdType, exprType, true);
} }
} }
return methodType; return methodType;
} }
@Override
public Type visitIfStmt(IfStmt stmt, IdentificationTable arg) { public Type visitIfStmt(IfStmt stmt, IdentificationTable arg) {
// The conditional statment must be a boolean // The conditional statment must be a boolean
Type condType = stmt.cond.visit(this, arg); Type condType = stmt.cond.visit(this, arg);
match(new BaseType(TypeKind.BOOLEAN, null), condType); IdentificationTable.match(new BaseType(TypeKind.BOOLEAN, null), condType, true);
// A single vardecl cannot exist after a conditional statement // A single vardecl cannot exist after a conditional statement
if(stmt.thenStmt instanceof VarDeclStmt) { if (stmt.thenStmt instanceof VarDeclStmt) {
Reporter.report(ErrorType.VAR_COND_ONLY, stmt.thenStmt); Reporter.report(ErrorType.SINGLE_VARCOND, stmt.thenStmt, null);
} else { } else {
stmt.thenStmt.visit(this, arg); stmt.thenStmt.visit(this, arg);
if(stmt.elseStmt != null) { if (stmt.elseStmt != null) {
if(stmt.elseStmt instanceof VarDeclStmt) { if (stmt.elseStmt instanceof VarDeclStmt) {
Reporter.report(ErrorType.VAR_COND_ONLY, stmt.elseStmt); Reporter.report(ErrorType.SINGLE_VARCOND, stmt.elseStmt,
null);
} else { } else {
stmt.elseStmt.visit(this, arg); stmt.elseStmt.visit(this, arg);
} }
} }
} }
return null; return null;
} }
@Override
public Type visitWhileStmt(WhileStmt stmt, IdentificationTable arg) { public Type visitWhileStmt(WhileStmt stmt, IdentificationTable arg) {
// The conditional statment must be a boolean // The conditional statment must be a boolean
Type condType = stmt.cond.visit(this, arg); Type condType = stmt.cond.visit(this, arg);
match(new BaseType(TypeKind.BOOLEAN, null), condType); IdentificationTable.match(new BaseType(TypeKind.BOOLEAN, null), condType, true);
if(stmt.body instanceof VarDeclStmt) { // A single vardecl cannot exist after a conditional statement
Reporter.report(ErrorType.VAR_COND_ONLY, stmt.body); if (stmt.body instanceof VarDeclStmt) {
Reporter.report(ErrorType.SINGLE_VARCOND, stmt.body, null);
} else { } else {
stmt.body.visit(this, arg); stmt.body.visit(this, arg);
} }
return null; return null;
} }
@Override
// /////////////////////////////////////////////////////////////////////////////
//
// EXPRESSIONS
//
// /////////////////////////////////////////////////////////////////////////////
public Type visitUnaryExpr(UnaryExpr expr, IdentificationTable arg) { public Type visitUnaryExpr(UnaryExpr expr, IdentificationTable arg) {
Type opType = expr.operator.visit(this, arg); Type opType = expr.operator.visit(this, arg);
Type exprType = expr.expr.visit(this, arg); Type exprType = expr.expr.visit(this, arg);
match(opType, exprType); IdentificationTable.match(opType, exprType, true);
return null; return opType;
} }
@Override
public Type visitBinaryExpr(BinaryExpr expr, IdentificationTable arg) { public Type visitBinaryExpr(BinaryExpr expr, IdentificationTable arg) {
Type opType = expr.operator.visit(this, arg); Type opType = expr.operator.visit(this, arg);
Type leftType = expr.left.visit(this, arg); Type leftType = expr.left.visit(this, arg);
Type rightType = expr.right.visit(this, arg); Type rightType = expr.right.visit(this, arg);
match(opType, leftType); // Both sides must be the same
match(opType, rightType); if(opType.typeKind == TypeKind.EQUALS) {
IdentificationTable.match(leftType, rightType, true);
return new BaseType(TypeKind.BOOLEAN, opType.posn);
}
return null; // 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;
} }
@Override
public Type visitRefExpr(RefExpr expr, IdentificationTable arg) { public Type visitRefExpr(RefExpr expr, IdentificationTable arg) {
Type exprType = expr.ref.visit(this, arg);
return expr.ref.visit(this, arg); return exprType;
} }
@Override
public Type visitCallExpr(CallExpr expr, IdentificationTable arg) { public Type visitCallExpr(CallExpr expr, IdentificationTable arg) {
Type functionType = expr.functionRef.visit(this, arg); Type functionRefType = expr.functionRef.visit(this, arg);
// Check that parameter count is correct and each type is correct if(expr.functionRef.decl instanceof MethodDecl) {
MethodDecl decl = (MethodDecl) expr.functionRef.decl;
if(decl.parameterDeclList.size() != expr.argList.size()) { MethodDecl decl = (MethodDecl) expr.functionRef.decl;
Reporter.report(ErrorType.INVALID_PARAM_COUNT, expr);
// 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);
}
}
} else { } else {
for(int i = 0; i < expr.argList.size(); i++) { Reporter.report(ErrorType.NONFUNCTION_CALL, expr, null);
Type exprType = expr.argList.get(i).visit(this, arg); }
Type pdType = decl.parameterDeclList.get(i).type;
match(pdType, exprType); return functionRefType;
}
public Type visitLiteralExpr(LiteralExpr expr, IdentificationTable arg) {
Type literalType = expr.literal.visit(this, arg);
return literalType;
}
public Type visitNewObjectExpr(NewObjectExpr expr, IdentificationTable arg) {
Type objectType = expr.classtype.visit(this, arg);
return objectType;
}
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);
}
Type eltType = expr.eltType.visit(this, arg);
return new ArrayType(eltType, expr.posn);
}
// /////////////////////////////////////////////////////////////////////////////
//
// REFERENCES
//
// /////////////////////////////////////////////////////////////////////////////
public Type visitQualifiedRef(QualifiedRef ref, IdentificationTable arg) {
Type refType = ref.ref.visit(this, arg);
// Note qualified ref's only make sense in the context of classes
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
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
else if(qualified instanceof ClassDecl) {
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);
} }
} }
return functionType; // The member should not be a method, as this is unsupported
} else if(qualified instanceof MethodDecl) {
Reporter.report(ErrorType.UNDEFINED, ref.id, null);
@Override }
public Type visitLiteralExpr(LiteralExpr expr, IdentificationTable arg) {
// Otherwise, we can assume the object is a variable and attempt to access members
return expr.literal.visit(this, arg); else if(md.isPrivate && currentClassDecl != qualClassDecl) {
} Reporter.report(ErrorType.VISIBILITY, md, ref.id);
return new BaseType(TypeKind.ERROR, ref.id.posn);
@Override
public Type visitNewObjectExpr(NewObjectExpr expr, IdentificationTable arg) {
return expr.classtype.visit(this, arg);
}
@Override
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);
} }
return expr.eltType.visit(this, arg); ref.id.decl = md;
ref.decl = md;
return md.type;
} }
@Override
public Type visitQualifiedRef(QualifiedRef ref, IdentificationTable arg) {
ref.ref.visit(this, arg);
ref.id.visit(this, arg);
// Check that each declaration is nested properly
if(ref.decl == null || table.getDeclaration(ref.decl.name) == null) {
System.out.println(ref.id.spelling);
// report(ErrorType.MISSING_DECL, ref.ref.decl);
}
return null;
}
@Override
public Type visitIndexedRef(IndexedRef ref, IdentificationTable arg) { public Type visitIndexedRef(IndexedRef ref, IdentificationTable arg) {
ref.ref.visit(this, arg);
ref.decl = ref.ref.decl; Type refType = ref.ref.visit(this, arg);
// Make sure index is an integer // Make sure index is an integer
Type indexExprType = ref.indexExpr.visit(this, arg); Type indexExprType = ref.indexExpr.visit(this, arg);
if(indexExprType.typeKind != TypeKind.INT) { if (indexExprType.typeKind != TypeKind.INT) {
Reporter.report(ErrorType.INVALID_INDEX, ref.indexExpr); Reporter.report(ErrorType.INVALID_INDEX, ref.indexExpr, null);
} }
return ref.decl.type; ref.decl = ref.ref.decl;
return refType;
} }
@Override
public Type visitIdRef(IdRef ref, IdentificationTable arg) { public Type visitIdRef(IdRef ref, IdentificationTable arg) {
ref.id.visit(this, arg); Type idType = ref.id.visit(this, arg);
ref.decl = ref.id.decl; ref.decl = ref.id.decl;
return ref.decl.type; return idType;
} }
@Override
public Type visitThisRef(ThisRef ref, IdentificationTable arg) { public Type visitThisRef(ThisRef ref, IdentificationTable arg) {
ref.decl = currentClassDecl; ref.decl = currentClassDecl;
if(currentMethodDecl.isStatic) {
Reporter.report(ErrorType.THIS, ref, currentMethodDecl);
}
return ref.decl.type; return ref.decl.type;
} }
// /////////////////////////////////////////////////////////////////////////////
//
// TERMINALS
//
// /////////////////////////////////////////////////////////////////////////////
@Override
public Type visitIdentifier(Identifier id, IdentificationTable arg) { public Type visitIdentifier(Identifier id, IdentificationTable arg) {
// Try to find identifier, reporting a message if it cannot be found
Declaration decl = arg.getDeclaration(id.spelling); // Check if identifier can be found in current scope
if(decl == null) { Declaration decl = arg.getDeclarationAtScope(id.spelling);
Reporter.report(ErrorType.UNIDENTIFIED, id); if (decl != null) { id.decl = decl; return decl.type; }
return new BaseType(TypeKind.ERROR, null);
// 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 { } else {
id.decl = decl;
return decl.type; // 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;
} }
} }
@Override
public Type visitOperator(Operator op, IdentificationTable arg) { public Type visitOperator(Operator op, IdentificationTable arg) {
switch(op.token.spelling) { switch (op.token.spelling) {
case "!": case "!":
case ">":
case "<":
case "==":
case "<=":
case ">=":
case "!=":
case "&&": case "&&":
case "||": case "||":
return new BaseType(TypeKind.BOOLEAN, op.posn); return new BaseType(TypeKind.BOOLEAN, op.posn);
case ">":
case "<":
case "<=":
case ">=":
return new BaseType(TypeKind.RELATIONAL, op.posn);
case "+": case "+":
case "-": case "-":
case "*": case "*":
case "/": case "/":
return new BaseType(TypeKind.INT, op.posn); return new BaseType(TypeKind.INT, op.posn);
default: case "==":
Reporter.report(ErrorType.UNIDENTIFIED_TYPE, op); case "!=":
return new BaseType(TypeKind.ERROR, op.posn); return new BaseType(TypeKind.EQUALS, op.posn);
} }
return null;
} }
@Override
public Type visitIntLiteral(IntLiteral num, IdentificationTable arg) { public Type visitIntLiteral(IntLiteral num, IdentificationTable arg) {
return new BaseType(TypeKind.INT, num.posn); return new BaseType(TypeKind.INT, num.posn);
} }
@Override
public Type visitBooleanLiteral(BooleanLiteral bool, IdentificationTable arg) { public Type visitBooleanLiteral(BooleanLiteral bool, IdentificationTable arg) {
return new BaseType(TypeKind.BOOLEAN, bool.posn); return new BaseType(TypeKind.BOOLEAN, bool.posn);
} }

View File

@ -1,26 +1,22 @@
package miniJava.ContextualAnalyzer; package miniJava.ContextualAnalyzer;
import java.util.HashMap; import java.util.*;
import java.util.ArrayList;
import miniJava.AbstractSyntaxTrees.ClassType; import miniJava.AbstractSyntaxTrees.*;
import miniJava.AbstractSyntaxTrees.Declaration;
import miniJava.AbstractSyntaxTrees.Type;
import miniJava.AbstractSyntaxTrees.TypeKind;
public class IdentificationTable { public class IdentificationTable {
private IdentificationTable parent; private IdentificationTable parent;
private HashMap<String, IdentificationTable> scope; private HashMap<String, IdentificationTable> scope;
private ArrayList<HashMap<String, Declaration>> table; private ArrayList<HashMap<String, Declaration>> table;
/** /**
* *
*/ */
public IdentificationTable() { public IdentificationTable() {
this(null); this(null);
} }
/** /**
* *
* @param parent * @param parent
@ -31,31 +27,31 @@ public class IdentificationTable {
this.table = new ArrayList<HashMap<String, Declaration>>(); this.table = new ArrayList<HashMap<String, Declaration>>();
this.table.add(new HashMap<String, Declaration>()); this.table.add(new HashMap<String, Declaration>());
} }
/** /**
* Adds another level for variables to be stored at (they will be * Adds another level for variables to be stored at
* removed when popping said level).
*/
public void pushLevel() {
table.add(new HashMap<String, Declaration>());
}
/**
* Removes all variables declared at the current level (these are
* no longer accessible).
*/ */
public void popLevel() { public void popLevel() {
table.remove(table.size() - 1); table.remove(table.size() - 1);
} }
/** /**
* This method will only ever be called with class/method declarations * Removes all variables declared at the current level
*/
public void pushLevel() {
table.add(new HashMap<String, Declaration>());
}
/**
* This method will only ever be called with class/method declarations.
*
* @param decl * @param decl
* @return * @return
*/ */
public IdentificationTable openScope(Declaration decl) { public IdentificationTable openScope(Declaration decl) {
if(scope.containsKey(decl.name) || getDeclarationAtScope(decl.name) != null) { Declaration current = getDeclarationAtScope(decl.name);
Reporter.report(ErrorType.REDEFINITION, decl); if (scope.containsKey(decl.name) || current != null) {
Reporter.report(ErrorType.REDEFINITION, decl, current);
return null; return null;
} else { } else {
table.get(table.size() - 1).put(decl.name, decl); table.get(table.size() - 1).put(decl.name, decl);
@ -63,83 +59,163 @@ public class IdentificationTable {
return scope.get(decl.name); return scope.get(decl.name);
} }
} }
/** /**
* Return nested scope corresponding to declaration (or null if non-existant). * Return nested scope corresponding to declaration (or null if
* non-existant).
*
* @param decl * @param decl
* @return * @return
*/ */
public IdentificationTable getScope(Declaration decl) { public IdentificationTable getScope(Declaration decl) {
if(scope.containsKey(decl.name)) { if (scope.containsKey(decl.name)) {
return scope.get(decl.name); return scope.get(decl.name);
} }
return null; return null;
} }
/** /**
* Iterates through all parents and tries to find the specified * Iterates through all parents and tries to find the specified declaration
* declaration by name. * by name.
*
* @param name * @param name
* @return * @return
*/ */
public Declaration getDeclaration(String name) { public Declaration getDeclaration(String name) {
IdentificationTable current = this; IdentificationTable current = this;
while(current != null) { while (current != null) {
Declaration decl = current.getDeclarationAtScope(name); Declaration decl = current.getDeclarationAtScope(name);
if(decl == null) { if (decl == null) current = current.parent;
current = current.parent; else return decl;
} else {
return decl;
}
} }
return null; return null;
} }
/** /**
* Iterates through levels (from higher to lower) for declaration, * Iterates through levels (from higher to lower) for declaration, returning
* returning none if it does not exist. * none if it does not exist.
*
* @param name * @param name
* @return * @return
*/ */
public Declaration getDeclarationAtScope(String name) { public Declaration getDeclarationAtScope(String name) {
for(int i = table.size() - 1; i >= 0; i--) { for (int i = table.size() - 1; i >= 0; i--) {
HashMap<String, Declaration> level = table.get(i); HashMap<String, Declaration> level = table.get(i);
if(level.containsKey(name)) { if (level.containsKey(name)) return level.get(name);
return level.get(name);
}
} }
return null; return null;
} }
/** /**
* Add declaration to current table's table member. * Add declaration to current table's table member.
*
* @param name * @param name
*/ */
public void setDeclarationAtScope(Declaration decl) { public void setDeclarationAtScope(Declaration decl) {
for(int i = 0; i < table.size(); i++) { for (int i = 0; i < table.size(); i++) {
HashMap<String, Declaration> level = table.get(i); HashMap<String, Declaration> level = table.get(i);
if(level.containsKey(decl.name)) { if (level.containsKey(decl.name)) {
Reporter.report(ErrorType.REDEFINITION, decl); Declaration defined = level.get(decl.name);
Reporter.report(ErrorType.REDEFINITION, decl, defined);
return; return;
} }
} }
table.get(table.size() - 1).put(decl.name, decl); table.get(table.size() - 1).put(decl.name, decl);
} }
/** /**
* Checks that the passed class type does exist. * Checks whether the specified class has been declared.
* @param ct *
* @param t
* @return
*/ */
public void validateClassId(Type t) { public boolean classExists(Type t) {
if(t.typeKind == TypeKind.CLASS) { if (t.typeKind == TypeKind.CLASS) {
ClassType ct = (ClassType) t; ClassType ct = (ClassType) t;
if(getDeclaration(ct.className.spelling) == null) { return getDeclaration(ct.className.spelling) != null;
Reporter.report(ErrorType.MISSING_DECL, ct); }
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;
} }
} }

View File

@ -3,120 +3,168 @@ package miniJava.ContextualAnalyzer;
import miniJava.AbstractSyntaxTrees.*; import miniJava.AbstractSyntaxTrees.*;
enum ErrorType { enum ErrorType {
VAR_COND_ONLY, THIS,
MISSING_DECL, NONFUNCTION_CALL,
UNIDENTIFIED, UNDEFINED,
REDEFINITION, STATIC,
INVALID_PARAM_COUNT, VISIBILITY,
INVALID_INDEX, NO_RETURN,
TYPE_MISMATCH, TYPE_MISMATCH,
UNIDENTIFIED_TYPE, REDEFINITION,
TYPE_CLASS_MISMATCH, MAIN_UNDECLARED,
TYPE_ARRAY_MISMATCH, INVALID_PARAM_COUNT,
NO_RETURN_EXPRESSION; MULTIPLE_MAIN,
UNDECLARED_TYPE,
SINGLE_VARCOND,
INVALID_INDEX
} }
public class Reporter { public class Reporter {
public static boolean error = false; public static boolean error = false;
/** /**
* Prints out to console correct error message. * Convenience function for getting type names.
* @param type *
* @param ast * @param t
* @return
*/ */
public static void report(ErrorType type, AST ast) { private static String getTypeName(Type t) {
error = true; if (t instanceof ClassType) {
switch(type) { 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) {
System.out.println("***" + message);
}
/**
* Convenience function for managing all error types.
*
* @param type
* @param a1
* @param a2
*/
public static void report(ErrorType type, AST a1, AST a2) {
switch (type) {
// VarDeclStmt is only statement in conditional branch // Cannot access 'this' in a static method
case VAR_COND_ONLY: { case THIS: {
System.out.println("***Conditional statment cannot be followed by a variable declaration statement " + ast.posn); MethodDecl md = (MethodDecl) a2;
emit("Cannot reference 'this' " + a1.posn + " in static method '" + md.name + "' " + md.posn);
break; break;
} }
// Declaration does not exist for reference // Attempting to call a non function as a function
case MISSING_DECL: { case NONFUNCTION_CALL: {
System.out.println("***Reference to a non-existant type " + ast.posn); emit("Not a valid function call at " + a1.posn);
break; break;
} }
// Reports when a reference could not be found // Tried accessing a non-static member from a static method
case UNIDENTIFIED: { case STATIC: {
System.out.println("***Reference refers to a declaration that does not exist " + ast.posn); 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; 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 // Attempting to redeclare a variable
case REDEFINITION: { case REDEFINITION: {
System.out.println("***Variable has already been defined earlier " + ast.posn); emit("Variable at " + a1.posn + " already declared earlier at " + a2.posn);
break; break;
} }
// A non void function does not have a return statement // Identifier could not be found
case NO_RETURN_EXPRESSION: { case UNDEFINED: {
System.out.println("***Non-void method does not have a return statement " + ast.posn); Identifier ident = (Identifier) a1;
emit("Identifier '" + ident.spelling + "' " + ident.posn + " is undeclared.");
break; break;
} }
// The number of parameters passed is either too few or too great
case INVALID_PARAM_COUNT: {
System.out.println("***The number of passed parameters does not equal expected count " + ast.posn);
}
// The expected expression MUST return an int (such as the index of an array)
case INVALID_INDEX: {
System.out.println("***Expected an integer value as the index of an array " + ast.posn);
break;
}
// Hmmm.....
case UNIDENTIFIED_TYPE: {
System.out.println("***Unexpected type " + ast.posn);
break;
}
// Clear Warning
default:
break;
}
}
/** // A public static void main(String[] args) method was not declared
* Type specific error reporting. case MAIN_UNDECLARED: {
* @param type emit("A main function was not declared");
* @param t1
* @param t2
*/
public static void report(ErrorType type, Type t1, Type t2) {
error = true;
switch(type) {
// Non class/array types don't match
case TYPE_MISMATCH: {
System.out.println("***Expected type " + t1.typeKind + " but got " + t2.typeKind + t2.posn);
break; break;
} }
// Two classes don't match // Parameter counts of an expression/statement do not match declaration
case TYPE_CLASS_MISMATCH: { case INVALID_PARAM_COUNT: {
ClassType c1 = (ClassType) t1; MethodDecl md = (MethodDecl) a2;
ClassType c2 = (ClassType) t2; emit("Call to '" + md.name + "' " + a2.posn + " has an invalid parameter count at " + a1.posn);
System.out.println("***Expected type " + c1.className.spelling + " but got " + c2.className.spelling + c2.posn);
break; break;
} }
// Two arrays don't match // A public static void main(String[] args) was declared more than once
case TYPE_ARRAY_MISMATCH: { case MULTIPLE_MAIN: {
ArrayType a1 = (ArrayType) t1; emit("Main function at " + a1.posn + " already declared previously at " + a2.posn);
ArrayType a2 = (ArrayType) t2;
System.out.println("***Expected array type " + a1.eltType.typeKind + " but got " + a2.eltType.typeKind + t2.posn);
break; break;
} }
// Clear Warning // A reference has been made to a non-existant type
default: 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; 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;
}
} }
error = true;
} }
} }

View File

@ -5,13 +5,13 @@ import miniJava.SyntacticAnalyzer.Token;
public class ParsingException extends Exception { public class ParsingException extends Exception {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public ParsingException() { public ParsingException() {
super("Unidentified parsing error!"); super("Unidentified parsing error!");
} }
public ParsingException(Token t) { public ParsingException(Token t) {
super("Parsing error with " + t.toString()); super("Parsing error with " + t.spelling + " at " + t.posn.toString());
} }
} }

View File

@ -1,11 +1,11 @@
package miniJava.Exceptions; package miniJava.Exceptions;
public class ScanningException extends Exception { public class ScanningException extends Exception {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public ScanningException(int col, int line) { public ScanningException(int col, int line) {
super("Scanning error at Column: " + col + ", Line: " + line); super("Scanning error at Column: " + col + ", Line: " + line);
} }
} }

View File

@ -7,320 +7,326 @@ import miniJava.AbstractSyntaxTrees.Package;
import miniJava.Exceptions.*; import miniJava.Exceptions.*;
public class Parser { public class Parser {
private Scanner scanner; private Scanner scanner;
private LinkedList<Token> stream; private LinkedList<Token> stream;
public Parser(Scanner scanner) { public Parser(Scanner scanner) {
this.scanner = scanner; this.scanner = scanner;
this.stream = new LinkedList<Token>(); this.stream = new LinkedList<Token>();
} }
/** /**
* Program ::= (ClassDeclaration)* eot * Program ::= (ClassDeclaration)* eot
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
public Package parse() throws ParsingException, ScanningException { public Package parse() throws ParsingException, ScanningException {
ClassDeclList decls = new ClassDeclList(); ClassDeclList decls = new ClassDeclList();
while(peek(1).type == Token.TYPE.CLASS) { while (peek(1).type == Token.TYPE.CLASS) {
decls.add(parseClassDeclaration()); decls.add(parseClassDeclaration());
} }
accept(Token.TYPE.EOT); accept(Token.TYPE.EOT);
return new Package(decls, new SourcePosition(0, 0)); return new Package(decls, new SourcePosition(0, 0));
} }
/** /**
* ClassDeclaration ::= * ClassDeclaration ::= class id { (Declarators id (; | MethodDeclaration))* }
* class id {
* (Declarators id (; | MethodDeclaration))*
* }
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private ClassDecl parseClassDeclaration() throws ParsingException, ScanningException { private ClassDecl parseClassDeclaration() throws ParsingException,
ScanningException {
// Class Header // Class Header
Token classToken = accept(Token.TYPE.CLASS); Token classToken = accept(Token.TYPE.CLASS);
String cn = accept(Token.TYPE.ID).spelling; String cn = accept(Token.TYPE.ID).spelling;
accept(Token.TYPE.LBRACKET); accept(Token.TYPE.LBRACKET);
// Setup // Setup
FieldDeclList fdl = new FieldDeclList(); FieldDeclList fdl = new FieldDeclList();
MethodDeclList mdl = new MethodDeclList(); MethodDeclList mdl = new MethodDeclList();
// Class Body // Class Body
while(peek(1).type != Token.TYPE.RBRACKET) { while (peek(1).type != Token.TYPE.RBRACKET) {
Declarators d = parseDeclarators(); Declarators d = parseDeclarators();
String name = accept(Token.TYPE.ID).spelling; String name = accept(Token.TYPE.ID).spelling;
FieldDecl f = new FieldDecl(d.isPrivate, d.isStatic, d.mt, name, d.posn); FieldDecl f = new FieldDecl(d.isPrivate, d.isStatic, d.mt, name,
d.posn);
// Field Declarations // Field Declarations
if(peek(1).type == Token.TYPE.SEMICOLON) { if (peek(1).type == Token.TYPE.SEMICOLON) {
accept(Token.TYPE.SEMICOLON); accept(Token.TYPE.SEMICOLON);
fdl.add(f); fdl.add(f);
} }
// Method Declarations // Method Declarations
else mdl.add(parseMethodDeclaration(f)); else
mdl.add(parseMethodDeclaration(f));
} }
accept(Token.TYPE.RBRACKET); accept(Token.TYPE.RBRACKET);
return new ClassDecl(cn, fdl, mdl, classToken.posn); return new ClassDecl(cn, fdl, mdl, classToken.posn);
} }
/** /**
* Declarators ::= (public | private)? static? Type * Declarators ::= (public | private)? static? Type
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Declarators parseDeclarators() throws ParsingException, ScanningException { private Declarators parseDeclarators() throws ParsingException,
ScanningException {
// Visibility // Visibility
SourcePosition start = null; SourcePosition start = null;
boolean isPrivate = false; boolean isPrivate = false;
if(peek(1).type == Token.TYPE.PUBLIC) { if (peek(1).type == Token.TYPE.PUBLIC) {
start = accept(Token.TYPE.PUBLIC).posn; start = accept(Token.TYPE.PUBLIC).posn;
} else if(peek(1).type == Token.TYPE.PRIVATE) { } else if (peek(1).type == Token.TYPE.PRIVATE) {
isPrivate = true; isPrivate = true;
start = accept(Token.TYPE.PRIVATE).posn; start = accept(Token.TYPE.PRIVATE).posn;
} }
// Class Methods // Class Methods
boolean isStatic = false; boolean isStatic = false;
if(peek(1).type == Token.TYPE.STATIC) { if (peek(1).type == Token.TYPE.STATIC) {
isStatic = true; isStatic = true;
if(start == null) { if (start == null) {
start = accept(Token.TYPE.STATIC).posn; start = accept(Token.TYPE.STATIC).posn;
} else { } else {
accept(Token.TYPE.STATIC); accept(Token.TYPE.STATIC);
} }
} }
Type t = parseType(); Type t = parseType();
if(start == null) { if (start == null) {
start = t.posn; start = t.posn;
} }
return new Declarators(isPrivate, isStatic, t, start); return new Declarators(isPrivate, isStatic, t, start);
} }
/** /**
* * MethodDeclaration ::= * MethodDeclaration ::= (ParameterList?) { Statement* (return Expression;)? }
* (ParameterList?) { * @param f
* Statement* (return Expression ;)?
* }
* @param f describes the declaratory aspect of the method
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private MethodDecl parseMethodDeclaration(FieldDecl f) throws ParsingException, ScanningException { private MethodDecl parseMethodDeclaration(FieldDecl f)
throws ParsingException, ScanningException {
// Method Header // Method Header
accept(Token.TYPE.LPAREN); accept(Token.TYPE.LPAREN);
// Parameter List // Parameter List
ParameterDeclList pdl = new ParameterDeclList(); ParameterDeclList pdl = new ParameterDeclList();
if(peek(1).type != Token.TYPE.RPAREN) pdl = parseParameterList(); if (peek(1).type != Token.TYPE.RPAREN)
pdl = parseParameterList();
accept(Token.TYPE.RPAREN); accept(Token.TYPE.RPAREN);
accept(Token.TYPE.LBRACKET); accept(Token.TYPE.LBRACKET);
// Method Body // Method Body
Expression re = null; Expression re = null;
StatementList stl = new StatementList(); StatementList stl = new StatementList();
while(peek(1).type != Token.TYPE.RBRACKET) { while (peek(1).type != Token.TYPE.RBRACKET) {
if(peek(1).type == Token.TYPE.RETURN) { if (peek(1).type == Token.TYPE.RETURN) {
accept(Token.TYPE.RETURN); accept(Token.TYPE.RETURN);
re = parseExpression(); re = parseExpression();
accept(Token.TYPE.SEMICOLON); accept(Token.TYPE.SEMICOLON);
break; break;
} }
stl.add(parseStatement()); stl.add(parseStatement());
} }
accept(Token.TYPE.RBRACKET); accept(Token.TYPE.RBRACKET);
return new MethodDecl(f, pdl, stl, re, f.posn); return new MethodDecl(f, pdl, stl, re, f.posn);
} }
/** /**
* Type ::= boolean | void | int ([])? | id ([])? * Type ::= boolean | void | int ([])? | id ([])?
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Type parseType() throws ParsingException, ScanningException { private Type parseType() throws ParsingException, ScanningException {
SourcePosition posn = null; SourcePosition posn = null;
switch(peek(1).type) { switch (peek(1).type) {
case BOOLEAN: case BOOLEAN:
posn = accept(Token.TYPE.BOOLEAN).posn; posn = accept(Token.TYPE.BOOLEAN).posn;
return new BaseType(TypeKind.BOOLEAN, posn); return new BaseType(TypeKind.BOOLEAN, posn);
case VOID: case VOID:
posn = accept(Token.TYPE.VOID).posn; posn = accept(Token.TYPE.VOID).posn;
return new BaseType(TypeKind.VOID, posn); return new BaseType(TypeKind.VOID, posn);
case INT: { case INT: {
posn = accept(Token.TYPE.INT).posn; posn = accept(Token.TYPE.INT).posn;
BaseType b = new BaseType(TypeKind.INT, posn); BaseType b = new BaseType(TypeKind.INT, posn);
if(peek(1).type == Token.TYPE.LSQUARE) { if (peek(1).type == Token.TYPE.LSQUARE) {
accept(Token.TYPE.LSQUARE); accept(Token.TYPE.LSQUARE);
accept(Token.TYPE.RSQUARE); accept(Token.TYPE.RSQUARE);
return new ArrayType(b, posn); return new ArrayType(b, posn);
}
return b;
} }
case ID: { return b;
Token id = accept(peek(1).type); }
Identifier i = new Identifier(id.spelling, id.posn);
ClassType c = new ClassType(i, id.posn); case ID: {
Token id = accept(peek(1).type);
if(peek(1).type == Token.TYPE.LSQUARE) { Identifier i = new Identifier(id.spelling, id.posn);
accept(Token.TYPE.LSQUARE); ClassType c = new ClassType(i, id.posn);
accept(Token.TYPE.RSQUARE);
return new ArrayType(c, id.posn); if (peek(1).type == Token.TYPE.LSQUARE) {
} accept(Token.TYPE.LSQUARE);
accept(Token.TYPE.RSQUARE);
return c; return new ArrayType(c, id.posn);
} }
default: return c;
throw new ParsingException(); }
default:
throw new ParsingException();
} }
} }
/** /**
* ParameterList ::= Type id (, Type id)* * ParameterList ::= Type id (, Type id)*
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private ParameterDeclList parseParameterList() throws ParsingException, ScanningException { private ParameterDeclList parseParameterList() throws ParsingException, ScanningException {
ParameterDeclList decls = new ParameterDeclList(); ParameterDeclList decls = new ParameterDeclList();
// First Parameter // First Parameter
Type t = parseType(); Type t = parseType();
Token id = accept(Token.TYPE.ID); Token id = accept(Token.TYPE.ID);
decls.add(new ParameterDecl(t, id.spelling, id.posn)); decls.add(new ParameterDecl(t, id.spelling, id.posn));
// Remainder of List // Remainder of List
while(peek(1).type == Token.TYPE.COMMA) { while (peek(1).type == Token.TYPE.COMMA) {
accept(Token.TYPE.COMMA); accept(Token.TYPE.COMMA);
Type nextType = parseType(); Type nextType = parseType();
Token nextId = accept(Token.TYPE.ID); Token nextId = accept(Token.TYPE.ID);
decls.add(new ParameterDecl(nextType, nextId.spelling, nextId.posn)); decls.add(new ParameterDecl(nextType, nextId.spelling, nextId.posn));
} }
return decls; return decls;
} }
/** /**
* ArgumentList ::= Expression (, Expression)* * ArgumentList ::= Expression (, Expression)*
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private ExprList parseArgumentList() throws ParsingException, ScanningException { private ExprList parseArgumentList() throws ParsingException, ScanningException {
ExprList e = new ExprList(); ExprList e = new ExprList();
e.add(parseExpression()); e.add(parseExpression());
while(peek(1).type == Token.TYPE.COMMA) { while (peek(1).type == Token.TYPE.COMMA) {
accept(Token.TYPE.COMMA); accept(Token.TYPE.COMMA);
e.add(parseExpression()); e.add(parseExpression());
} }
return e; return e;
} }
/** /**
* Reference ::= BaseRef (. BaseRef)* * Reference ::= BaseRef (. BaseRef)*
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Reference parseReference() throws ParsingException, ScanningException { private Reference parseReference() throws ParsingException, ScanningException {
Reference r = parseBaseRef(); Reference r = parseBaseRef();
while(peek(1).type == Token.TYPE.PERIOD) { while (peek(1).type == Token.TYPE.PERIOD) {
accept(Token.TYPE.PERIOD); accept(Token.TYPE.PERIOD);
Token tokenId = accept(Token.TYPE.ID); Token tokenId = accept(Token.TYPE.ID);
Identifier id = new Identifier(tokenId.spelling, tokenId.posn); Identifier id = new Identifier(tokenId.spelling, tokenId.posn);
r = new QualifiedRef(r, id, tokenId.posn); r = new QualifiedRef(r, id, tokenId.posn);
if(peek(1).type == Token.TYPE.LSQUARE) { if (peek(1).type == Token.TYPE.LSQUARE) {
accept(Token.TYPE.LSQUARE); accept(Token.TYPE.LSQUARE);
Expression e = parseExpression(); Expression e = parseExpression();
accept(Token.TYPE.RSQUARE); accept(Token.TYPE.RSQUARE);
r = new IndexedRef(r, e, tokenId.posn); r = new IndexedRef(r, e, tokenId.posn);
} }
} }
return r; return r;
} }
/** /**
* BaseRef ::= this | id ([ Expression])? * BaseRef ::= this | id ([ Expression])?
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Reference parseBaseRef() throws ParsingException, ScanningException { private Reference parseBaseRef() throws ParsingException, ScanningException {
switch(peek(1).type) { switch (peek(1).type) {
case THIS: { case THIS: {
Token thisToken = accept(Token.TYPE.THIS); Token thisToken = accept(Token.TYPE.THIS);
return new ThisRef(thisToken.posn); return new ThisRef(thisToken.posn);
} }
// id ([ Expression])? // id ([ Expression])?
default: { default: {
Token id = accept(Token.TYPE.ID); Token id = accept(Token.TYPE.ID);
Identifier i = new Identifier(id.spelling, id.posn); Identifier i = new Identifier(id.spelling, id.posn);
IdRef r = new IdRef(i, id.posn); IdRef r = new IdRef(i, id.posn);
if(peek(1).type == Token.TYPE.LSQUARE) { if (peek(1).type == Token.TYPE.LSQUARE) {
accept(Token.TYPE.LSQUARE); accept(Token.TYPE.LSQUARE);
Expression e = parseExpression(); Expression e = parseExpression();
accept(Token.TYPE.RSQUARE); accept(Token.TYPE.RSQUARE);
return new IndexedRef(r, e, id.posn); return new IndexedRef(r, e, id.posn);
} }
return r; return r;
} }
} }
} }
/** /**
* Statement ::= * Statement ::= {Statement*} | Type id = Expression; | Reference =
* {Statement*} * Expression; | Reference ( ArgumentList? ); | if (Expression) Statement
* | Type id = Expression; * (else Statement)? | while (Expression) Statement
* | Reference = Expression;
* | Reference ( ArgumentList? );
* | if (Expression) Statement (else Statement)?
* | while (Expression) Statement
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Statement parseStatement() throws ParsingException, ScanningException { private Statement parseStatement() throws ParsingException, ScanningException {
switch(peek(1).type) { switch (peek(1).type) {
// { Statement* } // { Statement* }
case LBRACKET: { case LBRACKET: {
Token leftToken = accept(Token.TYPE.LBRACKET); Token leftToken = accept(Token.TYPE.LBRACKET);
StatementList stl = new StatementList(); StatementList stl = new StatementList();
while(peek(1).type != Token.TYPE.RBRACKET) { while (peek(1).type != Token.TYPE.RBRACKET) {
stl.add(parseStatement()); stl.add(parseStatement());
} }
accept(Token.TYPE.RBRACKET); accept(Token.TYPE.RBRACKET);
return new BlockStmt(stl, leftToken.posn); return new BlockStmt(stl, leftToken.posn);
} }
// if (Expression) Statement (else Statement)? // if (Expression) Statement (else Statement)?
case IF: { case IF: {
Token ifToken = accept(Token.TYPE.IF); Token ifToken = accept(Token.TYPE.IF);
@ -328,15 +334,15 @@ public class Parser {
Expression e = parseExpression(); Expression e = parseExpression();
accept(Token.TYPE.RPAREN); accept(Token.TYPE.RPAREN);
Statement s1 = parseStatement(); Statement s1 = parseStatement();
if(peek(1).type == Token.TYPE.ELSE) { if (peek(1).type == Token.TYPE.ELSE) {
accept(Token.TYPE.ELSE); accept(Token.TYPE.ELSE);
Statement s2 = parseStatement(); Statement s2 = parseStatement();
return new IfStmt(e, s1, s2, ifToken.posn); return new IfStmt(e, s1, s2, ifToken.posn);
} }
return new IfStmt(e, s1, ifToken.posn); return new IfStmt(e, s1, ifToken.posn);
} }
// while (Expression) Statement // while (Expression) Statement
case WHILE: { case WHILE: {
Token whileToken = accept(Token.TYPE.WHILE); Token whileToken = accept(Token.TYPE.WHILE);
@ -344,74 +350,75 @@ public class Parser {
Expression e = parseExpression(); Expression e = parseExpression();
accept(Token.TYPE.RPAREN); accept(Token.TYPE.RPAREN);
Statement s = parseStatement(); Statement s = parseStatement();
return new WhileStmt(e, s, whileToken.posn); return new WhileStmt(e, s, whileToken.posn);
} }
// Type id = Expression ; // Type id = Expression ;
case BOOLEAN: case VOID: case INT: case ID: { case BOOLEAN:
case VOID:
case INT:
case ID: {
// Must be a type though there is a possibility of a reference // 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 if (peek(1).type != Token.TYPE.ID
||(peek(2).type == Token.TYPE.LSQUARE && peek(3).type == Token.TYPE.RSQUARE)) { || peek(2).type == Token.TYPE.ID
|| (peek(2).type == Token.TYPE.LSQUARE && peek(3).type == Token.TYPE.RSQUARE)) {
Type t = parseType(); Type t = parseType();
String name = accept(Token.TYPE.ID).spelling; String name = accept(Token.TYPE.ID).spelling;
VarDecl v = new VarDecl(t, name, t.posn); VarDecl v = new VarDecl(t, name, t.posn);
accept(Token.TYPE.EQUALS); accept(Token.TYPE.EQUALS);
Expression e = parseExpression(); Expression e = parseExpression();
accept(Token.TYPE.SEMICOLON); accept(Token.TYPE.SEMICOLON);
return new VarDeclStmt(v, e, t.posn); return new VarDeclStmt(v, e, t.posn);
} }
/* Fall Through */ /* Fall Through */
} }
default: { default: {
Statement s = null; Statement s = null;
Reference r = parseReference(); Reference r = parseReference();
// Reference ( ArgumentList? ) ; // Reference ( ArgumentList? ) ;
if(peek(1).type == Token.TYPE.LPAREN) { if (peek(1).type == Token.TYPE.LPAREN) {
ExprList e = new ExprList(); ExprList e = new ExprList();
accept(Token.TYPE.LPAREN); accept(Token.TYPE.LPAREN);
if(peek(1).type != Token.TYPE.RPAREN) { if (peek(1).type != Token.TYPE.RPAREN) {
e = parseArgumentList(); e = parseArgumentList();
} }
accept(Token.TYPE.RPAREN); accept(Token.TYPE.RPAREN);
s = new CallStmt(r, e, r.posn); s = new CallStmt(r, e, r.posn);
} }
// Reference = Expression ; // Reference = Expression ;
else { else {
accept(Token.TYPE.EQUALS); accept(Token.TYPE.EQUALS);
Expression e = parseExpression(); Expression e = parseExpression();
s = new AssignStmt(r, e, r.posn); s = new AssignStmt(r, e, r.posn);
} }
accept(Token.TYPE.SEMICOLON); accept(Token.TYPE.SEMICOLON);
return s; return s;
} }
} }
} }
/** /**
* Expression ::= * Expression ::= Reference | Reference ( ArgumentList? ) | unop Expression
* Reference * | ( Expression ) | num | true | false | new (id() | int [ Expression ] |
* | Reference ( ArgumentList? ) * id [ Expression ] )
* | unop Expression *
* | ( Expression )
* | num | true | false
* | new (id() | int [ Expression ] | id [ Expression ] )
* @return * @return
* @throws ScanningException * @throws ScanningException
*/ */
private Expression parseSingleExpression() throws ParsingException, ScanningException { private Expression parseSingleExpression() throws ParsingException, ScanningException {
Expression e = null; Expression e = null;
switch(peek(1).type) { switch (peek(1).type) {
// num // num
case NUM: { case NUM: {
Token number = accept(Token.TYPE.NUM); Token number = accept(Token.TYPE.NUM);
@ -419,7 +426,7 @@ public class Parser {
e = new LiteralExpr(i, number.posn); e = new LiteralExpr(i, number.posn);
break; break;
} }
// true | false // true | false
case TRUE: case TRUE:
case FALSE: { case FALSE: {
@ -428,7 +435,7 @@ public class Parser {
e = new LiteralExpr(b, bool.posn); e = new LiteralExpr(b, bool.posn);
break; break;
} }
// ( Expression ) // ( Expression )
case LPAREN: { case LPAREN: {
accept(Token.TYPE.LPAREN); accept(Token.TYPE.LPAREN);
@ -436,39 +443,39 @@ public class Parser {
accept(Token.TYPE.RPAREN); accept(Token.TYPE.RPAREN);
break; break;
} }
// unop Expression // unop Expression
case UNOP: case UNOP:
case BINOP: { case BINOP: {
if(peek(1).spelling.equals("!") || peek(1).spelling.equals("-")) { if (peek(1).spelling.equals("!") || peek(1).spelling.equals("-")) {
Token opToken = accept(peek(1).type); Token opToken = accept(peek(1).type);
Operator o = new Operator(opToken, opToken.posn); Operator o = new Operator(opToken, opToken.posn);
e = new UnaryExpr(o, parseSingleExpression(), opToken.posn); e = new UnaryExpr(o, parseSingleExpression(), opToken.posn);
} } else
else throw new ParsingException(); throw new ParsingException();
break; break;
} }
// new ( int [ Expression ] | id ( ) | id [ Expression ] ) // new ( int [ Expression ] | id ( ) | id [ Expression ] )
case NEW: { case NEW: {
Token newToken = accept(Token.TYPE.NEW); Token newToken = accept(Token.TYPE.NEW);
if(peek(1).type == Token.TYPE.INT) { if (peek(1).type == Token.TYPE.INT) {
accept(Token.TYPE.INT); accept(Token.TYPE.INT);
accept(Token.TYPE.LSQUARE); accept(Token.TYPE.LSQUARE);
Expression e2 = parseExpression(); Expression e2 = parseExpression();
accept(Token.TYPE.RSQUARE); accept(Token.TYPE.RSQUARE);
BaseType b = new BaseType(TypeKind.INT, newToken.posn); BaseType b = new BaseType(TypeKind.INT, newToken.posn);
e = new NewArrayExpr(b, e2, newToken.posn); e = new NewArrayExpr(b, e2, newToken.posn);
} }
else { else {
Token id = accept(Token.TYPE.ID); Token id = accept(Token.TYPE.ID);
Identifier i = new Identifier(id.spelling, id.posn); Identifier i = new Identifier(id.spelling, id.posn);
ClassType c = new ClassType(i, id.posn); ClassType c = new ClassType(i, id.posn);
if(peek(1).type == Token.TYPE.LPAREN){ if (peek(1).type == Token.TYPE.LPAREN) {
accept(Token.TYPE.LPAREN); accept(Token.TYPE.LPAREN);
accept(Token.TYPE.RPAREN); accept(Token.TYPE.RPAREN);
e = new NewObjectExpr(c, id.posn); e = new NewObjectExpr(c, id.posn);
@ -479,17 +486,18 @@ public class Parser {
e = new NewArrayExpr(c, e2, id.posn); e = new NewArrayExpr(c, e2, id.posn);
} }
} }
break; break;
} }
// Reference ((ArgumentList?))? // Reference ((ArgumentList?))?
case THIS: case ID: { case THIS:
case ID: {
Reference r = parseReference(); Reference r = parseReference();
if(peek(1).type == Token.TYPE.LPAREN) { if (peek(1).type == Token.TYPE.LPAREN) {
accept(Token.TYPE.LPAREN); accept(Token.TYPE.LPAREN);
ExprList el = new ExprList(); ExprList el = new ExprList();
if(peek(1).type != Token.TYPE.RPAREN) { if (peek(1).type != Token.TYPE.RPAREN) {
el = parseArgumentList(); el = parseArgumentList();
} }
accept(Token.TYPE.RPAREN); accept(Token.TYPE.RPAREN);
@ -497,147 +505,156 @@ public class Parser {
} else { } else {
e = new RefExpr(r, r.posn); e = new RefExpr(r, r.posn);
} }
break; break;
} }
default: default:
throw new ParsingException(); throw new ParsingException(peek(1));
} }
return e; return e;
} }
/** /**
* Disjunction & Initial Call: * Disjunction & Initial Call: Expression ::= Expression binop Expression
* Expression ::= Expression binop Expression
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Expression parseExpression() throws ParsingException, ScanningException { private Expression parseExpression() throws ParsingException, ScanningException {
Expression e = parseCExpression(); Expression e = parseCExpression();
while(peek(1).spelling.equals("||")) { while (peek(1).spelling.equals("||")) {
Token opToken = accept(Token.TYPE.BINOP); Token opToken = accept(Token.TYPE.BINOP);
Operator o = new Operator(opToken, opToken.posn); Operator o = new Operator(opToken, opToken.posn);
e = new BinaryExpr(o, e, parseCExpression(), e.posn); e = new BinaryExpr(o, e, parseCExpression(), e.posn);
} }
return e; return e;
} }
/** /**
* Conjunction * Conjunction
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Expression parseCExpression() throws ParsingException, ScanningException { private Expression parseCExpression() throws ParsingException, ScanningException {
Expression e = parseEExpression(); Expression e = parseEExpression();
while(peek(1).spelling.equals("&&")) { while (peek(1).spelling.equals("&&")) {
Token opToken = accept(Token.TYPE.BINOP); Token opToken = accept(Token.TYPE.BINOP);
Operator o = new Operator(opToken, opToken.posn); Operator o = new Operator(opToken, opToken.posn);
e = new BinaryExpr(o, e, parseEExpression(), e.posn); e = new BinaryExpr(o, e, parseEExpression(), e.posn);
} }
return e; return e;
} }
/** /**
* Equality * Equality
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Expression parseEExpression() throws ParsingException, ScanningException { private Expression parseEExpression() throws ParsingException, ScanningException {
Expression e = parseRExpression(); Expression e = parseRExpression();
while(peek(1).spelling.equals("==") || peek(1).spelling.equals("!=")) { while (peek(1).spelling.equals("==") || peek(1).spelling.equals("!=")) {
Token opToken = accept(Token.TYPE.BINOP); Token opToken = accept(Token.TYPE.BINOP);
Operator o = new Operator(opToken, opToken.posn); Operator o = new Operator(opToken, opToken.posn);
e = new BinaryExpr(o, e, parseRExpression(), e.posn); e = new BinaryExpr(o, e, parseRExpression(), e.posn);
} }
return e; return e;
} }
/** /**
* Relational * Relational
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Expression parseRExpression() throws ParsingException, ScanningException { private Expression parseRExpression() throws ParsingException, ScanningException {
Expression e = parseAExpression(); Expression e = parseAExpression();
while(peek(1).spelling.equals("<") || peek(1).spelling.equals("<=") while (peek(1).spelling.equals("<") || peek(1).spelling.equals("<=")
|| peek(1).spelling.equals(">") || peek(1).spelling.equals(">=")) { || peek(1).spelling.equals(">")
|| peek(1).spelling.equals(">=")) {
Token opToken = accept(Token.TYPE.BINOP); Token opToken = accept(Token.TYPE.BINOP);
Operator o = new Operator(opToken, opToken.posn); Operator o = new Operator(opToken, opToken.posn);
e = new BinaryExpr(o, e, parseAExpression(), e.posn); e = new BinaryExpr(o, e, parseAExpression(), e.posn);
} }
return e; return e;
} }
/** /**
* Additive * Additive
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Expression parseAExpression() throws ParsingException, ScanningException { private Expression parseAExpression() throws ParsingException, ScanningException {
Expression e = parseMExpression(); Expression e = parseMExpression();
while(peek(1).spelling.equals("+") || peek(1).spelling.equals("-")) { while (peek(1).spelling.equals("+") || peek(1).spelling.equals("-")) {
Token opToken = accept(Token.TYPE.BINOP); Token opToken = accept(Token.TYPE.BINOP);
Operator o = new Operator(opToken, opToken.posn); Operator o = new Operator(opToken, opToken.posn);
e = new BinaryExpr(o, e, parseMExpression(), e.posn); e = new BinaryExpr(o, e, parseMExpression(), e.posn);
} }
return e; return e;
} }
/** /**
* Multiplicative * Multiplicative
* @return * @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Expression parseMExpression() throws ParsingException, ScanningException { private Expression parseMExpression() throws ParsingException, ScanningException {
Expression e = parseSingleExpression(); Expression e = parseSingleExpression();
while(peek(1).spelling.equals("*") || peek(1).spelling.equals("/")) { while (peek(1).spelling.equals("*") || peek(1).spelling.equals("/")) {
Token opToken = accept(Token.TYPE.BINOP); Token opToken = accept(Token.TYPE.BINOP);
Operator o = new Operator(opToken, opToken.posn); Operator o = new Operator(opToken, opToken.posn);
e = new BinaryExpr(o, e, parseSingleExpression(), e.posn); e = new BinaryExpr(o, e, parseSingleExpression(), e.posn);
} }
return e; return e;
} }
/** /**
* Sees what the next token is, caching the result. * Sees what the next token is, caching the result.
* @param lookahead
* @return * @return
* @throws ScanningException * @throws ScanningException
*/ */
private Token peek(int lookahead) throws ScanningException { private Token peek(int lookahead) throws ScanningException {
// Cache tokens // Cache tokens
while(stream.size() < lookahead) { while (stream.size() < lookahead) {
Token next = scanner.scan(); Token next = scanner.scan();
stream.addLast(next); stream.addLast(next);
} }
return stream.get(lookahead - 1); return stream.get(lookahead - 1);
} }
/** /**
* Consumes token or throws exception. * Consumes token or throws exception.
* @param type
* @return
* @throws ParsingException
* @throws ScanningException * @throws ScanningException
*/ */
private Token accept(Token.TYPE type) throws ParsingException, ScanningException { private Token accept(Token.TYPE type) throws ParsingException, ScanningException {
Token next = peek(1); Token next = peek(1);
if(next.type == type) stream.poll(); if(next.type == type) stream.poll();
else throw new ParsingException(next); else throw new ParsingException(next);
return next; return next;
} }
} }

View File

@ -4,293 +4,310 @@ import java.io.*;
import miniJava.Exceptions.*; import miniJava.Exceptions.*;
public class Scanner { public class Scanner {
private int col = 1; private int col = 1;
private int line = 1; private int line = 1;
private BufferedReader input; private BufferedReader input;
public Scanner(BufferedReader input) {
this.input = input;
}
public Scanner(String input) {
StringReader reader = new StringReader(input);
this.input = new BufferedReader(reader);
}
/**
* Scans in input, returning next token.
* @return
* @throws IOException
*/
public Token scan() throws ScanningException {
String attr = ""; public Scanner(BufferedReader input) {
Token token = null; this.input = input;
}
while(token == null) {
// Check for EOF
int c = read();
if(c == -1) return new Token("", Token.TYPE.EOT);
// 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();
}
if(Token.keywords.containsKey(attr)) {
token = new Token(attr, Token.keywords.get(attr));
} else {
token = new Token(attr, Token.TYPE.ID);
}
}
// 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()); public Scanner(String input) {
return token; StringReader reader = new StringReader(input);
} this.input = new BufferedReader(reader);
}
/**
* 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); * Scans in input, returning next token.
else current = (char) next; *
} * @return
} * @throws IOException
*/
public Token scan() throws ScanningException {
/**
* Consumes input until the end of line is reached String attr = "";
* @throws IOException Token token = null;
*/
private void readLine() throws ScanningException { while (token == null) {
for(int n = 0; n != '\n' && n != '\r' && n != -1; n = read()) {}
} // Check for EOF
int c = read();
if (c == -1)
/** return new Token("", Token.TYPE.EOT);
* Tells whether character is alphabetical.
* @param c // Setup
* @return attr += (char) c;
*/
private boolean isAlpha(char c) { switch (c) {
return (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z') // Operators
|| c == '_'; case '*':
} token = new Token(attr, Token.TYPE.BINOP);
break;
/** case '+':
* Tells whether character is numerical. if (peek('+'))
* @param c throw new ScanningException(col, line);
* @return token = new Token(attr, Token.TYPE.BINOP);
*/ break;
private boolean isDigit(char c) {
return c >= '0' && c <= '9'; case '-':
} if (peek('-'))
throw new ScanningException(col, line);
token = new Token(attr, Token.TYPE.BINOP);
/** break;
* Tells wheter character is whitespace.
* @param c // Check for comment
* @return case '/':
*/ if (peek('*')) {
private boolean isWhitespace(char c) { read();
return c == ' ' readComment();
|| c == '\n' attr = "";
|| c == '\r' } else if (peek('/')) {
|| c == '\t'; 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();
}
if (Token.keywords.containsKey(attr)) {
token = new Token(attr, Token.keywords.get(attr));
} else {
token = new Token(attr, Token.TYPE.ID);
}
}
// 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;
}
/**
* 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 == '_';
}
/**
* Tells whether character is numerical.
*
* @param c
* @return
*/
private boolean isDigit(char c) {
return c >= '0' && c <= '9';
}
/**
* Tells wheter character is whitespace.
*
* @param c
* @return
*/
private boolean isWhitespace(char c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t';
}
} }

View File

@ -4,12 +4,12 @@ public class SourcePosition {
public final int col; public final int col;
public final int line; public final int line;
public SourcePosition(int line, int col) { public SourcePosition(int line, int col) {
this.col = col; this.col = col;
this.line = line; this.line = line;
} }
@Override @Override
public String toString() { public String toString() {
return "(Line: " + line + ", Column: " + col + ")"; return "(Line: " + line + ", Column: " + col + ")";

View File

@ -3,75 +3,49 @@ package miniJava.SyntacticAnalyzer;
import java.util.HashMap; import java.util.HashMap;
public class Token { public class Token {
public enum TYPE { public enum TYPE {
// Possible Terminals // Possible Terminals
ID, ID, NUM, UNOP, BINOP,
NUM,
UNOP,
BINOP,
// Keywords // Keywords
IF, IF, ELSE, NEW, INT, VOID, THIS, TRUE, FALSE, CLASS, WHILE, RETURN, BOOLEAN,
ELSE,
NEW,
INT,
VOID,
THIS,
TRUE,
FALSE,
CLASS,
WHILE,
RETURN,
BOOLEAN,
// Declarators // Declarators
STATIC, STATIC, PUBLIC, PRIVATE,
PUBLIC,
PRIVATE,
// Other Terminals // Other Terminals
EQUALS, EQUALS, PERIOD, COMMA, LPAREN, RPAREN, LSQUARE, RSQUARE, LBRACKET, RBRACKET, SEMICOLON,
PERIOD,
COMMA,
LPAREN,
RPAREN,
LSQUARE,
RSQUARE,
LBRACKET,
RBRACKET,
SEMICOLON,
// End of Token Stream // End of Token Stream
EOT EOT
}; };
public final static HashMap<String, TYPE> keywords; public final static HashMap<String, TYPE> keywords;
static static {
{ keywords = new HashMap<String, TYPE>();
keywords = new HashMap<String, TYPE>(); keywords.put("class", TYPE.CLASS);
keywords.put("class", TYPE.CLASS); keywords.put("return", TYPE.RETURN);
keywords.put("return", TYPE.RETURN); keywords.put("public", TYPE.PUBLIC);
keywords.put("public", TYPE.PUBLIC); keywords.put("private", TYPE.PRIVATE);
keywords.put("private", TYPE.PRIVATE); keywords.put("static", TYPE.STATIC);
keywords.put("static", TYPE.STATIC); keywords.put("int", TYPE.INT);
keywords.put("int", TYPE.INT); keywords.put("boolean", TYPE.BOOLEAN);
keywords.put("boolean", TYPE.BOOLEAN); keywords.put("void", TYPE.VOID);
keywords.put("void", TYPE.VOID); keywords.put("this", TYPE.THIS);
keywords.put("this", TYPE.THIS); keywords.put("if", TYPE.IF);
keywords.put("if", TYPE.IF); keywords.put("else", TYPE.ELSE);
keywords.put("else", TYPE.ELSE); keywords.put("while", TYPE.WHILE);
keywords.put("while", TYPE.WHILE); keywords.put("true", TYPE.TRUE);
keywords.put("true", TYPE.TRUE); keywords.put("false", TYPE.FALSE);
keywords.put("false", TYPE.FALSE); keywords.put("new", TYPE.NEW);
keywords.put("new", TYPE.NEW); }
}
public final TYPE type; public final TYPE type;
public SourcePosition posn; public SourcePosition posn;
public final String spelling; public final String spelling;
public Token(String spelling, TYPE type) { public Token(String spelling, TYPE type) {
this.type = type; this.type = type;
this.posn = null; this.posn = null;

View File

@ -1,5 +0,0 @@
class Test {
public int Test() {
}
}