Presentation is loading. Please wait.

Presentation is loading. Please wait.

Semantic Analysis (Symbol Table and Type Checking)

Similar presentations


Presentation on theme: "Semantic Analysis (Symbol Table and Type Checking)"— Presentation transcript:

1 Semantic Analysis (Symbol Table and Type Checking)
Chapter 5

2 The Compiler So Far Lexical analysis Parsing
Detects inputs with illegal tokens Parsing Detects inputs with ill-formed parse trees Semantic analysis (contextual Analysis) Catches all remaining errors

3 What’s Wrong? Example 1 Example 2 String y = “abc” ; y ++ ;
int y = x + 3; Example 2 String y = “abc” ; y ++ ;

4 Why a Separate Semantic Analysis?
Parsing cannot catch some errors Some language constructs are not context-free Example: All used variables must have been declared (i.e. in scope) ex: { int x { .. { .. x ..} ..} ..} Example: A method must be invoked with arguments of proper type (i.e. typing) ex: int f(int, int) {…} called by f(‘a’, 2.3, 1)

5 More problems require semantic analysis
Is x a scalar, an array, or a function? Is x declared before it is used/defined? Is x defined before it is used? Are any names declared but not used? Which declaration of x does this reference? Is an expression type-consistent? Does the dimension of a reference match the declaration? Where can x be stored? (heap, stack, ) Does *p reference the result of a malloc()? Is an array reference in bounds?

6 Why is semantic analysis hard?
need non-local information a[x] = y + z; // type consistent ? answers depend on values, not on syntax int a[10]; a[10] = 1; answers may involve computation a[10 + BASE] = 6;

7 How can we answer these questions?
1. use context-sensitive grammars (CSG) 2. use attribute grammars(AG) augment context-free grammar with rules calculate attributes for grammar symbols 3. our approach: Build AST Construct visitors to traverse AST to collect information about names in symbol tables Write various checking visitors to check possible semantic errors.

8 Symbol Tables Symbol Tables  Environments Scope
Mapping IDs to infrmation about the IDs like Types , Locations, etc. Definition  Insert in the table Use  Lookup ID Scope Where the IDs are “visible” Ex: formal parameters, local variables in MiniJava -> inside the method where defined -- (private) variables in a class -> inside the class -- (public) method : visible anywhere (unless overridden)

9 Symbol Table What kind of IDs should be entered?
class or structure names variable names defined constants procedure and function names literal constants and strings source text labels Separate table for structure layouts (types) (field offsets and lengths)

10 What kind of information should be included?
textual name data type dimension information ( for aggregates) declaring procedure or class lexical level of declaration storage class ( base address in stack; heap , global) size and offset in storage record  (pointer to) structure table parameter by-reference or by-value? function  number and type of arguments to functions

11 Attributes of symbol table
Attributes are properties of ID in declarations Symbol table associates names with attributes Names may have different attributes depending on their meaning: variables: type, procedure level, frame offset types: type descriptor, data size/alignment constants: type, value procedures: formals (names/types), result type, block information (local decls.), frame size classes : name, parent class, fields, methods, …

12 Symbol Table construction strategy
number of table constructed: one global symbol table : scope level info included one symbol table per scope + links to parent scope life-time of symbol table persistent once created  multi-pass compiler created on entering scope and destroyed on leaving its scope.  one pass compiler

13 A set of bindings (nameattributes assoc.)
Environments A set of bindings (nameattributes assoc.) Initial Env s0 Class C { int a; int b; int c; Env s1 ={parents0 }+ {a -> int, b -> int, c -> int} public void m() { System.out.println(a+c); int j = a+b; Env s2 = {parent  s1 }+ {j -> int} String a = “hello”; Env s2 = s2 + {a -> String} System.out.println(a);

14 Environments (Cont’d)
Env s2 = s2 + {a -> String} System.out.println(a); } Env s1 Env s0

15 Implementing Environments
Functional Style (non-destructive) enter scope  Keep previous env and create new one leave scope  discard/save new one and back to old implementation: hashtable or tree. Imperative Style (using hashtable ) enter scope  mark a new scope definition encountered  put new key-value leave scope  pop all key-value pairs since the last entering scope) a global table only.

16 Multiple Symbol Tables : ML-style
structure M = sturct structure E = struct val a = 5 end s0 + s2 structure N = struct val b = 10 val a = E.a + b end s0 + s2 + s4 structure D = struct val d = E.a + N.a end End s7 Initial Env s0 s1 = {a -> int} s2 = {E -> s1 } s3 = {b -> int,a -> int} s4 = {N -> s3 } s5 = {d -> int} s6 = {D -> s5 } s7 = s2 + s4 + s6

17 Multiple Symbol Tables : Java-style
Initial Env s0 s1 = {a -> int} s2 = {E -> s1 } s3 = {b -> int,a -> int} s4 = {N -> s3 } s5 = {d -> int} s6 = {D -> s5 } s7 = s2 + s4 + s6 Package M; s7 class E { static int a = 5; } s7 class N { static int b = 10 static int a = E.a + b class D { static int d = E.a+ N.a End s7

18 Implementation – Functional Symbol Table
Efficient Functional Approach s’ = s + {a |-> t} would return [s + {a |-> t} ] If implemented with a Hashtable would have to create O(n) buckets for each scope Is this a good idea?

19 Implementation – Imperative Symbol Table (inefficient nondestructive update)
Update (clone & put) s s’ = s + {d |-> t4} Undo a t1 d t4 b t3 c t2 See Appel Program 5.2 (p106)

20 Implementation - Tree How could this be implemented?
dog 3 dog 3 emu 42 bat 1 m2 = {m1 + emu |-> 42 } camel 2 Want m2 from m1 in O(n) m1 = { bat |-> 1 , camel |-> 2, dog |-> 3 }

21 Symbols v.s Strings as table key
problem with string as table key: time consuming for comparing of long names. why not comparing address if equal strings are identical. Symbol: a wrapper for (intern) Stirngs Symbol Representation Comparing symbols for equality is fast. Extracting an integer hash key is fast. Comparing two symbols for “greater-than” is fast. (monotonic ?) Properties: Symbol s1,s2 => s1 == s2 iff s1.equals(s2) iff s1.string == s2.string public class Symbol { public String toString(); public static Symbol getSymbol(String n); }

22 symbol.Symbol public class Symbol { public String name;
// Symbol cannot be constructed directly private Symbol(String n) { name = n;} public String toString(){ return name; } private static Map map = new Hashtable(); public static Symbol getSymbol(String n){ String u = n.intern(); Symbol s = (Symbol) map.get(u); if (s == null){ s = new Symbol(u); map.put(u,s); } return s; } }

23 Symbol Table Implementastion (efficient destructive update)
Using a Hash Table s top: Symbol marker: Binder c t4 c t4 b t4 a t1 c t4 c t4 a t3 b t2 c t4 null null

24 Some sample program(I)
/** * The Table class is similar to java.util.Dictionary, * except that each key must be a Symbol and there is * a scope mechanism. */ public class Table { private Hashtable dict = new java.util.Hashtable(); private Symbol top; private Binder marks; public Table(){}

25 Some sample program(II)
/** Gets the object associated with the specified * symbol in the Table. */ public Object get(Symbol key) { Binder e = (Binder)dict.get(key); if (e==null) return null; else return e.value; } /** Puts the specified value into the Table, * bound to the specified Symbol. public void put(Symbol key, Object value) { dict.put(key, new Binder(value, top, (Binder)dict.get(key))); top = key; }

26 Some sample program(III)
/** * Remembers the current state of the Table. */ public void beginScope() {marks = new Binder(null,top,marks); top=null;} /** Restores the table to what it was at the most * recent beginScope that has not already been ended. public void endScope() { while (top!=null) { Binder e = (Binder)dict.get(top); if (e.tail!=null) dict.put(top,e.tail); else dict.remove(top); top = e.prevtop; } top=marks.prevtop; marks=marks.tail; }

27 Some sample program(IV)
package Symbol; class Binder { Object value; Symbol prevtop; Binder tail; Binder(Object v, Symbol p, Binder t) { value=v; prevtop=p; tail=t; }

28 Type-Checking in MiniJava
Binding for type-checking in MiniJava Variable and formal parameter Var name <-> type of variable Method Method name <-> result type, parameters( including position information), local variables Class Class name <-> variables, method declaration, parent class

29 Symbol Table: example See Figure 5.7 on page 111 Primitive types
int -> IntegerType() Boolean -> BooleanType() Other types Int [] -> IntArrayType() Class -> IdentifierType(String s)

30 A MiniJava Program and its symbol table (Figure 5.7)
class B { C f; int[] j; int q; public int start(int p, int q) { int ret; int a; /* … */ return ret; } public boolean stop(int p) { /* …*/ return false; } } class{ C /* …*/ } B C FIELDS f C j int[] g int METHODS start int stop boolean PARAMS p int q int LOCALS ret int a int p int ….

31 Main Symbol tables in MiniJava
Containment Hierarchy: GlobalTable  ClassTable  MethodTable Table class hierarchy : HashMap  Table  NamedTable  GlobalTable  ClassTable TypedTable MethodTable

32

33

34

35

36 Be careful! getVarType(Method m, Class c, String id)
In c.m, find variable id Precedence: Local variable in method Parameter in parameter list Variable in the class Variable in the parent class getMethod(), getMethodType() May be defined in the parent Classes compareTypes() Primitive types : int, boolean, IntArrayType Subtype : IdentifierType

37 Type-Checking : Two Phases
Build Symbol Table Type-check statements and expressions public class Main { public static void main(String [] args) { try { Program prog = new MiniJavaParser(System.in).Program(); MiniJavaSymbolTableVisitor v1 = new MiniJavaSymbolTableVisitor(); v1.visit(prog); new TypeCheckVisitor(v1.getTable()).visit(prog);}catch (ParseException e) { System.out.println(e.toString()); }}}

38 BuildSymbolTableVisitor();
public class MiniSymbolTableVisitor extends DepthFirstVisitor { private GlobalTable gtable = new …; private ClassTable cTable ; private MethodTable mTable; boolean inClass, InMethod, InBody; String id; Type type // Type t; // Identifier i;

39 BuildSymbolTableVisitor(); - Cont’d
public void visit(VarDecl n) { super.visit(n); if (inMethod) { if (!(mTable.addLocal(id, cType))) { err.printf("Duplicate Formal parameter defined: %s %s !!", id, cType); } } else { if (!cTable.addField(id, cType)) { err.printf("Duplicate fileds defined: %s %s !!", id, cType); } }

40 MiniJavaSymbolTableVisitor() :DepthFirstVisitor()
public Type visit(MainClass n); public Type visit(ClassDeclSimple n); public Type visit(ClassDeclExtends n); public Type visit(VarDecl n); public Type visit(MethodDecl n); public Type visit(Formal n); public Type visit(IntArrayType n); public Type visit(BooleanType n); public Type visit(IntegerType n); public Type visit(IdentifierType n);

41 MiniJavaTypeCheckVisitor(SymbolTable);
package visitor; import syntaxtree.*; public class MiniJavaTypeCheckVisitor extends DepthFirstVisitor { static ClassTable cTable; static MethodTable mTable; static GlobalTable gTable; public TypeCheckVisitor(GlobalTable s){ gTable = s; }

42 MiniJavaTypeCheckVisitor(SymbolTable); - Cont’d
// Identifier i; // Exp e; public void visit(Assign n) { Type t1 = gTable.getVarType(mTable,cTable, n.i.toString()); Type t2 = new MiniJavaExpTypeVisitor(gTable) ); if ( !t1.equals(t2) ){ err.println("Type error in assignment to " n.i.toString()); }}

43 MiniJavaExpTypeVisitor(SymbolTable)
package visitor; import syntaxtree.*; public class MiniJavaExpVisitor extends DepthFirstVisitorR { // Exp e1,e2; public Type visit(Plus n) { if (! (visit(n.e1) == IntegerType.TYPE) ) { err.printf("Left side of Plus must be of type integer"); } if (! (visit(n.e2) instanceof IntegerType) ) { err.printf("Right side of Plus must be of type integer"); return IntegerType.TYPE;

44 MiniJavaTypeCheckVisitor : Visitor()
public void visit(MainClass n); public void visit(ClassDeclSimple n); public void visit(ClassDeclExtends n); public void visit(MethodDecl n); public void visit(If n); public void visit(While n); public void visit(Print n); public void visit(Assign n); public void visit(ArrayAssign n);

45 MiniJavaExpTypeVisitor() : VisitorR()
public Type visit(And n); // boolean public Type visit(LessThan n); // boolean public Type visit(Plus n); // int public Type visit(Minus n); public Type visit(Times n); public Type visit(ArrayLookup n); // int public Type visit(ArrayLength n); // int public Type visit(Call n); // result type public Type visit(IntegerLiteral n); // int public Type visit(True n); // boolean public Type visit(False n); public Type visit(IdentifierExp n); // symbol table lookup public Type visit(This n); // current class public Type visit(NewArray n); // int[] public Type visit(NewObject n); // public Type visit(Not n); // boolean

46 Overloading of Operators, ….
When operators are overloaded, the compiler must explicitly generate the code for the type conversion. “abc” + 4 For an assignment statement, both sides have the same type. When we allow extension of classes, the right hand side is a subtype of lhs. long x = (int) y + 3 Person p = new Student();

47 Error Handling For a type error or an undeclared identifier, it should print an error message. And must go on….. Recovery from type errors? Do as if it were correct. Not a big deal in our homework. Example: int i = new C(); int j = i + 1; still need to insert i into symbol table as an integer so the rest can be typechecked..

48 Type Checking For MiniJava

49 Type Checkng for MiniJava (I)
Package syntaxtree; Program(MainClass m, ClassDecList c1) // recursively type check m and cl MainClass(Identifier i1, Identifier i2, Statement s) // do nothing abstract class ClassDecl ClassDeclSimple(Identifier i, VarDeclList vl, methodDeclList m1) // recursively type check vl and ml ClassDeclExtends(Identifier i, Identifier j, VarDecList vl, MethodDeclList ml) //like above but must assure thtt (1) j is a //declared class

50 -----------------------------
VarDecl(Type t, Identifier i) Formal(Type t, Identifier i) //2. recursively type check that t is a built-in or declared type MethodDecl(Type t, Identifier i, FormalList fl, VariableDeclList vl, StatementList sl, Exp e) // same as (2) // recursively type check fl, vl, sl and e. // 3. type(e) == t

51 Type Checking for MiniJava (II)
abstract class type IntArrayType() BooleanType() IntegerType() // do nothing IndentifierType(String s) //check that s is the name of a class [in scope].

52 abstract class Statement
Block(StatementList sl) // recursively type check sl If(Exp e, Statement s1, Statement s2) //4. type(e) == boolean // recursively type check sl and s2 While(Exp e, Statement s) //4 + recursively check s. Print(Exp e) //5. type(e) == int Assign(Identifier i, Exp e) // 6. type(i) != int[] // 7. type(i) == type(e) ArrayAssign(Identifier i, Exp e1, Exp e2) // 8. type(i) == int[] && type(e1) == type(e2) == int

53 Type checking for MiniJava (III)
abstract class Exp : // Arithmetic Expression Plus(Exp e1, Exp e2) Minus(Exp e1, Exp e2) Times(Exp e1, Exp e2) //10. type(e1) == type(e2) == int //11. type(rlt) int ArrayLookup(Exp e1, Exp e2) // type(e1) == int[] & type(e2) == int // type(rlt)  int ArrayLength(Exp e) // type(e) == int[] // type(rlt) int IntegerLiteral(int i)

54 LessThan(Exp e1, Exp e2) // type(e1) == type(e2) == int // type(rlt)  boolean True() False() And(Exp e1, Exp e2) // type(e1) == type(e2) == boolean Not(Exp e) // ...

55 IdentifierExp(String s)
//s(field or or formal local)was declared and in scope //type(rlt)  type part of the declaration that s is bound to. This() // type(rlt)  current class type NewArray(Exp e) //type(e) == int //type(rlt)  int[] NewObject(Identifier i) // i is a class name in scope // type(rlt)  IdtentifierType(name of i ) Identifier(Sting s) // do nothing

56 Call(Exp e, Identifier i, ExpList el)
//c1. type(e) == IdentifierType(c) for some class c //c2. there is a method m in c named i with formal parameters of types fl. // c3. fl and el has the same size k >= 0 and // c4. for j = 1 .. k type(el(j)) == fl(j) // type(rlt)  returnType(m).


Download ppt "Semantic Analysis (Symbol Table and Type Checking)"

Similar presentations


Ads by Google