Hobbit Storry
Hobbit Storry
checker
/**
* Student name:Nguyen Danh Khoi
* Student ID:51301905
*/
import
import
import
import
import
import
import
bkool.parser._
bkool.utils._
java.io.{PrintWriter, File}
org.antlr.v4.runtime.ANTLRFileStream;
org.antlr.v4.runtime.CommonTokenStream;
org.antlr.v4.runtime.tree._
scala.collection.JavaConverters._
class StaticChecker(ast:AST) {
case class SaveClassList(list:List[(String,String,List[(String,Type,Kind,SIKin
d,Boolean)])]) extends Context
case class SaveList(list:List[(String,Type,Kind,SIKind,Boolean)]) extends Cont
ext
def check() = {
val global = new GlobalEnvironment()
val en = global.visitProgram(ast.asInstanceOf[Program],null).asInstanceOf
[List[(String,String,List[(String,Type,Kind,SIKind,Boolean)])]]
val sec = new SecondCheck(en)
val en2 = sec.visitProgram(ast.asInstanceOf[Program], null).asInstanceOf[
List[(String,Type,Kind,SIKind,Boolean)]]
}
trait Utils {
object notValidType extends Type
def UnaryType(a : Any, b : String ) : Type =
(a,b) match{
case (FloatType,"+"|"-")=> FloatType
case (IntType,"+"|"-") => IntType
case (BoolType,"!") => BoolType
case (_,_) => notValidType
}
def check_Is_Const (a :Any , b : Any): Boolean = (a,b) match {
case (true,true)=>true
case (_,_)=>false
}
def BinaryExpGetType(a : Any , c : Any , b : String): Type =(a,b,c) match
{
case
case
case
case
case
case
case
case
case
case
case
case
case
}
if (listpa.get._2 != "" ) {
if (lstnewclass.exists(x=>x == listpa.get._2)) listpa.get._3
else {
listpa.get._3++searchClass(listpa.get._2,listpa.get._2::lstnewclass,list
)
}
}
else listpa.get._3
}
def check_Is_Const(classs:String, name:String, list:List[(String,String,List[(
String,Type,Kind,SIKind,Boolean)])]):Boolean = {
val a = list find {e => e._1 == classs}
if (a.get._2 != "")
{
val b = a.get._3++searchClass(a.get._2,List(),list)
b.exists(x=>x._1 == name && x._4 == Static && x._5 == true)
}
else {
a.get._3.exists(x=>x._1 == name && x._4 == Static && x._5 == true)
}
}
}
class GlobalEnvironment extends Visitor with Utils {
override def visitClassDecl(ast: ClassDecl, c: Context) = {
val env = c.asInstanceOf[SaveClassList].list
if (env.exists(x=>x._1==ast.name.name)) throw Redeclared(Class,ast.name.na
me)
else {
(
ast.name.name,
ast.parent.name,
ast.decl.foldLeft(List[(String,Type,Kind,SIKind,Boolean)]())
(
(x,y) => y match
{
case MethodDecl(a,b,c,d,e) =>
visit(y.asInstanceOf[MethodDecl],SaveList(x)).asInstance
Of[List[(String,Type,Kind,SIKind,Boolean)]]
case AttributeDecl(a,b)
=>
visit(y.asInstanceOf[AttributeDecl],SaveList(x)).asInsta
nceOf[List[(String,Type,Kind,SIKind,Boolean)]]
}
)
)::env
}
}
override def visitMethodDecl(ast: MethodDecl, c: Context) = {
val env = c.asInstanceOf[SaveList].list
if (env.exists(x=>x._1==ast.name.name)) throw Redeclared(Method,ast.name.
name)
else (ast.name.name,ast.returnType,Method,ast.kind, false)::env
}
override def visitAttributeDecl(ast: AttributeDecl, c: Context) = {
val env = c.asInstanceOf[SaveList].list
ast.decl match {
case VarDecl(a,b) =>
if (env.exists(x=>x._1==ast.decl.asInstanceOf[VarDecl].variable.n
ame))
throw Redeclared(Attribute,ast.decl.asInstanceOf[VarDecl].var
iable.name)
else (ast.decl.asInstanceOf[VarDecl].variable.name,ast.decl.asIns
tanceOf[VarDecl].varType, Attribute, if(ast.kind == Static) Static else Instance
,false)::env
case ConstDecl(a,b,c) =>
if (env.exists(x=>x._1==ast.decl.asInstanceOf[ConstDecl].id.name)
)
throw Redeclared(Attribute,ast.decl.asInstanceOf[ConstDecl].i
d.name)
else (ast.decl.asInstanceOf[ConstDecl].id.name,ast.decl.asInstanc
eOf[ConstDecl].constType, Attribute, if(ast.kind == Static) Static else Instance
,true)::env
}
}
override def visitProgram(ast:Program, c:Context) = {
var ioList = List[(String,Type,Kind,SIKind,Boolean)](
("readInt",IntType,Method,Static,false),
("writeInt",VoidType,Method,Static,false),
("writeIntLn",VoidType,Method,Static,false),
("readFloat",FloatType,Method,Static,false),
("writeFloat",VoidType,Method,Static,false),
("writeFloatLn",VoidType,Method,Static,false),
("readBool",BoolType,Method,Static,false),
("writeBool",VoidType,Method,Static,false),
("writeBoolLn",VoidType,Method,Static,false),
("readStr",StringType,Method,Static,false),
("writeStr",VoidType,Method,Static,false),
("writeStrLn",VoidType,Method,Static,false)
)
ast.decl.foldLeft(List[(String,String,List[(String,Type,Kind,SIKind,Bool
ean)])](("io","",ioList)))((x,y) =>
visit(y,SaveClassList(x)).asInstanceOf[List[(String,String,List[(String,
Type,Kind,SIKind,Boolean)])]])
}
override
override
override
override
override
override
override
override
override
override
override
override
override
override
override
override
override
override
override
override
override
override
override
def
def
def
def
def
def
def
def
def
def
def
def
def
def
def
def
def
def
def
def
def
def
def
override
override
override
override
override
override
override
override
override
override
def
def
def
def
def
def
def
def
def
def
}
class SecondCheck(genv:List[(String,String,List[(String,Type,Kind,SIKind,Boo
lean)])]) extends Visitor with Utils {
override def visitProgram(ast: Program, c: Context) = ast.decl.map(visit(
_,c))
override def visitVarDecl(ast: VarDecl, c: Context) = {
val env = c.asInstanceOf[SaveList].list
val t = visit(ast.varType,c).asInstanceOf[Type]
if (env.exists(x=>x._1==ast.variable.name))
throw Redeclared(Variable,ast.variable.name)
else (ast.variable.name,t,Variable,null,false)::env
}
override def visitConstDecl(ast: ConstDecl, c: Context) = {
val env = c.asInstanceOf[SaveList].list
val t = visit(ast.constType,c).asInstanceOf[Type]
if (env.exists(x=>x._1==ast.id.name))
throw Redeclared(Constant,ast.id.name)
else (ast.id.name,t,Constant,null,true)::env
}
override def visitParamDecl(ast: ParamDecl, c: Context) = {
val env = c.asInstanceOf[SaveList].list
val t = visit(ast.paramType,c).asInstanceOf[Type]
if (env.exists(x=>x._1==ast.id.name))
throw Redeclared(Parameter,ast.id.name)
else (ast.id.name,t,Parameter,null,false)::env
}
override def visitClassDecl(ast: ClassDecl, c: Context) = {
if (ast.parent.name != "")
if (!genv.exists(x => x._1==ast.parent.name))
throw Undeclared(Class,ast.parent.name)
val listparent = searchClass(ast.name.name,List(),genv)
ast.decl.filter(_.isInstanceOf[AttributeDecl]).map(visit(_,SaveList(listpare
nt)))
ast.decl.filter(_.isInstanceOf[MethodDecl]).map(visit(_,SaveList(listparent)
))
}
override def visitMethodDecl(ast: MethodDecl, c: Context) = {
val env = c.asInstanceOf[SaveList].list
if(ast.returnType != null) visit(ast.returnType,c)
val locenv = ast.param.foldLeft(List[(String,Type,Kind,SIKind,Boolean)]())((
x,y)=>visit(y,SaveList(x)).asInstanceOf[List[(String,Type,Kind,SIKind,Boolean)]]
)
visitOtherBlock(ast.body.asInstanceOf[Block],SaveList(env),SaveList(locenv))
.asInstanceOf[List[(String,Type,Kind,SIKind,Boolean)]]
}
override def visitAttributeDecl(ast: AttributeDecl, c: Context) = {
ast.decl match {
case VarDecl(a,b) => visit(ast.decl.asInstanceOf[VarDecl].varType,c)
case ConstDecl(a,b,cc) => visit(ast.decl.asInstanceOf[ConstDecl].constT
ype,c)
}
}
override def visitInstance(ast: Instance.type, c: Context) = c
override def visitStatic(ast: Static.type, c: Context) = c
override def visitIntType(ast: IntType.type, c: Context) = IntType
override def visitFloatType(ast: FloatType.type, c: Context) = FloatType
override def visitBoolType(ast: BoolType.type, c: Context) = BoolType
override def visitStringType(ast: StringType.type, c: Context) = StringType
override def visitVoidType(ast: VoidType.type, c: Context) = VoidType
override def visitArrayType(ast: ArrayType, c: Context) = visit(ast.eleType,c
)
override def visitClassType(ast: ClassType, c: Context) = {
if (!genv.exists(x=>x._1==ast.classType))
throw Undeclared(Class,ast.classType)
else ast
}
override def visitBinaryOp(ast: BinaryOp, c: Context) = {
val l = visit(ast.left,c)
val l1 = l match {
case(a,b)=> a
}
val l2 = l match {
case(a,b)=> b
}
val r = visit(ast.right,c)
val r1 = r match {
case(a,b)=> a
}
val r2 = r match {
case(a,b)=> b
}
val finall = check_Is_Const(l2,r2)
val op = ast.op
val t = BinaryExpGetType (l1,r1,op)
t match {
case notValidType => throw TypeMismatchInExpression(ast)
case _ => (t,finall)
}
}
override def visitUnaryOp(ast: UnaryOp, c: Context) =
{
val t = visit(ast.body,c)
val ttype = t match {
case (a,b)=>a
}
val op = t match {
case (a,b) => b
}
.method.name,genv)
if (!check._1) throw Undeclared(Method,ast.method.name)
else check._2
}
else null
}
}
ast.params.map(visit(_,c))
}
override def visitId(ast: Id, c: Context) = {
val env = c.asInstanceOf[SaveList].list
if (!env.exists(x => x._1 == ast.name && x._3 != Attribute && x._3 != Method
))
throw Undeclared(Identifier,ast.name)
null
}
override def visitArrayCell(ast: ArrayCell, c: Context) = {
visit(ast.arr,c)
visit(ast.idx,c)
}
override def visitFieldAccess(ast: FieldAccess, c: Context) = {
if (ast.name == SelfLiteral){
val env = c.asInstanceOf[SaveList].list
if (!env.exists(x=>x._1==ast.field.name && x._3 == Attribute))
throw Undeclared(Attribute,ast.field.name)
else (env find (x=>x._1==ast.field.name && x._3 == Attribute)).get._2
}
else{
if(ast.name.isInstanceOf[Id]== true){
val env = c.asInstanceOf[SaveList].list
val a = find_ID(ast.name.asInstanceOf[Id].name,env)
if (a != null)
{
if (a._2.isInstanceOf[ClassType]){
val check = find_Member(Attribute,a._2.asInstanceOf[ClassType].class
Type,ast.field.name,genv)
if (!check._1)throw Undeclared(Attribute,ast.field.name)
else check._2
}
else null //asas
}
else{
if (genv.exists(x=>x._1==ast.name.asInstanceOf[Id].name)) {
val check = find_Member(Attribute,ast.name.asInstanceOf[Id].name,ast
.field.name,genv)
if (!check._1) throw Undeclared(Attribute,ast.field.name)
else check._2
}
else throw Undeclared(Identifier,ast.name.asInstanceOf[Id].name) //KBI
L
}
}
else {
val t = visit(ast.name,c)
if (t.isInstanceOf[ClassType]){
val check = find_Member(Attribute,t.asInstanceOf[ClassType].classType,
ast.field.name,genv)
if (!check._1)throw Undeclared(Attribute,ast.field.name)
else check._2
}
else null
}
}
}
override def visitBlock(ast: Block, c: Context) =
{
val env = c.asInstanceOf[SaveList].list
val locenv = ast.decl.foldLeft(List[(String,Type,Kind,SIKind,Boolean)]())((x
,y)
=>visit(y,SaveList(x)).asInstanceOf[List[(String,Type,Kind,SIKind,Boolea
n)]])
ast.stmt.map(visit(_,SaveList(locenv++env)))
}
def visitOtherBlock(ast: Block, c: Context, c2: Context) = {
val env = c.asInstanceOf[SaveList].list
val env2 = c2.asInstanceOf[SaveList].list
val locenv = ast.decl.foldLeft(env2)((x,y)=>visit(y,SaveList(x)).asInstanceO
f[List[(String,Type,Kind,SIKind,Boolean)]])
ast.stmt.map(visit(_,SaveList(locenv++env)))
}
override def visitAssign(ast: Assign, c: Context)= {
val env = c.asInstanceOf[SaveList].list
if(ast.leftHandSide.isInstanceOf[Id]) {
//if (env.exists(x=>x._1==ast.leftHandSide.asInstanceOf[Id].name && x._5 =
= true))
//throw CannotAssignToConstant(ast)
if (!env.exists(x=>x._1==ast.leftHandSide.asInstanceOf[Id].name && x._3 !=
Method && x._3 != Attribute))
throw Undeclared(Identifier,ast.leftHandSide.asInstanceOf[Id].name)
//Cannot assign constant
}
else if(ast.leftHandSide.isInstanceOf[FieldAccess]) {
if (ast.leftHandSide.asInstanceOf[FieldAccess].name == SelfLiteral){
val env = c.asInstanceOf[SaveList].list
if (!env.exists(x=>x._1 == ast.leftHandSide.asInstanceOf[FieldAccess].fi
eld.name && x._3 == Attribute))
throw Undeclared(Attribute,ast.leftHandSide.asInstanceOf[FieldAccess].
field.name)
//Cannot assign constant
//if (env.exists(x=>x._1 == ast.leftHandSide.asInstanceOf[FieldAccess].f
ield.name && x._5 == true))
//throw CannotAssignToConstant(ast)
}
else{
if (ast.leftHandSide.asInstanceOf[FieldAccess].name.isInstanceOf[Id])
{
val lhs = ast.leftHandSide.asInstanceOf[FieldAccess]
val env = c.asInstanceOf[SaveList].list
val a = find_ID(lhs.name.asInstanceOf[Id].name,env)
if (a != null)
{
if (a._2.isInstanceOf[ClassType]){
val check = find_Member(Attribute,a._2.asInstanceOf[ClassType].cla
ssType,lhs.field.name,genv)
}
else null //KBIL TypeMissMatch
}
else{
if (genv.exists(x=>x._1==ast.parent.asInstanceOf[Id].name)) {
val check = find_Member(Method,ast.parent.asInstanceOf[Id].name,ast.
method.name,genv)
if (!check._1) throw Undeclared(Method,ast.method.name)
else check._2
}
else throw Undeclared(Identifier,ast.parent.asInstanceOf[Id].name) //K
BIL
}
}
else {
val t = visit(ast.parent,c)
if (t.isInstanceOf[ClassType]){
val check = find_Member(Method,t.asInstanceOf[ClassType].classType,ast
.method.name,genv)
if (!check._1) throw Undeclared(Method,ast.method.name)
else check._2
}
else null
}
}
ast.params.map(visit(_,c))
}
override def visitWhile(ast: While, c: Context) = {
visit(ast.expr,c)
visit(ast.loop,c)
}
override def visitBreak(ast: Break.type, c: Context) = Break
override def visitContinue(ast: Continue.type, c: Context) = Continue
override def visitReturn(ast: Return, c: Context) = visit(ast.expr,c)
override
override
override
override
override
override
}
def
def
def
def
def
def