parent
83c72019f5
commit
3517e9648c
|
@ -9,7 +9,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ public abstract class AST {
|
||||||
return cn;
|
return cn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract <A,R> R visit(Visitor<A,R> v, A o);
|
public abstract <A, R> R visit(Visitor<A, R> v, A o);
|
||||||
|
|
||||||
public SourcePosition posn;
|
public SourcePosition posn;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,15 +16,17 @@ 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
|
||||||
|
* root node of AST
|
||||||
*/
|
*/
|
||||||
public void showTree(AST ast){
|
public void showTree(AST ast) {
|
||||||
System.out.println("======= AST Display =========================");
|
System.out.println("======= AST Display =========================");
|
||||||
ast.visit(this, "");
|
ast.visit(this, "");
|
||||||
System.out.println("=============================================");
|
System.out.println("=============================================");
|
||||||
|
@ -34,8 +36,11 @@ public class ASTDisplay implements Visitor<String,Object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* display arbitrary text for a node
|
* display arbitrary text for a node
|
||||||
* @param prefix spacing to indicate depth in AST
|
*
|
||||||
* @param text preformatted node display
|
* @param prefix
|
||||||
|
* spacing to indicate depth in AST
|
||||||
|
* @param text
|
||||||
|
* preformatted node display
|
||||||
*/
|
*/
|
||||||
private void show(String prefix, String text) {
|
private void show(String prefix, String text) {
|
||||||
System.out.println(prefix + text);
|
System.out.println(prefix + text);
|
||||||
|
@ -43,8 +48,11 @@ public class ASTDisplay implements Visitor<String,Object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* display AST node by name
|
* display AST node by name
|
||||||
* @param prefix spacing to indicate depth in AST
|
*
|
||||||
* @param node AST node, will be shown by name
|
* @param prefix
|
||||||
|
* spacing to indicate depth in AST
|
||||||
|
* @param node
|
||||||
|
* AST node, will be shown by name
|
||||||
*/
|
*/
|
||||||
private void show(String prefix, AST node) {
|
private void show(String prefix, AST node) {
|
||||||
System.out.println(prefix + node.toString());
|
System.out.println(prefix + node.toString());
|
||||||
|
@ -52,7 +60,9 @@ public class ASTDisplay implements Visitor<String,Object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* quote a string
|
* quote a string
|
||||||
* @param text string to quote
|
*
|
||||||
|
* @param text
|
||||||
|
* string to quote
|
||||||
*/
|
*/
|
||||||
private String quote(String text) {
|
private String quote(String text) {
|
||||||
return ("\"" + text + "\"");
|
return ("\"" + text + "\"");
|
||||||
|
@ -60,73 +70,73 @@ public class ASTDisplay implements Visitor<String,Object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* increase depth in AST
|
* increase depth in AST
|
||||||
* @param prefix current spacing to indicate depth in AST
|
*
|
||||||
|
* @param prefix
|
||||||
|
* current spacing to indicate depth in AST
|
||||||
* @return new spacing
|
* @return new spacing
|
||||||
*/
|
*/
|
||||||
private String indent(String prefix) {
|
private String indent(String prefix) {
|
||||||
return 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) {
|
||||||
|
@ -135,90 +145,88 @@ public class ASTDisplay implements Visitor<String,Object> {
|
||||||
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){
|
public Object visitVardeclStmt(VarDeclStmt stmt, String arg) {
|
||||||
show(arg, stmt);
|
show(arg, stmt);
|
||||||
stmt.varDecl.visit(this, indent(arg));
|
stmt.varDecl.visit(this, indent(arg));
|
||||||
stmt.initExp.visit(this, indent(arg));
|
stmt.initExp.visit(this, indent(arg));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visitAssignStmt(AssignStmt stmt, String arg){
|
public Object visitAssignStmt(AssignStmt stmt, String arg) {
|
||||||
show(arg,stmt);
|
show(arg, stmt);
|
||||||
stmt.ref.visit(this, indent(arg));
|
stmt.ref.visit(this, indent(arg));
|
||||||
stmt.val.visit(this, indent(arg));
|
stmt.val.visit(this, indent(arg));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visitCallStmt(CallStmt stmt, String arg){
|
public Object visitCallStmt(CallStmt stmt, String arg) {
|
||||||
show(arg,stmt);
|
show(arg, stmt);
|
||||||
stmt.methodRef.visit(this, indent(arg));
|
stmt.methodRef.visit(this, indent(arg));
|
||||||
ExprList al = stmt.argList;
|
ExprList al = stmt.argList;
|
||||||
show(arg," ExprList [" + al.size() + "]");
|
show(arg, " ExprList [" + al.size() + "]");
|
||||||
String pfx = arg + " . ";
|
String pfx = arg + " . ";
|
||||||
for (Expression e: al) {
|
for (Expression e : al) {
|
||||||
e.visit(this, pfx);
|
e.visit(this, pfx);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visitIfStmt(IfStmt stmt, String arg){
|
public Object visitIfStmt(IfStmt stmt, String arg) {
|
||||||
show(arg,stmt);
|
show(arg, stmt);
|
||||||
stmt.cond.visit(this, indent(arg));
|
stmt.cond.visit(this, indent(arg));
|
||||||
stmt.thenStmt.visit(this, indent(arg));
|
stmt.thenStmt.visit(this, indent(arg));
|
||||||
if (stmt.elseStmt != null)
|
if (stmt.elseStmt != null)
|
||||||
|
@ -226,28 +234,27 @@ public class ASTDisplay implements Visitor<String,Object> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visitWhileStmt(WhileStmt stmt, String arg){
|
public Object visitWhileStmt(WhileStmt stmt, String arg) {
|
||||||
show(arg, stmt);
|
show(arg, stmt);
|
||||||
stmt.cond.visit(this, indent(arg));
|
stmt.cond.visit(this, indent(arg));
|
||||||
stmt.body.visit(this, indent(arg));
|
stmt.body.visit(this, indent(arg));
|
||||||
return null;
|
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){
|
public Object visitBinaryExpr(BinaryExpr expr, String arg) {
|
||||||
show(arg, expr);
|
show(arg, expr);
|
||||||
expr.operator.visit(this, indent(arg));
|
expr.operator.visit(this, indent(arg));
|
||||||
expr.left.visit(this, indent(indent(arg)));
|
expr.left.visit(this, indent(indent(arg)));
|
||||||
|
@ -255,49 +262,48 @@ public class ASTDisplay implements Visitor<String,Object> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visitRefExpr(RefExpr expr, String arg){
|
public Object visitRefExpr(RefExpr expr, String arg) {
|
||||||
show(arg, expr);
|
show(arg, expr);
|
||||||
expr.ref.visit(this, indent(arg));
|
expr.ref.visit(this, indent(arg));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visitCallExpr(CallExpr expr, String arg){
|
public Object visitCallExpr(CallExpr expr, String arg) {
|
||||||
show(arg, expr);
|
show(arg, expr);
|
||||||
expr.functionRef.visit(this, indent(arg));
|
expr.functionRef.visit(this, indent(arg));
|
||||||
ExprList al = expr.argList;
|
ExprList al = expr.argList;
|
||||||
show(arg," ExprList + [" + al.size() + "]");
|
show(arg, " ExprList + [" + al.size() + "]");
|
||||||
String pfx = arg + " . ";
|
String pfx = arg + " . ";
|
||||||
for (Expression e: al) {
|
for (Expression e : al) {
|
||||||
e.visit(this, pfx);
|
e.visit(this, pfx);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visitLiteralExpr(LiteralExpr expr, String arg){
|
public Object visitLiteralExpr(LiteralExpr expr, String arg) {
|
||||||
show(arg, expr);
|
show(arg, expr);
|
||||||
expr.literal.visit(this, indent(arg));
|
expr.literal.visit(this, indent(arg));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visitNewArrayExpr(NewArrayExpr expr, String arg){
|
public Object visitNewArrayExpr(NewArrayExpr expr, String arg) {
|
||||||
show(arg, expr);
|
show(arg, expr);
|
||||||
expr.eltType.visit(this, indent(arg));
|
expr.eltType.visit(this, indent(arg));
|
||||||
expr.sizeExpr.visit(this, indent(arg));
|
expr.sizeExpr.visit(this, indent(arg));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visitNewObjectExpr(NewObjectExpr expr, String arg){
|
public Object visitNewObjectExpr(NewObjectExpr expr, String arg) {
|
||||||
show(arg, expr);
|
show(arg, expr);
|
||||||
expr.classtype.visit(this, indent(arg));
|
expr.classtype.visit(this, indent(arg));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
//
|
||||||
// REFERENCES
|
// REFERENCES
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public Object visitQualifiedRef(QualifiedRef qr, String arg) {
|
public Object visitQualifiedRef(QualifiedRef qr, String arg) {
|
||||||
show(arg, qr);
|
show(arg, qr);
|
||||||
|
@ -314,39 +320,38 @@ public class ASTDisplay implements Visitor<String,Object> {
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
public <A, R> R visit(Visitor<A, R> v, A o) {
|
||||||
return v.visitArrayType(this, o);
|
return v.visitArrayType(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type eltType;
|
public Type eltType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,14 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,16 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,13 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,14 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,14 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,12 @@ public class ClassDecl extends Declaration {
|
||||||
super(cn, null, posn);
|
super(cn, null, posn);
|
||||||
fieldDeclList = fdl;
|
fieldDeclList = fdl;
|
||||||
methodDeclList = mdl;
|
methodDeclList = mdl;
|
||||||
|
|
||||||
|
Identifier ident = new Identifier(cn, posn);
|
||||||
|
type = new ClassType(ident, 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.visitClassDecl(this, o);
|
return v.visitClassDecl(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,13 @@ 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) {
|
public <A, R> R visit(Visitor<A, R> v, A o) {
|
||||||
return v.visitClassType(this, o);
|
return v.visitClassType(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,9 @@ public abstract class Declaration extends AST {
|
||||||
|
|
||||||
@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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ 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;
|
||||||
|
|
|
@ -7,17 +7,16 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,16 +9,16 @@ 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){
|
public FieldDecl(boolean isPrivate, boolean isStatic, Type t, String name,
|
||||||
|
SourcePosition posn) {
|
||||||
super(isPrivate, isStatic, t, name, posn);
|
super(isPrivate, isStatic, t, name, posn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldDecl(MemberDecl md, SourcePosition posn) {
|
public FieldDecl(MemberDecl md, SourcePosition posn) {
|
||||||
super(md,posn);
|
super(md, 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.visitFieldDecl(this, o);
|
return v.visitFieldDecl(this, o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@ 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>();
|
||||||
}
|
}
|
||||||
|
@ -18,11 +17,11 @@ public class FieldDeclList implements Iterable<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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,12 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,11 @@ import miniJava.SyntacticAnalyzer.SourcePosition;
|
||||||
|
|
||||||
public class Identifier extends Terminal {
|
public class Identifier extends Terminal {
|
||||||
|
|
||||||
public Identifier (String s, SourcePosition posn) {
|
public Identifier(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.visitIdentifier(this, o);
|
return v.visitIdentifier(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,23 +7,22 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,13 +9,13 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class IntLiteral extends Literal {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,14 +7,13 @@ 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){
|
public <A, R> R visit(Visitor<A, R> v, A o) {
|
||||||
return v.visitLiteralExpr(this, o);
|
return v.visitLiteralExpr(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,14 @@ 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,
|
||||||
|
String name, SourcePosition posn) {
|
||||||
super(name, mt, posn);
|
super(name, mt, posn);
|
||||||
this.isPrivate = isPrivate;
|
this.isPrivate = isPrivate;
|
||||||
this.isStatic = isStatic;
|
this.isStatic = isStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemberDecl(MemberDecl md, SourcePosition posn){
|
public MemberDecl(MemberDecl md, SourcePosition posn) {
|
||||||
super(md.name, md.type, posn);
|
super(md.name, md.type, posn);
|
||||||
this.isPrivate = md.isPrivate;
|
this.isPrivate = md.isPrivate;
|
||||||
this.isStatic = md.isStatic;
|
this.isStatic = md.isStatic;
|
||||||
|
|
|
@ -9,8 +9,9 @@ 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) {
|
||||||
|
super(md, posn);
|
||||||
parameterDeclList = pl;
|
parameterDeclList = pl;
|
||||||
statementList = sl;
|
statementList = sl;
|
||||||
returnExp = e;
|
returnExp = e;
|
||||||
|
|
|
@ -7,8 +7,7 @@ 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>();
|
||||||
}
|
}
|
||||||
|
@ -18,11 +17,11 @@ public class MethodDeclList implements Iterable<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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,14 @@ 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) {
|
public <A, R> R visit(Visitor<A, R> v, A o) {
|
||||||
return v.visitNewArrayExpr(this, o);
|
return v.visitNewArrayExpr(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,6 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,14 +7,13 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,12 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class Package extends AST {
|
||||||
classDeclList = cdl;
|
classDeclList = cdl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <A,R> R visit(Visitor<A,R> v, A o) {
|
public <A, R> R visit(Visitor<A, R> v, A o) {
|
||||||
return v.visitPackage(this, o);
|
return v.visitPackage(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,4 +17,3 @@ public class ParameterDecl extends LocalDecl {
|
||||||
return v.visitParameterDecl(this, o);
|
return v.visitParameterDecl(this, o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@ 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>();
|
||||||
}
|
}
|
||||||
|
@ -18,11 +17,11 @@ public class ParameterDeclList implements Iterable<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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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;
|
||||||
|
|
|
@ -7,14 +7,13 @@ 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) {
|
public <A, R> R visit(Visitor<A, R> v, A o) {
|
||||||
return v.visitRefExpr(this, o);
|
return v.visitRefExpr(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,16 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import miniJava.SyntacticAnalyzer.SourcePosition;
|
||||||
|
|
||||||
abstract public class Type extends AST {
|
abstract public class Type extends AST {
|
||||||
|
|
||||||
public Type(TypeKind typ, SourcePosition posn){
|
public Type(TypeKind typ, SourcePosition posn) {
|
||||||
super(posn);
|
super(posn);
|
||||||
typeKind = typ;
|
typeKind = typ;
|
||||||
}
|
}
|
||||||
|
@ -17,5 +17,3 @@ abstract public class Type extends AST {
|
||||||
public TypeKind typeKind;
|
public TypeKind typeKind;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,14 @@ 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) {
|
public <A, R> R visit(Visitor<A, R> v, A o) {
|
||||||
return v.visitUnaryExpr(this, o);
|
return v.visitUnaryExpr(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class VarDecl extends LocalDecl {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,14 @@ 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) {
|
public <A, R> R visit(Visitor<A, R> v, A o) {
|
||||||
return v.visitVardeclStmt(this, o);
|
return v.visitVardeclStmt(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 visitFieldDecl(FieldDecl fd, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitMethodDecl(MethodDecl md, ArgType arg);
|
public ResultType visitMethodDecl(MethodDecl md, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitParameterDecl(ParameterDecl pd, ArgType arg);
|
public ResultType visitParameterDecl(ParameterDecl pd, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitVarDecl(VarDecl decl, ArgType arg);
|
public ResultType visitVarDecl(VarDecl decl, ArgType arg);
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
public ResultType visitBaseType(BaseType type, ArgType arg);
|
public ResultType visitBaseType(BaseType type, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitClassType(ClassType type, ArgType arg);
|
public ResultType visitClassType(ClassType type, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitArrayType(ArrayType type, ArgType arg);
|
public ResultType visitArrayType(ArrayType type, ArgType arg);
|
||||||
|
|
||||||
// Statements
|
// Statements
|
||||||
public ResultType visitBlockStmt(BlockStmt stmt, ArgType arg);
|
public ResultType visitBlockStmt(BlockStmt stmt, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitVardeclStmt(VarDeclStmt stmt, ArgType arg);
|
public ResultType visitVardeclStmt(VarDeclStmt stmt, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitAssignStmt(AssignStmt stmt, ArgType arg);
|
public ResultType visitAssignStmt(AssignStmt stmt, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitCallStmt(CallStmt stmt, ArgType arg);
|
public ResultType visitCallStmt(CallStmt stmt, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitIfStmt(IfStmt stmt, ArgType arg);
|
public ResultType visitIfStmt(IfStmt stmt, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitWhileStmt(WhileStmt stmt, ArgType arg);
|
public ResultType visitWhileStmt(WhileStmt stmt, ArgType arg);
|
||||||
|
|
||||||
// Expressions
|
// Expressions
|
||||||
public ResultType visitUnaryExpr(UnaryExpr expr, ArgType arg);
|
public ResultType visitUnaryExpr(UnaryExpr expr, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitBinaryExpr(BinaryExpr expr, ArgType arg);
|
public ResultType visitBinaryExpr(BinaryExpr expr, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitRefExpr(RefExpr expr, ArgType arg);
|
public ResultType visitRefExpr(RefExpr expr, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitCallExpr(CallExpr expr, ArgType arg);
|
public ResultType visitCallExpr(CallExpr expr, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitLiteralExpr(LiteralExpr expr, ArgType arg);
|
public ResultType visitLiteralExpr(LiteralExpr expr, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitNewObjectExpr(NewObjectExpr expr, ArgType arg);
|
public ResultType visitNewObjectExpr(NewObjectExpr expr, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitNewArrayExpr(NewArrayExpr expr, ArgType arg);
|
public ResultType visitNewArrayExpr(NewArrayExpr expr, ArgType arg);
|
||||||
|
|
||||||
// References
|
// References
|
||||||
public ResultType visitQualifiedRef(QualifiedRef ref, ArgType arg);
|
public ResultType visitQualifiedRef(QualifiedRef ref, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitIndexedRef(IndexedRef ref, ArgType arg);
|
public ResultType visitIndexedRef(IndexedRef ref, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitIdRef(IdRef ref, ArgType arg);
|
public ResultType visitIdRef(IdRef ref, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitThisRef(ThisRef ref, ArgType arg);
|
public ResultType visitThisRef(ThisRef ref, ArgType arg);
|
||||||
|
|
||||||
// Terminals
|
// Terminals
|
||||||
public ResultType visitIdentifier(Identifier id, ArgType arg);
|
public ResultType visitIdentifier(Identifier id, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitOperator(Operator op, ArgType arg);
|
public ResultType visitOperator(Operator op, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitIntLiteral(IntLiteral num, ArgType arg);
|
public ResultType visitIntLiteral(IntLiteral num, ArgType arg);
|
||||||
|
|
||||||
public ResultType visitBooleanLiteral(BooleanLiteral bool, ArgType arg);
|
public ResultType visitBooleanLiteral(BooleanLiteral bool, ArgType arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,14 @@ 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) {
|
public <A, R> R visit(Visitor<A, R> v, A o) {
|
||||||
return v.visitWhileStmt(this, o);
|
return v.visitWhileStmt(this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,24 +3,23 @@ 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));
|
||||||
|
@ -34,17 +33,15 @@ public class Compiler {
|
||||||
// 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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,109 +1,92 @@
|
||||||
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
|
||||||
|
if (mainMethod == null)
|
||||||
|
Reporter.report(ErrorType.MAIN_UNDECLARED, null, null);
|
||||||
|
|
||||||
// Check class types match
|
return (Reporter.error) ? Compiler.rc : 0;
|
||||||
if(t1.typeKind == TypeKind.CLASS) {
|
|
||||||
if(t2.typeKind != TypeKind.CLASS) {
|
|
||||||
Reporter.report(ErrorType.TYPE_MISMATCH, t1, t2);
|
|
||||||
} 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);
|
// PACKAGE
|
||||||
}
|
//
|
||||||
}
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -111,16 +94,25 @@ public class Analyzer implements Visitor<IdentificationTable, Type> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitClassDecl(ClassDecl cd, IdentificationTable arg) {
|
|
||||||
IdentificationTable cdTable = arg.getScope(cd);
|
|
||||||
if(cdTable != null) {
|
|
||||||
|
|
||||||
for(FieldDecl fd : cd.fieldDeclList) {
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// DECLARATIONS
|
||||||
|
//
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public Type visitClassDecl(ClassDecl cd, IdentificationTable arg) {
|
||||||
|
|
||||||
|
IdentificationTable cdTable = arg.getScope(cd);
|
||||||
|
|
||||||
|
if (cdTable != null) {
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,142 +120,158 @@ public class Analyzer implements Visitor<IdentificationTable, Type> {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TYPES
|
||||||
|
//
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// STATEMENTS
|
||||||
|
//
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
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
|
|
||||||
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
|
// 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) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -273,15 +281,15 @@ public class Analyzer implements Visitor<IdentificationTable, Type> {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -289,164 +297,270 @@ public class Analyzer implements Visitor<IdentificationTable, Type> {
|
||||||
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 null;
|
return new BaseType(TypeKind.BOOLEAN, opType.posn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
if(expr.functionRef.decl instanceof MethodDecl) {
|
||||||
|
|
||||||
|
MethodDecl decl = (MethodDecl) expr.functionRef.decl;
|
||||||
|
|
||||||
// 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) expr.functionRef.decl;
|
if (decl.parameterDeclList.size() != expr.argList.size()) {
|
||||||
if(decl.parameterDeclList.size() != expr.argList.size()) {
|
Reporter.report(ErrorType.INVALID_PARAM_COUNT, expr, decl);
|
||||||
Reporter.report(ErrorType.INVALID_PARAM_COUNT, expr);
|
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < expr.argList.size(); i++) {
|
for (int i = 0; i < expr.argList.size(); i++) {
|
||||||
Type exprType = expr.argList.get(i).visit(this, arg);
|
Type exprType = expr.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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Reporter.report(ErrorType.NONFUNCTION_CALL, expr, null);
|
||||||
|
}
|
||||||
|
|
||||||
return functionType;
|
return functionRefType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitLiteralExpr(LiteralExpr expr, IdentificationTable arg) {
|
public Type visitLiteralExpr(LiteralExpr expr, IdentificationTable arg) {
|
||||||
|
Type literalType = expr.literal.visit(this, arg);
|
||||||
return expr.literal.visit(this, arg);
|
return literalType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitNewObjectExpr(NewObjectExpr expr, IdentificationTable arg) {
|
public Type visitNewObjectExpr(NewObjectExpr expr, IdentificationTable arg) {
|
||||||
|
Type objectType = expr.classtype.visit(this, arg);
|
||||||
return expr.classtype.visit(this, arg);
|
return objectType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type visitNewArrayExpr(NewArrayExpr expr, IdentificationTable arg) {
|
public Type visitNewArrayExpr(NewArrayExpr expr, IdentificationTable arg) {
|
||||||
Type sizeExprType = expr.sizeExpr.visit(this, arg);
|
Type sizeExprType = expr.sizeExpr.visit(this, arg);
|
||||||
if(sizeExprType.typeKind != TypeKind.INT) {
|
if (sizeExprType.typeKind != TypeKind.INT) {
|
||||||
Reporter.report(ErrorType.INVALID_INDEX, expr.sizeExpr);
|
Reporter.report(ErrorType.INVALID_INDEX, expr.sizeExpr, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return expr.eltType.visit(this, arg);
|
Type eltType = expr.eltType.visit(this, arg);
|
||||||
|
return new ArrayType(eltType, expr.posn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// REFERENCES
|
||||||
|
//
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public Type visitQualifiedRef(QualifiedRef ref, IdentificationTable arg) {
|
public Type visitQualifiedRef(QualifiedRef ref, IdentificationTable arg) {
|
||||||
ref.ref.visit(this, arg);
|
|
||||||
ref.id.visit(this, arg);
|
|
||||||
|
|
||||||
// Check that each declaration is nested properly
|
Type refType = ref.ref.visit(this, arg);
|
||||||
if(ref.decl == null || table.getDeclaration(ref.decl.name) == null) {
|
|
||||||
System.out.println(ref.id.spelling);
|
// Note qualified ref's only make sense in the context of classes
|
||||||
// report(ErrorType.MISSING_DECL, ref.ref.decl);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The member should not be a method, as this is unsupported
|
||||||
|
else if(qualified instanceof MethodDecl) {
|
||||||
|
Reporter.report(ErrorType.UNDEFINED, ref.id, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we can assume the object is a variable and attempt to access members
|
||||||
|
else if(md.isPrivate && currentClassDecl != qualClassDecl) {
|
||||||
|
Reporter.report(ErrorType.VISIBILITY, md, ref.id);
|
||||||
|
return new BaseType(TypeKind.ERROR, ref.id.posn);
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.id.decl = md;
|
||||||
|
ref.decl = md;
|
||||||
|
return md.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TERMINALS
|
||||||
|
//
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
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 {
|
||||||
|
|
||||||
|
@ -33,29 +29,29 @@ public class IdentificationTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -65,12 +61,14 @@ public class IdentificationTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,37 +76,34 @@ public class IdentificationTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
|
@ -116,13 +111,15 @@ public class IdentificationTable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,15 +128,94 @@ public class IdentificationTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,20 @@ 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 {
|
||||||
|
@ -21,102 +24,147 @@ 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);
|
||||||
|
}
|
||||||
|
|
||||||
// VarDeclStmt is only statement in conditional branch
|
return t.typeKind.toString();
|
||||||
case VAR_COND_ONLY: {
|
}
|
||||||
System.out.println("***Conditional statment cannot be followed by a variable declaration statement " + ast.posn);
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
|
||||||
|
// Cannot access 'this' in a static method
|
||||||
|
case THIS: {
|
||||||
|
MethodDecl md = (MethodDecl) a2;
|
||||||
|
emit("Cannot reference 'this' " + a1.posn + " in static method '" + md.name + "' " + md.posn);
|
||||||
break;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
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
|
// A public static void main(String[] args) method was not declared
|
||||||
|
case MAIN_UNDECLARED: {
|
||||||
|
emit("A main function was not declared");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parameter counts of an expression/statement do not match declaration
|
||||||
case INVALID_PARAM_COUNT: {
|
case INVALID_PARAM_COUNT: {
|
||||||
System.out.println("***The number of passed parameters does not equal expected count " + ast.posn);
|
MethodDecl md = (MethodDecl) a2;
|
||||||
|
emit("Call to '" + md.name + "' " + a2.posn + " has an invalid parameter count at " + a1.posn);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The expected expression MUST return an int (such as the index of an array)
|
// A public static void main(String[] args) was declared more than once
|
||||||
|
case MULTIPLE_MAIN: {
|
||||||
|
emit("Main function at " + a1.posn + " already declared previously at " + a2.posn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A reference has been made to a non-existant type
|
||||||
|
case UNDECLARED_TYPE: {
|
||||||
|
if(a1 instanceof Type) {
|
||||||
|
String typeName = getTypeName((Type) a1);
|
||||||
|
emit("'" + typeName + "' " + a1.posn + " has not been declared previously");
|
||||||
|
} else {
|
||||||
|
emit("Identifier at " + a1.posn + " could not be identified");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Variable Declaration Statement was made as the only statement of a condition
|
||||||
|
case SINGLE_VARCOND: {
|
||||||
|
emit("Conditional statment cannot be followed by a variable declaration statement exclusively " + a1.posn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An indexed expression must be of an int type
|
||||||
case INVALID_INDEX: {
|
case INVALID_INDEX: {
|
||||||
System.out.println("***Expected an integer value as the index of an array " + ast.posn);
|
emit("Index expression is not of type int " + a1.posn);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hmmm.....
|
|
||||||
case UNIDENTIFIED_TYPE: {
|
|
||||||
System.out.println("***Unexpected type " + ast.posn);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear Warning
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Type specific error reporting.
|
|
||||||
* @param type
|
|
||||||
* @param t1
|
|
||||||
* @param t2
|
|
||||||
*/
|
|
||||||
public static void report(ErrorType type, Type t1, Type t2) {
|
|
||||||
error = true;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two classes don't match
|
|
||||||
case TYPE_CLASS_MISMATCH: {
|
|
||||||
ClassType c1 = (ClassType) t1;
|
|
||||||
ClassType c2 = (ClassType) t2;
|
|
||||||
System.out.println("***Expected type " + c1.className.spelling + " but got " + c2.className.spelling + c2.posn);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Two arrays don't match
|
|
||||||
case TYPE_ARRAY_MISMATCH: {
|
|
||||||
ArrayType a1 = (ArrayType) t1;
|
|
||||||
ArrayType a2 = (ArrayType) t2;
|
|
||||||
System.out.println("***Expected array type " + a1.eltType.typeKind + " but got " + a2.eltType.typeKind + t2.posn);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear Warning
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class ParsingException extends Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParsingException(Token t) {
|
public ParsingException(Token t) {
|
||||||
super("Parsing error with " + t.toString());
|
super("Parsing error with " + t.spelling + " at " + t.posn.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,12 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,14 +33,13 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -51,19 +51,21 @@ public class Parser {
|
||||||
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);
|
||||||
|
@ -73,26 +75,28 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -100,7 +104,7 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
Type t = parseType();
|
Type t = parseType();
|
||||||
if(start == null) {
|
if (start == null) {
|
||||||
start = t.posn;
|
start = t.posn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,22 +112,22 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 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);
|
||||||
|
@ -131,9 +135,9 @@ public class Parser {
|
||||||
// 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);
|
||||||
|
@ -150,13 +154,14 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
|
@ -170,7 +175,7 @@ public class Parser {
|
||||||
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);
|
||||||
|
@ -184,7 +189,7 @@ public class Parser {
|
||||||
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.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(c, id.posn);
|
return new ArrayType(c, id.posn);
|
||||||
|
@ -201,6 +206,7 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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 {
|
||||||
|
@ -213,7 +219,7 @@ public class Parser {
|
||||||
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);
|
||||||
|
@ -226,12 +232,13 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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());
|
||||||
}
|
}
|
||||||
|
@ -242,17 +249,18 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -266,11 +274,12 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -282,7 +291,7 @@ public class Parser {
|
||||||
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);
|
||||||
|
@ -295,25 +304,22 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -328,7 +334,7 @@ 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);
|
||||||
|
@ -349,11 +355,15 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
|
@ -373,10 +383,10 @@ public class Parser {
|
||||||
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);
|
||||||
|
@ -397,20 +407,17 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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: {
|
||||||
|
@ -440,12 +447,12 @@ public class Parser {
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +460,7 @@ public class Parser {
|
||||||
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();
|
||||||
|
@ -468,7 +475,7 @@ public class Parser {
|
||||||
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);
|
||||||
|
@ -484,12 +491,13 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
|
@ -502,22 +510,22 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
@ -529,12 +537,13 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -546,12 +555,13 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -563,13 +573,15 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -581,12 +593,13 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -598,12 +611,13 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
@ -614,13 +628,14 @@ public class Parser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
}
|
}
|
||||||
|
@ -628,9 +643,11 @@ public class Parser {
|
||||||
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 {
|
||||||
|
|
|
@ -20,6 +20,7 @@ public class Scanner {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans in input, returning next token.
|
* Scans in input, returning next token.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
|
@ -28,16 +29,17 @@ public class Scanner {
|
||||||
String attr = "";
|
String attr = "";
|
||||||
Token token = null;
|
Token token = null;
|
||||||
|
|
||||||
while(token == null) {
|
while (token == null) {
|
||||||
|
|
||||||
// Check for EOF
|
// Check for EOF
|
||||||
int c = read();
|
int c = read();
|
||||||
if(c == -1) return new Token("", Token.TYPE.EOT);
|
if (c == -1)
|
||||||
|
return new Token("", Token.TYPE.EOT);
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
attr += (char) c;
|
attr += (char) c;
|
||||||
|
|
||||||
switch(c) {
|
switch (c) {
|
||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
case '*':
|
case '*':
|
||||||
|
@ -45,32 +47,42 @@ public class Scanner {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
if(peek('+')) throw new ScanningException(col, line);
|
if (peek('+'))
|
||||||
|
throw new ScanningException(col, line);
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-':
|
case '-':
|
||||||
if(peek('-')) throw new ScanningException(col, line);
|
if (peek('-'))
|
||||||
|
throw new ScanningException(col, line);
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Check for comment
|
// Check for comment
|
||||||
case '/':
|
case '/':
|
||||||
if(peek('*')) { read(); readComment(); attr = ""; }
|
if (peek('*')) {
|
||||||
else if(peek('/')) { readLine(); attr = ""; }
|
read();
|
||||||
else token = new Token(attr, Token.TYPE.BINOP);
|
readComment();
|
||||||
|
attr = "";
|
||||||
|
} else if (peek('/')) {
|
||||||
|
readLine();
|
||||||
|
attr = "";
|
||||||
|
} else
|
||||||
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Check for c or c=
|
// Check for c or c=
|
||||||
case '>':
|
case '>':
|
||||||
case '<':
|
case '<':
|
||||||
if(peek('=')) attr += (char) read();
|
if (peek('='))
|
||||||
|
attr += (char) read();
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Check for ! or !=
|
// Check for ! or !=
|
||||||
case '!':
|
case '!':
|
||||||
if(!peek('=')) token = new Token(attr, Token.TYPE.UNOP);
|
if (!peek('='))
|
||||||
|
token = new Token(attr, Token.TYPE.UNOP);
|
||||||
else {
|
else {
|
||||||
attr += (char) read();
|
attr += (char) read();
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
|
@ -80,7 +92,8 @@ public class Scanner {
|
||||||
// Check for && or ||
|
// Check for && or ||
|
||||||
case '&':
|
case '&':
|
||||||
case '|':
|
case '|':
|
||||||
if(!peek((char) c)) throw new ScanningException(col, line);
|
if (!peek((char) c))
|
||||||
|
throw new ScanningException(col, line);
|
||||||
else {
|
else {
|
||||||
attr += (char) read();
|
attr += (char) read();
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
|
@ -89,7 +102,8 @@ public class Scanner {
|
||||||
|
|
||||||
// Other Operators
|
// Other Operators
|
||||||
case '=':
|
case '=':
|
||||||
if(!peek('=')) token = new Token(attr, Token.TYPE.EQUALS);
|
if (!peek('='))
|
||||||
|
token = new Token(attr, Token.TYPE.EQUALS);
|
||||||
else {
|
else {
|
||||||
attr += (char) read();
|
attr += (char) read();
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
|
@ -135,13 +149,13 @@ public class Scanner {
|
||||||
default:
|
default:
|
||||||
|
|
||||||
// Identifier or Keyword
|
// Identifier or Keyword
|
||||||
if(isAlpha((char) c)) {
|
if (isAlpha((char) c)) {
|
||||||
for(char n = peek(); isAlpha(n) || isDigit(n);) {
|
for (char n = peek(); isAlpha(n) || isDigit(n);) {
|
||||||
attr += (char) read();
|
attr += (char) read();
|
||||||
n = peek();
|
n = peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Token.keywords.containsKey(attr)) {
|
if (Token.keywords.containsKey(attr)) {
|
||||||
token = new Token(attr, Token.keywords.get(attr));
|
token = new Token(attr, Token.keywords.get(attr));
|
||||||
} else {
|
} else {
|
||||||
token = new Token(attr, Token.TYPE.ID);
|
token = new Token(attr, Token.TYPE.ID);
|
||||||
|
@ -149,8 +163,8 @@ public class Scanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number
|
// Number
|
||||||
else if(isDigit((char) c)) {
|
else if (isDigit((char) c)) {
|
||||||
for(char n = peek(); isDigit(n);) {
|
for (char n = peek(); isDigit(n);) {
|
||||||
attr += (char) read();
|
attr += (char) read();
|
||||||
n = peek();
|
n = peek();
|
||||||
}
|
}
|
||||||
|
@ -159,12 +173,14 @@ public class Scanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whitespace
|
// Whitespace
|
||||||
else if(isWhitespace((char) c)) {
|
else if (isWhitespace((char) c)) {
|
||||||
attr = "";
|
attr = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unrecognized Character
|
// Unrecognized Character
|
||||||
else throw new ScanningException(col, line);;
|
else
|
||||||
|
throw new ScanningException(col, line);
|
||||||
|
;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -174,9 +190,9 @@ public class Scanner {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks at next character in stream without consuming.
|
* Looks at next character in stream without consuming.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
|
@ -187,14 +203,14 @@ public class Scanner {
|
||||||
input.reset();
|
input.reset();
|
||||||
|
|
||||||
return next == -1 ? '\0' : (char) next;
|
return next == -1 ? '\0' : (char) next;
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ScanningException(col, line);
|
throw new ScanningException(col, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether passed character is next in stream.
|
* Returns whether passed character is next in stream.
|
||||||
|
*
|
||||||
* @param c
|
* @param c
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
|
@ -206,73 +222,77 @@ public class Scanner {
|
||||||
input.reset();
|
input.reset();
|
||||||
|
|
||||||
return c == next;
|
return c == next;
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ScanningException(col, line);
|
throw new ScanningException(col, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alternative reading that keeps track of position.
|
* Alternative reading that keeps track of position.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private int read() throws ScanningException {
|
private int read() throws ScanningException {
|
||||||
try {
|
try {
|
||||||
int next = input.read();
|
int next = input.read();
|
||||||
if(next != '\n' && next != '\r') col += 1;
|
if (next != '\n' && next != '\r')
|
||||||
|
col += 1;
|
||||||
else {
|
else {
|
||||||
col = 1; line += 1;
|
col = 1;
|
||||||
if(peek('\r') || peek('\n')) next = input.read();
|
line += 1;
|
||||||
|
if (peek('\r') || peek('\n'))
|
||||||
|
next = input.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ScanningException(col, line);
|
throw new ScanningException(col, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consumes input until an end of comment has been reached.
|
* Consumes input until an end of comment has been reached.
|
||||||
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void readComment() throws ScanningException {
|
private void readComment() throws ScanningException {
|
||||||
char prev = '\0', current = '\0';
|
char prev = '\0', current = '\0';
|
||||||
while(prev != '*' || current != '/') {
|
while (prev != '*' || current != '/') {
|
||||||
|
|
||||||
prev = current;
|
prev = current;
|
||||||
|
|
||||||
int next = read();
|
int next = read();
|
||||||
if(next == -1) throw new ScanningException(col, line);
|
if (next == -1)
|
||||||
else current = (char) next;
|
throw new ScanningException(col, line);
|
||||||
|
else
|
||||||
|
current = (char) next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consumes input until the end of line is reached
|
* Consumes input until the end of line is reached
|
||||||
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void readLine() throws ScanningException {
|
private void readLine() throws ScanningException {
|
||||||
for(int n = 0; n != '\n' && n != '\r' && n != -1; n = read()) {}
|
for (int n = 0; n != '\n' && n != '\r' && n != -1; n = read()) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells whether character is alphabetical.
|
* Tells whether character is alphabetical.
|
||||||
|
*
|
||||||
* @param c
|
* @param c
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private boolean isAlpha(char c) {
|
private boolean isAlpha(char c) {
|
||||||
return (c >= 'a' && c <= 'z')
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||||
|| (c >= 'A' && c <= 'Z')
|
|
||||||
|| c == '_';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells whether character is numerical.
|
* Tells whether character is numerical.
|
||||||
|
*
|
||||||
* @param c
|
* @param c
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -280,17 +300,14 @@ public class Scanner {
|
||||||
return c >= '0' && c <= '9';
|
return c >= '0' && c <= '9';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells wheter character is whitespace.
|
* Tells wheter character is whitespace.
|
||||||
|
*
|
||||||
* @param c
|
* @param c
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private boolean isWhitespace(char c) {
|
private boolean isWhitespace(char c) {
|
||||||
return c == ' '
|
return c == ' ' || c == '\n' || c == '\r' || c == '\t';
|
||||||
|| c == '\n'
|
|
||||||
|| c == '\r'
|
|
||||||
|| c == '\t';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,49 +7,23 @@ 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);
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
class Test {
|
|
||||||
public int Test() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue