Download presentation
Presentation is loading. Please wait.
Published byLetitia Diane Houston Modified over 9 years ago
1
CSE 5317/4305 L6: Semantic Analysis1 Semantic Analysis Leonidas Fegaras
2
CSE 5317/4305 L6: Semantic Analysis2 Type Checking Checking whether the use of names is consistent with their declaration in the program int x; x := x+1; correct use of x x.A := 1; x[0] := 0; type errors Statically typed languages: done at compile time, not at run time Need to remember declarations –Symbol Table scanner parser get token token source file get next character AST type checking AST symbol table type errors
3
CSE 5317/4305 L6: Semantic Analysis3 Symbol Table A compile-time data structure used to map names into declarations It stores: –for each type name, its type definition eg. for the C type declaration typedef int* mytype, it maps the name mytype to a data structure that represents the type int* –for each variable name, its type if the variable is an array, it also stores dimension information it may also store storage class, offset in activation record, etc –for each constant name, its type and value –for each function and procedure, its formal parameter list and its output type each formal parameter must have –name –type –type of passing (by-reference, by-value, etc)
4
CSE 5317/4305 L6: Semantic Analysis4 Symbol Table (cont.) Need to capture nested scopes, if necessary { int a; { int a; a = 1; }; a = 2; }; Interface: insert ( key: String, binding: Declaration ) lookup ( key: String ): Option[Declaration] begin_scope () end_scope ()
5
CSE 5317/4305 L6: Semantic Analysis5 The Gen Symbol Table class SymbolTable { var symbol_table: List[List[(String,Declaration)]] = Nil def lookup ( key: String ): Option[Declaration] = { val ds = for ( s <- symbol_table; (n,d) <- s if n.equals(key) ) yield d ds match { case c::cs => Some(c) case _ => None } def insert ( key: String, declaration: Declaration ) { symbol_table match { case c::cs => symbol_table = ((key,declaration)::c)::cs case _ => throw new Error("Empty scope") }
6
CSE 5317/4305 L6: Semantic Analysis6 The Gen Symbol Table (cont.) def begin_scope () { symbol_table = List()::symbol_table } def end_scope () { symbol_table match { case c::cs => symbol_table = cs case _ => throw new Error("Empty scope") }
7
CSE 5317/4305 L6: Semantic Analysis7 Example { int a; { int a; a = 1; }; a = 2; };
8
CSE 5317/4305 L6: Semantic Analysis8 Type ASTs A typechecker is a function that maps an AST that represents an expression into its type Need to define the data structures for types: sealed abstract class Type case class IntegerType () extends Type case class BooleanType () extends Type case class NamedType ( typename: String ) extends Type case class ArrayType ( elements: Type ) extends Type case class RecordType ( components: List[(String,Type)] ) extends Type
9
CSE 5317/4305 L6: Semantic Analysis9 Declarations The symbol table must contain type declarations (ie. typedefs),variable declarations, constant declarations, and function signatures: var symbol_table: List[List[(String,Declaration)]] = Nil sealed abstract class Declaration case class TypeDeclaration ( declaration: Type ) extends Declaration case class VarDeclaration ( declaration: Type ) extends Declaration case class ConstantDeclaration ( declaration: Type, value: Exp ) extends Declaration case class FunctionDeclaration ( result: Type, parameters: List[Type] ) extends Declaration
10
CSE 5317/4305 L6: Semantic Analysis10 Typechecking A tree traversals that checks each node of the AST tree recursively: def typecheck ( e: Expr ): Type = e match { case IntegerExp => IntegerType case TrueExp => BooleanType case FalseExp => BooleanType case VariableExp(name) => st.lookup(name) match { case Some(VarDeclaration(type) => type case Some(_) => throw new Error(name+" is not a variable") case None => throw new Error("Undefined variable: "+name) }
11
CSE 5317/4305 L6: Semantic Analysis11 Typechecking: BinaryExp case BinOpExp(op,left,right) => { val left_type = typecheck(left) val right_type = typecheck(right) op match { case "+": if (left_type == right_type && left_type == IntegerType()) left_type else throw new Error("expected integers in addition") … }
12
CSE 5317/4305 L6: Semantic Analysis12 Typechecking: CallExp case CallExp(f,args) => st.lookup(f) match { case Some(FunctionDeclaration(otp,params)) => { if (params.length != args.length) throw new Error("Number of parameters doesn't match number of arguments") else (args.map(typecheck(_)) zip params).map({ case (atp,(_,ptp)) => if (!equal_types(atp,ptp)) throw new Error("The type of call argument ("+atp +") does not match the type of the formal parameter: "+ptp) }) otp } case _ => throw new Error("Undefined function: "+f) } equal_types(x,y) checks the types x and y for equality Two types of type equality: type equality based on type name equivalence, or based on structural equivalence
13
CSE 5317/4305 L6: Semantic Analysis13 The Calculator Interpreter Evaluate an expression e using a symbol table st: def eval ( e: Expr ): Double = { e match { case RealConst(v) => v case IntConst(v) => v case StringConst(v) => throw new Error("Strings are not permitted: "+e) case Var(v) => st.lookup(v) match { case Some(VarDec(v)) => v case Some(_) => throw new Error(v+" is not a variable") case None => throw new Error("Undefined variable: "+v) } case IfExp(e1,e2,e3) => if (eval(e1) > 0.0) eval(e2) else eval(e3)
14
CSE 5317/4305 L6: Semantic Analysis14 The Calculator Interpreter (cont.) case CallExp(fnc,args) => st.lookup(fnc) match { case Some(FunDec(body,params)) => if (params.length != args.length) throw new Error("Number of parameters does not much number of arguments") else { st.begin_scope() (args.map(eval(_)) zip params).map({ case (a,p) => st.insert(p,new VarDec(a)) }) val res = eval(body) st.end_scope() res } case Some(_) => throw new Error(fnc+" has not been defined as a function"); case None => throw new Error("Undefined function: "+fnc) }
15
CSE 5317/4305 L6: Semantic Analysis15 The Calculator Interpreter (cont.) case BinOpExp(op,e1,e2) => { val left = eval(e1) val right = eval(e2) op match { case "plus" => left + right case "minus" => left - right case "times" => left * right case "div" => left / right case "and" => if ((left > 0.0) && (right > 0.)) 1.0 else 0.0 case "or" => if ((left > 0.0) || (right > 0.0)) 1.0 else 0.0 case "eq" => if (left == right) 1.0 else 0.0 case "ne" => if (left != right) 1.0 else 0.0 case "gt" => if (left > right) 1.0 else 0.0 case "lt" => if (left < right) 1.0 else 0.0 case "ge" => if (left >= right) 1.0 else 0.0 case "le" => if (left <= right) 1.0 else 0.0 case _ => throw new Error("Unrecognized binary operation: "+e) } case _ => throw new Error("Unrecognized expression: "+e)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.