summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIru Cai <mytbk920423@gmail.com>2014-10-13 07:34:34 +0800
committerIru Cai <mytbk920423@gmail.com>2014-10-13 07:34:34 +0800
commit92f91d3e9bce1aaf581baa9339744266d7eb0c1a (patch)
treeb179091deae37958f92294a4079b65c5519c7752
parent31aac86103f0c05fbaaf1e690ec27b23cfeea9c0 (diff)
downloadminijava-92f91d3e9bce1aaf581baa9339744266d7eb0c1a.tar.xz
final version
-rw-r--r--src/minijava/symboltable/MClasses.java3
-rw-r--r--src/minijava/symboltable/MExpression.java17
-rw-r--r--src/minijava/symboltable/MMethod.java33
-rw-r--r--src/minijava/symboltable/MPrimaryExpr.java4
-rw-r--r--src/minijava/symboltable/MStatement.java22
-rw-r--r--src/minijava/typecheck/Main.java2
-rw-r--r--src/minijava/typecheck/PrintError.java10
-rw-r--r--src/minijava/visitor/BuildSymbolTableVisitor.java20
8 files changed, 93 insertions, 18 deletions
diff --git a/src/minijava/symboltable/MClasses.java b/src/minijava/symboltable/MClasses.java
index 10bd009..34601a5 100644
--- a/src/minijava/symboltable/MClasses.java
+++ b/src/minijava/symboltable/MClasses.java
@@ -46,6 +46,9 @@ public class MClasses extends MType {
String ext_name = m_class.extend_class_name;
if (ext_name!=null) {
m_class.extend_class = findClassByName(ext_name);
+ if (m_class.extend_class==null) {
+ PrintError.print(m_class.line, m_class.column, "Extend class not exist!");
+ }
}
}
int tag = 1; // 扫描循环继承的标记
diff --git a/src/minijava/symboltable/MExpression.java b/src/minijava/symboltable/MExpression.java
index 4cf4724..a5dc0ba 100644
--- a/src/minijava/symboltable/MExpression.java
+++ b/src/minijava/symboltable/MExpression.java
@@ -76,7 +76,15 @@ public class MExpression extends MType {
PrintError.print(line, column, "no class found in a message send expression");
return null;
}
- int idx = m_class.methods.findMethod(e_id.name);
+ int idx=-1;
+ while (m_class!=null) {
+ idx = m_class.methods.findMethod(e_id.name);
+ if (idx==-1) {
+ m_class = m_class.extend_class; // 本类无该方法,从父类继续找
+ } else {
+ break;
+ }
+ }
if (idx==-1) {
PrintError.print(line, column, "method " + e_id.name + " not found");
return null;
@@ -141,6 +149,13 @@ public class MExpression extends MType {
System.err.print("]");
case ArrayLen:
case MsgSend:
+ first.printExpr(0);
+ System.err.print("."+e_id.name+"(");
+ for (int i=0; i<e_list.size(); i++) {
+ if (i>0) System.err.print(",");
+ e_list.e_list.elementAt(i).printExpr(0);
+ }
+ System.err.print(")");
}
}
}
diff --git a/src/minijava/symboltable/MMethod.java b/src/minijava/symboltable/MMethod.java
index 2d2dc24..9e770a3 100644
--- a/src/minijava/symboltable/MMethod.java
+++ b/src/minijava/symboltable/MMethod.java
@@ -4,7 +4,7 @@ import minijava.typecheck.PrintError;
public class MMethod extends MLocalVarType {
MVarList params;
- String ret_type_name;
+ public String ret_type_name;
public MClass method_class;
MVarList paramList;
public MStatementList statements;
@@ -74,9 +74,10 @@ public class MMethod extends MLocalVarType {
if (idx!=-1) {
// 找到同名方法,检测是否能覆盖
if (this.ret_type_name.
- equals(m_class.methods.methods.elementAt(idx))==false) {
+ equals(m_class.methods.methods.elementAt(idx).ret_type_name)==false) {
PrintError.print(line, column, "Method " +
- this.name + " has type different from the one in its parent class");
+ this.name + " has type different from the one in its parent class "
+ + m_class.name);
return false;
}
}
@@ -95,15 +96,37 @@ public class MMethod extends MLocalVarType {
if (idx!=-1) {
return paramList.varlist.elementAt(idx);
}
- idx = method_class.vars.findVar(s);
+ MClass m_class = method_class;
+ idx = m_class.vars.findVar(s);
+ while (idx==-1 && m_class.extend_class!=null) {
+ // 在父类继续查找
+ m_class = m_class.extend_class;
+ idx = m_class.vars.findVar(s);
+ }
if (idx!=-1) {
- return method_class.vars.varlist.elementAt(idx);
+ return m_class.vars.varlist.elementAt(idx);
}
return null;
}
public void checkStatements() {
statements.checkStatements(this);
+ // 检查返回类型是否和返回值匹配
+ if (ret_type_name==MIdentifier.voidType && ret_expr==null) {
+ // ok
+ } else if (!ret_type_name.equals(ret_expr.exprType(this))) {
+ MClasses all = this.method_class.all_classes;
+ MClass t1 = all.findClassByName(ret_type_name);
+ MClass t2 = all.findClassByName(ret_expr.exprType(this));
+ if (t1!=null) {
+ while (t2!=null && t2!=t1) {
+ t2 = t2.extend_class;
+ }
+ }
+ if (t1!=t2) {
+ PrintError.print(line, column, "return expression and return type mismatch!");
+ }
+ }
}
public void printMethod(int spaces) {
diff --git a/src/minijava/symboltable/MPrimaryExpr.java b/src/minijava/symboltable/MPrimaryExpr.java
index ba233b5..246ac93 100644
--- a/src/minijava/symboltable/MPrimaryExpr.java
+++ b/src/minijava/symboltable/MPrimaryExpr.java
@@ -44,6 +44,10 @@ public class MPrimaryExpr extends MType {
case Alloc:
return e_id.getName();
case ArrayAlloc:
+ if (e_exp.exprType(m)!=MIdentifier.intType) {
+ PrintError.print(getLine(), getColumn(), "wrong type of expression in array alloc");
+ return null;
+ }
return MIdentifier.arrType;
case Braket:
return e_exp.exprType(m);
diff --git a/src/minijava/symboltable/MStatement.java b/src/minijava/symboltable/MStatement.java
index 3610719..5169097 100644
--- a/src/minijava/symboltable/MStatement.java
+++ b/src/minijava/symboltable/MStatement.java
@@ -36,13 +36,29 @@ public class MStatement extends MType {
case Assign:
// id = expr
MVariable m_var = m.findVarByName(s_id.name);
+ String expr_type = e_first.exprType(m);
+ //System.err.println(s_id.name + " " + expr_type);
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))) {
+ } else if (m_var.typename.equals(expr_type)) {
return;
} else {
- PrintError.print(line, column, "type mismatch in assign statement");
+ MClasses all = m.method_class.all_classes;
+ MClass id_class = all.findClassByName(m_var.typename);
+ MClass expr_class = all.findClassByName(expr_type);
+ if (id_class==null) { // id本身不是类
+ PrintError.print(line, column, "type mismatch in assign statement");
+ return;
+ }
+ while (expr_class!=id_class && expr_class!=null) { // 从expr的类找父类
+ expr_class = expr_class.extend_class;
+ }
+ if (expr_class!=id_class) {
+ PrintError.print(line, column, "type mismatch in assign statement");
+ } else {
+ return;
+ }
}
break;
case Block:
@@ -57,7 +73,7 @@ public class MStatement extends MType {
}
break;
case Print:
- if (e_first.exprType(m)!=null) {
+ if (e_first.exprType(m)==MIdentifier.intType) {
return;
} else {
PrintError.print(line, column, "Invalid type in print statement");
diff --git a/src/minijava/typecheck/Main.java b/src/minijava/typecheck/Main.java
index 1c069ba..0dbc2d8 100644
--- a/src/minijava/typecheck/Main.java
+++ b/src/minijava/typecheck/Main.java
@@ -43,6 +43,8 @@ public class Main {
// 打印错误信息
PrintError.printAll();
+
+ PrintError.outputResult();
} catch (TokenMgrError e) {
// Handle Lexical Errors
diff --git a/src/minijava/typecheck/PrintError.java b/src/minijava/typecheck/PrintError.java
index a5a5157..24754f9 100644
--- a/src/minijava/typecheck/PrintError.java
+++ b/src/minijava/typecheck/PrintError.java
@@ -17,7 +17,15 @@ public class PrintError {
public static void printAll() {
int sz = errors.size();
for (int i = 0; i < sz; i++) {
- System.out.println(errors.elementAt(i));
+ System.err.println(errors.elementAt(i));
+ }
+ }
+
+ public static void outputResult() {
+ if (errors.size()>0) {
+ System.out.println("Type error");
+ } else {
+ System.out.println("Program type checked successfully");
}
}
}
diff --git a/src/minijava/visitor/BuildSymbolTableVisitor.java b/src/minijava/visitor/BuildSymbolTableVisitor.java
index c99d0ab..4de3383 100644
--- a/src/minijava/visitor/BuildSymbolTableVisitor.java
+++ b/src/minijava/visitor/BuildSymbolTableVisitor.java
@@ -112,6 +112,7 @@ public class BuildSymbolTableVisitor extends GJDepthFirst<MType, MType> {
// 往main class中添加main方法
MMethod main_method = new MMethod("main", MIdentifier.voidType,
n.f6.beginLine, n.f6.beginColumn);
+ //main_method.ret_type_name = MIdentifier.voidType;
MIdentifier argid = (MIdentifier) n.f11.accept(this, null);
MVariable param = new MVariable(argid.getName(), MIdentifier.sArrayType,
argid.getLine(), argid.getColumn());
@@ -627,10 +628,12 @@ public class BuildSymbolTableVisitor extends GJDepthFirst<MType, MType> {
* f1 -> ( ExpressionRest() )*
*/
public MType visit(ExpressionList n, MType argu) {
- MType _ret=null;
- n.f0.accept(this, argu);
- n.f1.accept(this, argu);
- return _ret;
+ if (argu!=null) {
+ MExpressionList m_elist = (MExpressionList)argu;
+ m_elist.add_expr((MExpression)n.f0.accept(this,null));
+ n.f1.accept(this, m_elist);
+ }
+ return null;
}
/**
@@ -638,10 +641,11 @@ public class BuildSymbolTableVisitor extends GJDepthFirst<MType, MType> {
* f1 -> Expression()
*/
public MType visit(ExpressionRest n, MType argu) {
- MType _ret=null;
- n.f0.accept(this, argu);
- n.f1.accept(this, argu);
- return _ret;
+ if (argu!=null) {
+ MExpressionList m_elist = (MExpressionList)argu;
+ m_elist.add_expr((MExpression)n.f1.accept(this,null));
+ }
+ return null;
}
/**