diff options
author | bd-912 <bdunahu@colostate.edu> | 2024-03-16 22:06:32 -0600 |
---|---|---|
committer | bd-912 <bdunahu@colostate.edu> | 2024-03-16 22:06:32 -0600 |
commit | 6a24c69232901de51f50beab9c3d3b3760dee334 (patch) | |
tree | 70c71b9ec25d3f6085d71c83e2be3719fe638ae9 /minijava | |
parent | 5b09fb3697f4b1cc1f2f3781f10e1334ada69c22 (diff) |
(Nonfunctional) Implemented many type-checking rules
Diffstat (limited to 'minijava')
-rw-r--r-- | minijava/PPrinter.java | 5 | ||||
-rw-r--r-- | minijava/SymTableVis.java | 43 | ||||
-rw-r--r-- | minijava/TypeCheckSimp.java | 683 | ||||
-rw-r--r-- | minijava/TypeEnum.java | 5 | ||||
-rw-r--r-- | minijava/TypeInstance.java | 29 |
5 files changed, 761 insertions, 4 deletions
diff --git a/minijava/PPrinter.java b/minijava/PPrinter.java index 7dd484b..aed7ec4 100644 --- a/minijava/PPrinter.java +++ b/minijava/PPrinter.java @@ -1,8 +1,5 @@ -// -// Generated by JTB 1.3.2 -// - package minijava; + import syntaxtree.*; import visitor.*; import java.util.*; diff --git a/minijava/SymTableVis.java b/minijava/SymTableVis.java new file mode 100644 index 0000000..3d8003b --- /dev/null +++ b/minijava/SymTableVis.java @@ -0,0 +1,43 @@ +package minijava; + +import syntaxtree.*; +import visitor.*; +import java.util.*; + +/** + * Provides default methods which visit each node in the tree in depth-first + * order. Your visitors may extend this class. + */ +public class SymTableVis<R,A> implements GJVisitor<R,A> { + + public HashMap<String,String> symt = new HashMap<>(); + + private void print_filter(String message) { + boolean debug = true; + if (debug) + System.out.println(message); + } + + public R visit(VarDeclaraction n, A argu) { + R _ret=null; + + this.print_filter("Processing declaration"); + + String type = ""; + switch (n.f0.f0.which) { + case 2: + type = "Int"; break; + default: + this.print_filter("Unsupported case"); + } + + String id = n.f1.f0.tokenImage; + + this.printfilter("Inserting " + id + " => " + type); + // Safe? + symt.put(id, type); + + return _ret; + } + +} diff --git a/minijava/TypeCheckSimp.java b/minijava/TypeCheckSimp.java new file mode 100644 index 0000000..01f8b27 --- /dev/null +++ b/minijava/TypeCheckSimp.java @@ -0,0 +1,683 @@ +package minijava; + +import syntaxtree.*; +import visitor.*; +import java.util.*; + +/** + * Provides default methods which visit each node in the tree in depth-first + * order. Your visitors may extend this class. + */ +public class TypeCheckSimp implements GJVisitor<TypeInstance,HashMap<String,String>> { + + private void print_filter(String message) { + boolean debug = true; + if (debug) + System.out.println(message); + } + // + // Auto class visitors--probably don't need to be overridden. + // + public TypeInstance visit(NodeList n, HashMap<String,String> argu) { + TypeInstance _ret=null; + int _count=0; + for ( Enumeration<Node> e = n.elements(); e.hasMoreElements(); ) { + e.nextElement().accept(this,argu); + _count++; + } + return _ret; + } + + public TypeInstance visit(NodeListOptional n, HashMap<String,String> argu) { + if ( n.present() ) { + TypeInstance _ret=null; + int _count=0; + for ( Enumeration<Node> e = n.elements(); e.hasMoreElements(); ) { + e.nextElement().accept(this,argu); + _count++; + } + return _ret; + } + else + return null; + } + + public TypeInstance visit(NodeOptional n, HashMap<String,String> argu) { + if ( n.present() ) + return n.node.accept(this,argu); + else + return null; + } + + public TypeInstance visit(NodeSequence n, HashMap<String,String> argu) { + TypeInstance _ret=null; + int _count=0; + for ( Enumeration<Node> e = n.elements(); e.hasMoreElements(); ) { + e.nextElement().accept(this,argu); + _count++; + } + return _ret; + } + + public TypeInstance visit(NodeToken n, HashMap<String,String> argu) { return null; } + + // + // User-generated visitor methods below + // + + /** + * f0 -> MainClass() + * f1 -> ( TypeDeclaration() )* + * f2 -> <EOF> + */ + public TypeInstance visit(Goal n, HashMap<String,String> argu) { + TypeInstance ret = n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + return ret; + } + + /** + * f0 -> "class" + * f1 -> Identifier() + * f2 -> "{" + * f3 -> "public" + * f4 -> "static" + * f5 -> "void" + * f6 -> "main" + * f7 -> "(" + * f8 -> "String" + * f9 -> "[" + * f10 -> "]" + * f11 -> Identifier() + * f12 -> ")" + * f13 -> "{" + * f14 -> ( VarDeclaration() )* + * f15 -> ( Statement() )* + * f16 -> "}" + * f17 -> "}" + */ + public TypeInstance visit(MainClass n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance name = n.f1.accept(this, argu); + n.f2.accept(this, argu); + n.f3.accept(this, argu); + n.f4.accept(this, argu); + n.f5.accept(this, argu); + n.f6.accept(this, argu); + n.f7.accept(this, argu); + n.f8.accept(this, argu); + n.f9.accept(this, argu); + n.f10.accept(this, argu); + TypeInstance args = n.f11.accept(this, argu); + n.f12.accept(this, argu); + n.f13.accept(this, argu); + TypeInstance var_dec = n.f14.accept(this, argu); + TypeInstance stmt = n.f15.accept(this, argu); + n.f16.accept(this, argu); + n.f17.accept(this, argu); + return stmt; + } + + /** + * f0 -> ClassDeclaration() + * | ClassExtendsDeclaration() + */ + public TypeInstance visit(TypeDeclaration n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> "class" + * f1 -> Identifier() + * f2 -> "{" + * f3 -> ( VarDeclaration() )* + * f4 -> ( MethodDeclaration() )* + * f5 -> "}" + */ + public TypeInstance visit(ClassDeclaration n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + n.f3.accept(this, argu); + n.f4.accept(this, argu); + n.f5.accept(this, argu); + return _ret; + } + + /** + * f0 -> "class" + * f1 -> Identifier() + * f2 -> "extends" + * f3 -> Identifier() + * f4 -> "{" + * f5 -> ( VarDeclaration() )* + * f6 -> ( MethodDeclaration() )* + * f7 -> "}" + */ + public TypeInstance visit(ClassExtendsDeclaration n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + n.f3.accept(this, argu); + n.f4.accept(this, argu); + n.f5.accept(this, argu); + n.f6.accept(this, argu); + n.f7.accept(this, argu); + return _ret; + } + + // FIXME + /** + * f0 -> Type() + * f1 -> Identifier() + * f2 -> ";" + */ + public TypeInstance visit(VarDeclaration n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + return new TypeInstance(TypeEnum.CHECK); + } + + /** + * f0 -> "public" + * f1 -> Type() + * f2 -> Identifier() + * f3 -> "(" + * f4 -> ( FormalParameterList() )? + * f5 -> ")" + * f6 -> "{" + * f7 -> ( VarDeclaration() )* + * f8 -> ( Statement() )* + * f9 -> "return" + * f10 -> Expression() + * f11 -> ";" + * f12 -> "}" + */ + public TypeInstance visit(MethodDeclaration n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + n.f3.accept(this, argu); + n.f4.accept(this, argu); + n.f5.accept(this, argu); + n.f6.accept(this, argu); + n.f7.accept(this, argu); + n.f8.accept(this, argu); + n.f9.accept(this, argu); + n.f10.accept(this, argu); + n.f11.accept(this, argu); + n.f12.accept(this, argu); + return _ret; + } + + /** + * f0 -> FormalParameter() + * f1 -> ( FormalParameterRest() )* + */ + public TypeInstance visit(FormalParameterList n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + return _ret; + } + + /** + * f0 -> Type() + * f1 -> Identifier() + */ + public TypeInstance visit(FormalParameter n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + return _ret; + } + + /** + * f0 -> "," + * f1 -> FormalParameter() + */ + public TypeInstance visit(FormalParameterRest n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + return _ret; + } + + /** + * f0 -> ArrayType() + * | BooleanType() + * | IntegerType() + * | Identifier() + */ + public TypeInstance visit(Type n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> "int" + * f1 -> "[" + * f2 -> "]" + */ + public TypeInstance visit(ArrayType n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + return new TypeInstance(TypeEnum.int_array); + } + + /** + * f0 -> "boolean" + */ + public TypeInstance visit(BooleanType n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> "int" + */ + public TypeInstance visit(IntegerType n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> Block() + * | AssignmentStatement() + * | ArrayAssignmentStatement() + * | IfStatement() + * | WhileStatement() + * | PrintStatement() + */ + public TypeInstance visit(Statement n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> "{" + * f1 -> ( Statement() )* + * f2 -> "}" + */ + public TypeInstance visit(Block n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + n.f2.accept(this, argu); + return ret; + } + + /** + * f0 -> Identifier() + * f1 -> "=" + * f2 -> Expression() + * f3 -> ";" + */ + public TypeInstance visit(AssignmentStatement n, HashMap<String,String> argu) { + TypeInstance lhs = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance rhs = n.f2.accept(this, argu); + n.f3.accept(this, argu); + return (lhs.equal_type(rhs)) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> Identifier() + * f1 -> "[" + * f2 -> Expression() //int + * f3 -> "]" + * f4 -> "=" + * f5 -> Expression() //int + * f6 -> ";" + */ + public TypeInstance visit(ArrayAssignmentStatement n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance index = n.f2.accept(this, argu); + n.f3.accept(this, argu); + n.f4.accept(this, argu); + TypeInstance value = n.f5.accept(this, argu); + n.f6.accept(this, argu); + return (index.get_type() == TypeEnum.integer && + value.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "if" + * f1 -> "(" + * f2 -> Expression() + * f3 -> ")" + * f4 -> Statement() + * f5 -> "else" + * f6 -> Statement() + */ + public TypeInstance visit(IfStatement n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance expr = n.f2.accept(this, argu); + n.f3.accept(this, argu); + TypeInstance stmt1 = n.f4.accept(this, argu); + n.f5.accept(this, argu); + TypeInstance stmt2 = n.f6.accept(this, argu); + return (expr.get_type() == TypeEnum.bool && + stmt1.get_type() == stmt2.get_type() == TypeEnum.CHECK) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "while" + * f1 -> "(" + * f2 -> Expression() + * f3 -> ")" + * f4 -> Statement() + */ + public TypeInstance visit(WhileStatement n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance expr = n.f2.accept(this, argu); + n.f3.accept(this, argu); + TypeInstance stmt = n.f4.accept(this, argu); + return (expr.get_type() == TypeEnum.bool && + stmt.get_type() == TypeEnum.CHECK) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "System.out.println" + * f1 -> "(" + * f2 -> Expression() + * f3 -> ")" + * f4 -> ";" + */ + public TypeInstance visit(PrintStatement n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance ret = n.f2.accept(this, argu); + n.f3.accept(this, argu); + n.f4.accept(this, argu); + return (ret.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> AndExpression() + * | CompareExpression() + * | PlusExpression() + * | MinusExpression() + * | TimesExpression() + * | ArrayLookup() + * | ArrayLength() + * | MessageSend() + * | PrimaryExpression() + */ + public TypeInstance visit(Expression n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> PrimaryExpressionppp() + * f1 -> "&&" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(AndExpression n, HashMap<String,String> argu) { + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.bool && + oper2.get_type() == TypeEnum.bool) ? + new TypeInstance(TypeEnum.bool) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "<" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(CompareExpression n, HashMap<String,String> argu) { + TypeInstance _ret=null; + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.integer && + oper2.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.bool) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "+" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(PlusExpression n, HashMap<String,String> argu) { + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.integer && + oper2.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "-" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(MinusExpression n, HashMap<String,String> argu) { + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.integer && + oper2.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "*" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(TimesExpression n, HashMap<String,String> argu) { + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.integer && + oper2.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "[" + * f2 -> PrimaryExpression() + * f3 -> "]" + */ + public TypeInstance visit(ArrayLookup n, HashMap<String,String> argu) { + TypeInstance _ret=null; + TypeInstance array = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance index = n.f2.accept(this, argu); + n.f3.accept(this, argu); + return (array.get_type() == TypeEnum.int_array && + index.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "." + * f2 -> "length" + */ + public TypeInstance visit(ArrayLength n, HashMap<String,String> argu) { + // can only act on an array + TypeInstance _ret=null; + TypeInstance ret = n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + return (ret.get_type() == TypeEnum.int_array) ? new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "." + * f2 -> Identifier() + * f3 -> "(" + * f4 -> ( ExpressionList() )? + * f5 -> ")" + */ + public TypeInstance visit(MessageSend n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + n.f3.accept(this, argu); + n.f4.accept(this, argu); + n.f5.accept(this, argu); + return _ret; + } + + // FIXME + /** + * f0 -> Expression() + * f1 -> ( ExpressionRest() )* + */ + public TypeInstance visit(ExpressionList n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + return _ret; + } + + /** + * f0 -> "," + * f1 -> Expression() + */ + public TypeInstance visit(ExpressionRest n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + return ret; + } + + /** + * f0 -> IntegerLiteral() + * | TrueLiteral() + * | FalseLiteral() + * | Identifier() + * | ThisExpression() + * | ArrayAllocationExpression() + * | AllocationExpression() + * | NotExpression() + * | BracketExpression() + */ + public TypeInstance visit(PrimaryExpression n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> <INTEGER_LITERAL> + */ + public TypeInstance visit(IntegerLiteral n, HashMap<String,String> argu) { + return new TypeInstance(TypeEnum.integer); + } + + /** + * f0 -> "true" + */ + public TypeInstance visit(TrueLiteral n, HashMap<String,String> argu) { + return new TypeInstance(TypeEnum.bool); + } + + /** + * f0 -> "false" + */ + public TypeInstance visit(FalseLiteral n, HashMap<String,String> argu) { + return new TypeInstance(TypeEnum.bool); + } + + /** + * f0 -> <IDENTIFIER> + */ + public TypeInstance visit(Identifier n, HashMap<String,String> argu) { + return new TypeInstance(TypeEnum.CHECK); + } + + //FIXME + /** + * f0 -> "this" + */ + public TypeInstance visit(ThisExpression n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + return _ret; + } + + /** + * f0 -> "new" + * f1 -> "int" + * f2 -> "[" + * f3 -> Expression() + * f4 -> "]" + */ + public TypeInstance visit(ArrayAllocationExpression n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + n.f2.accept(this, argu); + n.f3.accept(this, argu); + n.f4.accept(this, argu); + return (ret.get_type() == TypeEnum.integer) ? new TypeInstance(TypeEnum.int_array) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "new" + * f1 -> Identifier() + * f2 -> "(" + * f3 -> ")" + */ + public TypeInstance visit(AllocationExpression n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + n.f2.accept(this, argu); + n.f3.accept(this, argu); + return ret; + } + + /** + * f0 -> "!" + * f1 -> Expression() + */ + public TypeInstance visit(NotExpression n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + return (ret.get_type() == TypeEnum.bool) ? ret : new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "(" + * f1 -> Expression() + * f2 -> ")" + */ + public TypeInstance visit(BracketExpression n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + n.f2.accept(this, argu); + return ret; + } + +} diff --git a/minijava/TypeEnum.java b/minijava/TypeEnum.java new file mode 100644 index 0000000..4003eba --- /dev/null +++ b/minijava/TypeEnum.java @@ -0,0 +1,5 @@ +package minijava; + +public enum TypeEnum { + int_array, bool, integer, CHECK, ERROR +} diff --git a/minijava/TypeInstance.java b/minijava/TypeInstance.java new file mode 100644 index 0000000..13920e4 --- /dev/null +++ b/minijava/TypeInstance.java @@ -0,0 +1,29 @@ +package minijava; + +public class TypeInstance { + TypeEnum type; + + public TypeInstance(TypeEnum type) { + this.type = type; + } + + public boolean equal_type(TypeInstance other) { + /** + * Given a TypeInstance object other, + * returns true if other object + * is the same type as this one. + * + * We can say two types are equal, as + * long as they are not equal on a + * type error! + */ + + return this.type != TypeEnum.ERROR + this.type == other.type; + } + + public TypeEnum get_type() { + return this.type; + } + +} |