Presentation is loading. Please wait.

Presentation is loading. Please wait.

Static checking and symbol table Chapter 6, Chapter 7.6 and Chapter 8.2 Static checking: check whether the program follows both the syntactic and semantic.

Similar presentations


Presentation on theme: "Static checking and symbol table Chapter 6, Chapter 7.6 and Chapter 8.2 Static checking: check whether the program follows both the syntactic and semantic."— Presentation transcript:

1 Static checking and symbol table Chapter 6, Chapter 7.6 and Chapter 8.2 Static checking: check whether the program follows both the syntactic and semantic conventions at compile time (versus dynamic checking -- check at run time). Examples of static checking –Type checks: –Flow of control checks int a, b[10], c; … a = b + c; main { int I …. I++; break; }

2 –Examples of static checks –uniqueness check: –defined before use: –name related check: –Some checks can only be done at runtime: Array-bound checking in java: a[i] = 0; main() { int i, j; double i, j; …. } main() { int i; i1 = 0; …. } LOOPA: LOOP EXIT WHEN I=N I=I+1; END LOOP LOOPB;

3 –To perform static checks, semantic information must be recorded in some place -- symbol table. Grammar specifies the syntax, additional (semantic) information, sometimes called attributes, must be recorded in symbol table for all identifiers. Typically attributes in a symbol table entry include type and offset (where in the memory can I find this variable?). –Struct {int id; int type; int offset;} stentry; Organization of a symbol table: –basic requirement: must be able to find the information associated with a symbol (identifier) quickly. –Example: array, link list, hash table. –Provides two functions: enter(table, name, type, offset) and lookup(name);

4 –Dealing with nested scope: –How to organize the symbol table? –How to do lookup and enter? One symbol table for each scope (procedure, blocks)? Maintain a stack of symbol tables for lookup/enter Program sort(input, output) var a: array [0..10] of integers; x: integer; procedure readarray var x : real; begin …. x …. End procedure quicksort(i, j) begin … x … end main() { int a, b; a = 0; { int a; a = 1; } printf(“a = %d\n”, a); }

5 Symbol tables for sort: nil header a... x... readarray quicksort header x …. header Symbol table for sort Symbol table for readarray Symbol table for quicksort

6 How does the compiler created the symbol table? –First let us consider the simple case: no nested scope, every thing entered into one symbol table: table by using enter (table, id, type, offset) –grammar: P ->D D ->D; D D ->id : T T -> integer T ->real T ->array [num] of T T ->^T I : array [10] of integer; j : real; k : integer I array(10, integer) 0 j real 40 k integer 48

7 P -> {offset = 0;} D D ->D; D D ->id : T {enter(table, id.name, T.type, offset); offset:= offset + T.width} T -> integer {T.type = integer; T.width = 4} T ->real {T.type = real; T.width = 8;} T ->array [num] of T1 {T.type = array(num.val, T1.type); T.width = num.val * T1.width} T ->^T1 {T.type = pointer(T1.type); T.width = 4;}

8 –Now consider the case when you have nested procedures (blocks can be considered as special procedures) must maintain a stack of symbol tables, create new ones when entering new procedure must reset offset when entering new procedures (a stack of offsets) Let us also compute the total size of a table –Grammar: P->D D ->D; D D->id : T D->proc id; D; S T ->integer | real | array[num] of T | ^T

9 mktable(previous): make a new table, properly set all links and related information. Enter(table, name, type, offset). Addwidth(table, width): compute all memory needed by the symbol table. Enterproc(table, name, newtable): enter the procedure name with its symbol table into the old table. –Grammar: P->{t=mktable(nil); push(t, tblptr);push(0, offset);}D {addwidth(top(tblptr), top(offset))} D ->D; D D->id : T {enter(top(tblptr), id.name, T.type, top(offset)); top(offset) = top(offset) + T.width;} D->proc id; {t:=mktable(top(tblptr));push(t, tblptr); push(0, offset);}D; S {t:= top(tblptr);addwidth(t, top(offset)); pop(tblptr); pop(offset);enterproc(top(tblptr), id.name, t)}

10 Dealing with structure (record): –T ->record D end –Make a new symbol table for all the fields in the record.

11 T->record { t=mktable(nil); push(t, tblptr); push(0, offset); } D end { T.type = record(top(tblptr)); T.width = top(offset); pop(tblptr); pop(offset); }

12 Question: How does allowing variable declaration at anywhere in a program (like in C++, java) affect the maintenance of the symbol tables?

13 –Type checking Make sure operations can be performed on operands. Make sure the types of actual arguments matches the types of formal arguments. Need a type system to do the job. –A type system is a collection of rules for assigning type expression to the various parts of a program. –The type system for a practical language can be complicated. Type checking of expressions: P->D;E D->D;D | id : T T->char | integer | array[num] of T | ^T E->literal | num | id | E mod E | E[E] | E^

14 P->D;E D->D;D D->id : T {enter(id.val, T.type);} T->char {T.type = char;} | integer {T.type = integer;} | array[num] of T1 {T.type = array(num.val, T1.type);} | ^T1 {T.type = pointer(T1.type);} E->literal {E.type = char;} | num {E.type = integer;} | id {E.type = lookup(id.val);} | E1 mod E2 {if E1.type == integer && E2.type ==integer then E.type = integer; else E.type =error;} | E1[E2] {if E1.type == array(s, t) && E2.type == integer then E.type = t; else E.type =error;} | E1^ {if E1.type == pointer(t) then E.type = t; else E.type =error;}

15 Type checking for statements S -> id := E S -> if E then S1 S ->while E do S1 S->S1;S2

16 Type checking for statements S -> id := E {if id.type == E.type then S.type = void; else S.type = error;} S -> if E then S1 {if E.type == boolean then S.type = S1.type; else S.type = error;} S ->while E do S1 { if E.type == boolean then S.type = S1.type; else S.type = error;} S->S1;S2 {if S1.type == void and S2.type == void then S.type = void; else S.type = type_error; }

17 Type checking for functions: T->T1->T2 /* function declaration */ {T.type = T1.type ->T2.type} E->E1(E2) /* function call */ {if E1.type == t1.type->t2.type && E2.type == t1.type then T.type = t2.type; else T.type - error; }

18 Equivalence of type expressions Name equivalence - each type with different name is different structural equivalence - names are replaced by the type expressions they define Example: type link = ^cell; var next : link last : link p: ^cell Is structural equivalence good for C++?

19 –Other things related to type. coercion: implicit type conversion: –e.g. double x; ….x = 1; overloading: –a function or operator can represent different operations in different contexts. polymorphic functions: –the body of a polymorphic function can be executed with arguments of different types.


Download ppt "Static checking and symbol table Chapter 6, Chapter 7.6 and Chapter 8.2 Static checking: check whether the program follows both the syntactic and semantic."

Similar presentations


Ads by Google