From 31aac86103f0c05fbaaf1e690ec27b23cfeea9c0 Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Fri, 10 Oct 2014 06:34:52 +0800 Subject: nearly finished --- src/minijava/symboltable/MClass.java | 47 +++++++++++- src/minijava/symboltable/MClasses.java | 64 +++++++++++++++++ src/minijava/symboltable/MExpression.java | 87 ++++++++++++++++++++++- src/minijava/symboltable/MIdentifier.java | 2 + src/minijava/symboltable/MMethod.java | 71 +++++++++++++++++- src/minijava/symboltable/MPrimaryExpr.java | 44 ++++++++++++ src/minijava/symboltable/MStatement.java | 84 ++++++++++++++++++++-- src/minijava/symboltable/MStatementList.java | 7 ++ src/minijava/typecheck/Main.java | 13 +++- src/minijava/visitor/BuildSymbolTableVisitor.java | 59 +++++++++------ 10 files changed, 448 insertions(+), 30 deletions(-) diff --git a/src/minijava/symboltable/MClass.java b/src/minijava/symboltable/MClass.java index 37bfcfb..10354a8 100644 --- a/src/minijava/symboltable/MClass.java +++ b/src/minijava/symboltable/MClass.java @@ -6,9 +6,11 @@ package minijava.symboltable; import minijava.typecheck.PrintError; public class MClass extends MLocalVarType { - public MClasses all_classes; // 所有类的列表 + public MClasses all_classes; // 所有类的列表,在建立符号表时完成 public boolean isDeclared = false; // 是否已声明,用于检查符号表 - public String extend_class_name = null; // 所继承的类 + public String extend_class_name = null; // 所继承的类名 + public MClass extend_class = null; // 所继承的类,在符号表建立完成后才能求得 + public int extend_tag = 0; // 检测循环继承时用,0表示未检测 public MMethodList methods; public MClass(String v_name, MClasses all, int m_line, int m_column) { @@ -36,9 +38,50 @@ public class MClass extends MLocalVarType { return "Method double declaration " + "\"" + method_name + "\"."; } methods.addMethod(method); + method.method_class = this; return null; } + // 检测类型名是否有效 + public boolean validType(String s_type) { + if (s_type==MIdentifier.intType + || s_type==MIdentifier.boolType + || s_type==MIdentifier.arrType + || s_type==MIdentifier.voidType + || s_type==MIdentifier.sArrayType) { + return true; + } + + if (all_classes.findClassByName(s_type)!=null) { + return true; + } + + return false; + } + + // 对类进行类型检查 + public boolean classVarCheck() { + boolean result = true; + for (int i=0; i mj_classes = new Vector(); // 用于存放类 + MClass findClassByName(String c_name) { + for (int i=0; i IntegerLiteral() @@ -35,6 +37,40 @@ public class MPrimaryExpr extends MType { } } + public String primExprType(MMethod m) { + switch (e_type) { + case Int: + return MIdentifier.intType; + case Alloc: + return e_id.getName(); + case ArrayAlloc: + return MIdentifier.arrType; + case Braket: + return e_exp.exprType(m); + case True: + case False: + return MIdentifier.boolType; + case Id: + MVariable m_var = m.findVarByName(e_id.name); + if (m_var!=null) { + return m_var.typename; + } else { + return null; + } + case Not: + if (e_exp.exprType(m)==MIdentifier.boolType) { + return MIdentifier.boolType; + } else { + PrintError.print(getLine(), getColumn(), "A non boolean expr after '!' operator"); + return null; + } + case This: + return m.method_class.name; + default: + return null; + } + } + public void printPrimExpr(int spaces) { System.err.print(OutputFormat.spaces(spaces)); @@ -49,6 +85,14 @@ public class MPrimaryExpr extends MType { case Id: System.err.print(e_id.getName()); break; + case Alloc: + System.err.print("new "+e_id.getName()+"()"); + break; + case ArrayAlloc: + System.err.print("new int["); + e_exp.printExpr(0); + System.err.print("]"); + break; } } } diff --git a/src/minijava/symboltable/MStatement.java b/src/minijava/symboltable/MStatement.java index 6410ca0..3610719 100644 --- a/src/minijava/symboltable/MStatement.java +++ b/src/minijava/symboltable/MStatement.java @@ -1,5 +1,7 @@ package minijava.symboltable; +import minijava.typecheck.PrintError; + public class MStatement extends MType { public enum Keyword { Block, Assign, ArrAssign, If, While, Print; @@ -10,7 +12,8 @@ public class MStatement extends MType { public MExpression e_first, e_second; // for assign(e_first), array assign, if, while, print public MStatement s_first, s_second; // for if, while - public MStatement(Keyword keyw) { + public MStatement(int s_line, int s_column, Keyword keyw) { + super(s_line, s_column); s_type = keyw; s_list = null; s_id = null; @@ -18,6 +21,63 @@ public class MStatement extends MType { s_first = s_second = null; } + public void checkStatement(MMethod m) { + switch (s_type) { + case ArrAssign: + // id[expr] = expr + if (m.findVarByName(s_id.name).typename==MIdentifier.arrType + && e_first.exprType(m)==MIdentifier.intType + && e_second.exprType(m)==MIdentifier.intType) { + return; + } else { + PrintError.print(line, column, "type mismatch in array assign statement"); + } + break; + case Assign: + // id = expr + MVariable m_var = m.findVarByName(s_id.name); + if (m_var==null) { + PrintError.print(line, column, "variable "+s_id.name+" not exist!"); + return; + } else if (m_var.typename.equals(e_first.exprType(m))) { + return; + } else { + PrintError.print(line, column, "type mismatch in assign statement"); + } + break; + case Block: + s_list.checkStatements(m); + break; + case If: + if (e_first.exprType(m)==MIdentifier.boolType) { + s_first.checkStatement(m); + s_second.checkStatement(m); + } else { + PrintError.print(line, column, "invalid type in if statement."); + } + break; + case Print: + if (e_first.exprType(m)!=null) { + return; + } else { + PrintError.print(line, column, "Invalid type in print statement"); + } + break; + case While: + // while (expr) state + if (e_first.exprType(m)==MIdentifier.boolType) { + s_first.checkStatement(m); + } else { + PrintError.print(line, column, "invalid type in while statement."); + } + break; + default: + break; + + } + + } + public void printStatement(int spaces) { String sp = OutputFormat.spaces(spaces); @@ -31,17 +91,31 @@ public class MStatement extends MType { System.err.println(")"); break; case ArrAssign: - System.err.println(sp+"[]="); + System.err.println(sp+"[]= ("+s_id.getName()+") ("); + e_first.printExpr(0); + System.err.print(") ("); + e_second.printExpr(0); + System.err.println(")"); break; case If: - System.err.println(sp+"if"); + System.err.println(sp+"if ("); + e_first.printExpr(0); + System.err.println(")"); + s_first.printStatement(spaces+2); + s_second.printStatement(spaces+2); break; case While: - System.err.println(sp+"while"); + System.err.println(sp+"while ("); + e_first.printExpr(0); + System.err.println(")"); + s_first.printStatement(spaces+2); break; case Print: - System.err.println(sp+"print"); + System.err.println(sp+"print ("); + e_first.printExpr(0); + System.err.println(")"); break; } } + } diff --git a/src/minijava/symboltable/MStatementList.java b/src/minijava/symboltable/MStatementList.java index 034bc8b..3cb3b02 100644 --- a/src/minijava/symboltable/MStatementList.java +++ b/src/minijava/symboltable/MStatementList.java @@ -23,4 +23,11 @@ public class MStatementList extends MType { s_list.elementAt(i).printStatement(spaces); } } + + public void checkStatements(MMethod m) { + for (int i=0; i { PrintError.print(m_class.getLine(), m_class.getColumn(), error_msg); // 往main class中添加main方法 - MMethod main_method = new MMethod("main", "void", n.f6.beginLine, n.f6.beginColumn); + MMethod main_method = new MMethod("main", MIdentifier.voidType, + n.f6.beginLine, n.f6.beginColumn); MIdentifier argid = (MIdentifier) n.f11.accept(this, null); - MVariable param = new MVariable(argid.getName(), "String[]", + MVariable param = new MVariable(argid.getName(), MIdentifier.sArrayType, argid.getLine(), argid.getColumn()); main_method.addParam(param); m_class.insertMethod(main_method); @@ -247,7 +248,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { MClass m_class = (MClass)argu; String ret_type = n.f1.accept(this, null).getName(); String method_name = n.f2.accept(this, null).getName(); - MMethod m_method = new MMethod(method_name, ret_type, n.f2.f0.beginLine, n.f2.f0.beginColumn); + MMethod m_method = new MMethod(method_name, ret_type, + n.f2.f0.beginLine, n.f2.f0.beginColumn); // 将定义的方法插入类中,如果出错则打印错误信息 String _err = m_class.insertMethod(m_method); @@ -364,7 +366,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f2 -> "}" */ public MType visit(Block n, MType argu) { - MStatement s = new MStatement(MStatement.Keyword.Block); + MStatement s = new MStatement(n.f0.beginLine, n.f0.beginColumn, + MStatement.Keyword.Block); s.s_list = new MStatementList(); if (argu!=null) { // should be a statement list ((MStatementList)argu).addStatement(s); @@ -381,8 +384,10 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { */ public MType visit(AssignmentStatement n, MType argu) { MStatementList m_list = (MStatementList) argu; - MStatement s = new MStatement(MStatement.Keyword.Assign); - s.s_id = (MIdentifier) n.f0.accept(this, null); + MIdentifier st_id = (MIdentifier) n.f0.accept(this, null); + MStatement s = new MStatement(st_id.getLine(), st_id.getColumn(), + MStatement.Keyword.Assign); + s.s_id = st_id; s.e_first = (MExpression) n.f2.accept(this, null); if (m_list!=null) { // a statement list m_list.addStatement(s); @@ -401,8 +406,10 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { */ public MType visit(ArrayAssignmentStatement n, MType argu) { MStatementList m_list = (MStatementList) argu; - MStatement s = new MStatement(MStatement.Keyword.ArrAssign); - s.s_id = (MIdentifier) n.f0.accept(this, null); + MIdentifier st_id = (MIdentifier) n.f0.accept(this, null); + MStatement s = new MStatement(st_id.getLine(), st_id.getColumn(), + MStatement.Keyword.ArrAssign); + s.s_id = st_id; s.e_first = (MExpression) n.f2.accept(this, null); s.e_second = (MExpression) n.f5.accept(this, null); if (m_list!=null) { // a statement list @@ -422,7 +429,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { */ public MType visit(IfStatement n, MType argu) { MStatementList m_list = (MStatementList) argu; - MStatement s = new MStatement(MStatement.Keyword.If); + MStatement s = new MStatement(n.f0.beginLine, n.f0.beginColumn, + MStatement.Keyword.If); s.e_first = (MExpression) n.f2.accept(this, null); s.s_first = (MStatement) n.f4.accept(this, null); s.s_second = (MStatement) n.f6.accept(this, null); @@ -441,7 +449,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { */ public MType visit(WhileStatement n, MType argu) { MStatementList m_list = (MStatementList)argu; - MStatement s = new MStatement(MStatement.Keyword.While); + MStatement s = new MStatement(n.f0.beginLine, n.f0.beginColumn, + MStatement.Keyword.While); s.e_first = (MExpression) n.f2.accept(this, null); s.s_first = (MStatement) n.f4.accept(this, null); if (m_list!=null) { @@ -459,7 +468,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { */ public MType visit(PrintStatement n, MType argu) { MStatementList m_list = (MStatementList)argu; - MStatement s = new MStatement(MStatement.Keyword.Print); + MStatement s = new MStatement(n.f0.beginLine, n.f0.beginColumn, + MStatement.Keyword.Print); s.e_first = (MExpression) n.f2.accept(this, null); if (m_list!=null) { m_list.addStatement(s); @@ -488,7 +498,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f2 -> PrimaryExpression() */ public MType visit(AndExpression n, MType argu) { - MExpression e = new MExpression(MExpression.Operator.And); + MExpression e = new MExpression(n.f1.beginLine, n.f1.beginColumn, + MExpression.Operator.And); e.first = (MExpression) n.f0.accept(this, null); e.second = (MExpression) n.f2.accept(this, null); if (argu!=null) { @@ -503,7 +514,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f2 -> PrimaryExpression() */ public MType visit(CompareExpression n, MType argu) { - MExpression e = new MExpression(MExpression.Operator.Smaller); + MExpression e = new MExpression(n.f1.beginLine, n.f1.beginColumn, + MExpression.Operator.Smaller); e.first = (MExpression) n.f0.accept(this, null); e.second = (MExpression) n.f2.accept(this, null); if (argu!=null) { @@ -518,7 +530,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f2 -> PrimaryExpression() */ public MType visit(PlusExpression n, MType argu) { - MExpression e = new MExpression(MExpression.Operator.Plus); + MExpression e = new MExpression(n.f1.beginLine, n.f1.beginColumn, + MExpression.Operator.Plus); e.first = (MExpression) n.f0.accept(this, null); e.second = (MExpression) n.f2.accept(this, null); if (argu!=null) { @@ -533,7 +546,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f2 -> PrimaryExpression() */ public MType visit(MinusExpression n, MType argu) { - MExpression e = new MExpression(MExpression.Operator.Minus); + MExpression e = new MExpression(n.f1.beginLine, n.f1.beginColumn, + MExpression.Operator.Minus); e.first = (MExpression) n.f0.accept(this, null); e.second = (MExpression) n.f2.accept(this, null); if (argu!=null) { @@ -548,7 +562,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f2 -> PrimaryExpression() */ public MType visit(TimesExpression n, MType argu) { - MExpression e = new MExpression(MExpression.Operator.Times); + MExpression e = new MExpression(n.f1.beginLine, n.f1.beginColumn, + MExpression.Operator.Times); e.first = (MExpression) n.f0.accept(this, null); e.second = (MExpression) n.f2.accept(this, null); if (argu!=null) { @@ -564,7 +579,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f3 -> "]" */ public MType visit(ArrayLookup n, MType argu) { - MExpression e = new MExpression(MExpression.Operator.ArrayLookup); + MExpression e = new MExpression(n.f1.beginLine, n.f1.beginColumn, + MExpression.Operator.ArrayLookup); e.first = (MExpression) n.f0.accept(this, null); e.second = (MExpression) n.f2.accept(this, null); if (argu!=null) { @@ -579,7 +595,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f2 -> "length" */ public MType visit(ArrayLength n, MType argu) { - MExpression e = new MExpression(MExpression.Operator.ArrayLen); + MExpression e = new MExpression(n.f1.beginLine, n.f1.beginColumn, + MExpression.Operator.ArrayLen); e.first = (MExpression) n.f0.accept(this, null); if (argu!=null) { ((MExpressionList)argu).add_expr(e); @@ -596,7 +613,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f5 -> ")" */ public MType visit(MessageSend n, MType argu) { - MExpression e = new MExpression(MExpression.Operator.MsgSend); + MExpression e = new MExpression(n.f1.beginLine, n.f1.beginColumn, + MExpression.Operator.MsgSend); e.first = (MExpression) n.f0.accept(this, null); e.e_id = (MIdentifier) n.f2.accept(this, null); // 将表达式列表的内容添加至e.e_list @@ -638,7 +656,8 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * | BracketExpression() */ public MType visit(PrimaryExpression n, MType argu) { - MExpression e = new MExpression(MExpression.Operator.Primary); + // FIXME: cannot get line and column + MExpression e = new MExpression(0, 0, MExpression.Operator.Primary); n.f0.accept(this, e.e_exp); if (argu!=null) { // a expression list ((MExpressionList)argu).add_expr(e); -- cgit v1.2.3