Semantic Analysis 1 Semantic Analysis l l l

  • Slides: 66
Download presentation
Semantic Analysis 1

Semantic Analysis 1

Semantic Analysis l l l l 2 Semantic Analyzer Attribute Grammars Syntax Tree Construction

Semantic Analysis l l l l 2 Semantic Analyzer Attribute Grammars Syntax Tree Construction Top-Down Translators Bottom-Up Translators Recursive Evaluators Type Checking

Semantic Analyzer source program Lexical Analyzer correct program Syntax Analyzer Semantic Analyzer syntax tree

Semantic Analyzer source program Lexical Analyzer correct program Syntax Analyzer Semantic Analyzer syntax tree Symbol Table 3

Semantic Analysis 4 l Type-checking of programs l Translation of programs l Interpretation of

Semantic Analysis 4 l Type-checking of programs l Translation of programs l Interpretation of programs

Attribute Grammars l l l 5 An attribute grammar is a context free grammar

Attribute Grammars l l l 5 An attribute grammar is a context free grammar with associated semantic attributes and semantic rules Each grammar symbol is associated with a set of semantic attributes Each production is associated with a set of semantic rules for computing semantic attributes

An Example - Interpretation L → E ‘n’ E → E 1 ‘+’ T

An Example - Interpretation L → E ‘n’ E → E 1 ‘+’ T E→T T → T 1 ‘*’ F T→F F → ‘(’ E ‘)’ F → digit 6 {print(E. val); } {E. val : = E 1. val + T. val; } {E. val : = T. val; } {T. val : = T 1. val * F. val; } {T. val : = F. val; } {F. val : = E. val; } {F. val : = digit. val; } Attribute val represents the value of a construct

Annotated Parse Trees L 3*5+4 print(E. val) E. val = 19 E. val =

Annotated Parse Trees L 3*5+4 print(E. val) E. val = 19 E. val = 15 ‘+’ F. val = 3 7 digit. val = 3 ‘*’ T. val = 4 F. val = 4 T. val = 15 T. val = 3 ‘n’ F. val = 5 digit. val = 4

Semantic Attributes l l 8 A (semantic) attribute of a node (grammar symbol) in

Semantic Attributes l l 8 A (semantic) attribute of a node (grammar symbol) in the parse tree is synthesized if its value is computed from that of its children An attribute of a node in the parse tree is inherited if its value is computed from that of its parent and siblings

Synthesized Attributes L → E ‘n’ E → E 1 ‘+’ T E→T T

Synthesized Attributes L → E ‘n’ E → E 1 ‘+’ T E→T T → T 1 ‘*’ F T→F F → ‘(’ E ‘)’ F → digit 9 {print(E. val); } {E. val : = E 1. val + T. val; } {E. val : = T. val; } {T. val : = T 1. val * F. val; } {T. val : = F. val; } {F. val : = E. val; } {F. val : = digit. val; }

Synthesized Attributes L 3*5+4 print(E. val) E. val = 19 E. val = 15

Synthesized Attributes L 3*5+4 print(E. val) E. val = 19 E. val = 15 ‘+’ F. val = 3 10 digit. val = 3 ‘*’ T. val = 4 F. val = 4 T. val = 15 T. val = 3 ‘n’ F. val = 5 digit. val = 4

Inherited Attributes D → T {L. in : = T. type; } L T

Inherited Attributes D → T {L. in : = T. type; } L T → int {T. type : = integer; } T → float {T. type : = float; } L → {L 1. in : = L. in; } L 1 ‘, ’ id {addtype(id. entry, L. in); } L → id {addtype(id. entry, L. in); } 11

Inherited Attributes D T. type = float L. in = float; addtype() ‘, ’

Inherited Attributes D T. type = float L. in = float; addtype() ‘, ’ id 1 12 id 3

Semantic Rules l 13 Each grammar production A is associated with a set of

Semantic Rules l 13 Each grammar production A is associated with a set of semantic rules of the form b : = f (c 1, c 2, …, ck) where f is a function and 1. b is a synthesized attribute of A and c 1, c 2, …, ck are attributes of A or grammar symbols in , or 2. b is an inherited attribute of one of the grammar symbols in and c 1, c 2, …, ck are attributes of A or grammar symbols in

Dependencies of Attributes l l l 14 In the semantic rule b : =

Dependencies of Attributes l l l 14 In the semantic rule b : = f(c 1, c 2, …, ck) we say b depends on c 1, c 2, …, ck The semantic rule for b must be evaluated after the semantic rules for c 1, c 2, …, ck The dependencies of attributes can be represented by a directed graph called dependency graph

Dependency Graphs D T 1 type float in 2 L 10 in 3 L

Dependency Graphs D T 1 type float in 2 L 10 in 3 L 8 in 4 L 6 ‘, ’ id 1 5 entry 15 ‘, ’ id 3 9 entry id 2 7 entry

S-Attributed Attribute Grammars l 16 An attribute grammar is S-attributed if it uses synthesized

S-Attributed Attribute Grammars l 16 An attribute grammar is S-attributed if it uses synthesized attributes exclusively

An Example L → E ‘n’ E → E 1 ‘+’ T E→T T

An Example L → E ‘n’ E → E 1 ‘+’ T E→T T → T 1 ‘*’ F T→F F → ‘(’ E ‘)’ F → digit 17 {print(E. val); } {E. val : = E 1. val + T. val; } {E. val : = T. val; } {T. val : = T 1. val * F. val; } {T. val : = F. val; } {F. val : = E. val; } {F. val : = digit. val; }

L-Attributed Attribute Grammars l 18 An attribute grammar is L-attributed if each attribute computed

L-Attributed Attribute Grammars l 18 An attribute grammar is L-attributed if each attribute computed in each semantic rule for each production A X 1 X 2 … Xn is a synthesized attribute, or an inherited attribute of Xj, 1 j n, depending only on 1. the attributes of X 1, X 2, …, Xj-1 2. the inherited attributes of A

An Example D→TL T → int T → float L → L 1 ‘,

An Example D→TL T → int T → float L → L 1 ‘, ’ id L → id 19 {L. in : = T. type; } {T. type : = integer; } {T. type : = float; } {L 1. in : = L. in; addtype(id. entry, L. in); } {addtype(id. entry, L. in); }

A Counter Example A → {L. i : = l(A. i); } L {M.

A Counter Example A → {L. i : = l(A. i); } L {M. i : = m(L. s); } M {A. s : = f(M. s); } A → {Q. i : = q(R. s); } Q {R. i : = r(A. i); } R {A. s : = f(Q. s); } 20

Construction of Syntax Trees l An abstract syntax tree is a condensed form of

Construction of Syntax Trees l An abstract syntax tree is a condensed form of parse tree E if-stmt E + T * T F 4 F 5 if expr then stmt else stmt E if-stmt expr 21 stmt 3 + * 3 4 5

Syntax Trees for Expressions Interior nodes are operators l Leaves are identifiers or numbers

Syntax Trees for Expressions Interior nodes are operators l Leaves are identifiers or numbers l Functions for constructing nodes – mknode(op, left, right) – mkleaf(id, entry) – mkleaf(num, value) l 22

An Example a-4+b + id b - id a 23 num 4 p 1

An Example a-4+b + id b - id a 23 num 4 p 1 : = mkleaf(id, entrya); p 2 : = mkleaf(num, 4); p 3 : = mknode(‘-’, p 1, p 2); p 4 : = mkleaf(id, entryb); p 5 : = mknode(‘+’, p 3, p 4);

An Example E → E 1 ‘+’ T E → E 1 ‘-’ T

An Example E → E 1 ‘+’ T E → E 1 ‘-’ T E→T T → ‘(’ E ‘)’ T → id T → num 24 {E. ptr : = mknode(‘+’, E 1. ptr, T. ptr); } {E. ptr : = mknode(‘-’, E 1. ptr, T. ptr); } {E. ptr : = T. ptr; } {T. ptr : = E. ptr; } {T. ptr : = mkleaf(id, id. entry); } {T. ptr : = mkleaf(num, num. value); }

Top-Down Translators l l 25 For each nonterminal, – inherited attributes formal parameters –

Top-Down Translators l l 25 For each nonterminal, – inherited attributes formal parameters – synthesized attributes returned values For each production, – for each terminal X with synthesized attribute x, save X. x; match(X); – for nonterminal B, c : = B(b 1, b 2, …, bk); – for each semantic rule, copy the rule to the parser

An Example - Interpretation E T { R. i : = T. nptr }

An Example - Interpretation E T { R. i : = T. nptr } R { E. nptr : = R. s } R addop T { R 1. i : = mknode(addop. lexeme, R. i, T. nptr) } R 1 { R. s : = R 1. s } R { R. s : = R. i } 26 T ‘(’ E ‘)’ { T. nptr : = E. nptr } T num { T. nptr : = mkleaf(num, num. value) }

An Example syntax_tree_node *E( ); syntax_tree_node *R( syntax_tree_node * ); syntax_tree_node *T( ); 27

An Example syntax_tree_node *E( ); syntax_tree_node *R( syntax_tree_node * ); syntax_tree_node *T( ); 27

An Example 28 syntax_tree_node *E( ) { syntax_tree_node *enptr, *tnptr, *ri, *rs; switch (token)

An Example 28 syntax_tree_node *E( ) { syntax_tree_node *enptr, *tnptr, *ri, *rs; switch (token) { case ‘(’: case num: tnptr = T( ); ri = tnptr; /* R. i : = T. nptr */ rs = R(ri); enptr = rs; /* E. nptr : = R. s */ break; default: error(); } return enptr; }

An Example 29 syntax_tree_node *R(syntax_tree_node * i) { syntax_tree_node *nptr, *i 1, *s; char

An Example 29 syntax_tree_node *R(syntax_tree_node * i) { syntax_tree_node *nptr, *i 1, *s; char add; switch (token) { case addop: add = yylval; match(addop); nptr = T(); i 1 = mknode(add, i, nptr); /* R 1. i : = mknode(addop. lexeme, R. i, T. nptr) */ s 1 = R(i 1); s = s 1; break; /* R. s : = R 1. s */ case EOF: s = i; break; /* R. s : = R. i */ default: error(); } return s; }

An Example 30 syntax_tree_node *T( ) { syntax_tree_node *tnptr, *enptr; int numvalue; switch (token)

An Example 30 syntax_tree_node *T( ) { syntax_tree_node *tnptr, *enptr; int numvalue; switch (token) { case ‘(’: match(‘(’); enptr = E( ); match(‘)’); tnptr = enptr; break; /* T. nptr : = E. nptr */ case num: numvalue = yylval; match(num); tnptr = mkleaf(num, numvalue); break; /* T. nptr : = mkleaf(num, num. value) */ default: error( ); } return tnptr; }

Bottom-Up Translators l Keep the values of synthesized attributes on the parser stack A

Bottom-Up Translators l Keep the values of synthesized attributes on the parser stack A XYZ top 31 A X Y Z {A. a : = f(X. x, Y. y, Z. z); } symbol. . . val. . . X Y X. x Y. y val[top-2] val[top-1] Z Z. z val[top] {val[ntop] : = f(val[top-2], val[top-1], val[top]); }

Evaluation of Synthesized Attributes l l l 32 When a token is shifted onto

Evaluation of Synthesized Attributes l l l 32 When a token is shifted onto the stack, its attribute value is placed in val[top] Code for semantic rules are executed just before a reduction takes place If the left-hand side symbol has a synthesized attribute, code for semantic rules will place the value of the attribute in val[ntop]

An Example L → E ‘n’ E → E 1 ‘+’ T E→T T

An Example L → E ‘n’ E → E 1 ‘+’ T E→T T → T 1 ‘*’ F T→F F → ‘(’ E ‘)’ F → digit 33 {print(val[top-1]); } {val[ntop] : = val[top-2] + val[top]; } {val[top] : = val[top]; } {val[ntop] : = val[top-2] * val[top]; } {val[top] : = val[top]; } {val[ntop] : = val[top-1]; } {val[top] : = digit. value; }

An Example Input 34 3*5+4 n 5+4 n +4 n +4 n symbol digit

An Example Input 34 3*5+4 n 5+4 n +4 n +4 n symbol digit F T T* T * digit T*F T E val 3 3_ 3_5 15 15 production used F digit T F F digit T T*F E T

An Example Input +4 n 4 n n n 35 symbol E E+ E

An Example Input +4 n 4 n n n 35 symbol E E+ E + digit E+F E+T E En L val 15 15 _ 4 19 19 _ _ production used E T F digit T F E E+T L En

Evaluation of Inherited Attributes l Removing embedding actions from attribute grammar by introducing marker

Evaluation of Inherited Attributes l Removing embedding actions from attribute grammar by introducing marker nonterminals E TR R “+” T {print(‘+’)} R | “-” T {print(‘-’)} R | T num {print(num. val)} 36 E TR R “+” T M R | “-” T N R | T num {print(num. val)} M {print(‘+’)} N {print(‘-’)}

Evaluation of Inherited Attributes l Inheriting synthesized attributes on the stack A X {Y.

Evaluation of Inherited Attributes l Inheriting synthesized attributes on the stack A X {Y. i : = X. s} Y top 37 symbol. . . val. . . X Y X. s

An Example D T {L. in : = T. type; } L T int

An Example D T {L. in : = T. type; } L T int {T. type : = integer; } T float {T. type : = float; } L {L 1. in : = L. in} L 1 ‘, ’ id {addtype(id. entry, L. in); } L id {addtype(id. entry, L. in); } 38 D T L T int T float L L 1 ‘, ’ id L id {val[ntop] : = integer; } {val[ntop] : = float; } {addtype(val[top], val[top-3]); } {addtype(val[top], val[top-1]); }

An Example Input int p, q, r , q, r , r r 39

An Example Input int p, q, r , q, r , r r 39 symbol int T T id TL TL, T L , id i _ _ e TL D val _ i ie i_ i__ production used T int L id i_ i__ L L “, ” id i_ L L “, ” id

Evaluation of Inherited Attributes l Simulating the evaluation of inherited attributes Inheriting the value

Evaluation of Inherited Attributes l Simulating the evaluation of inherited attributes Inheriting the value of a synthesized attribute works only if the grammar allows the position of the attribute value to be predicted 40

An Example 41 S a. AC S b. ABC C c {C. i :

An Example 41 S a. AC S b. ABC C c {C. i : = A. s} {C. s : = g(C. i)} S a. AC S b. ABMC C c M {C. i : = A. s} {M. i : = A. s; C. i : = M. s} {C. s : = g(C. i)} {M. s : = M. i}

Another Example 42 S a. AC {C. i : = f(A. s)} S a.

Another Example 42 S a. AC {C. i : = f(A. s)} S a. ANC N {N. i : = A. s; C. i : = N. s} {N. s : = f(N. i)}

From Inherited to Synthesized D L “: ” T L L “, ” id

From Inherited to Synthesized D L “: ” T L L “, ” id | id T integer | char D id L L “, ” id L | “: ” T T integer | char D D L 43 id L L : T , id int , id L id , id L , id L : T int

Bison %token DIGIT %% 44 line : expr ‘n’ {printf(“%dn”, $1); } ; expr:

Bison %token DIGIT %% 44 line : expr ‘n’ {printf(“%dn”, $1); } ; expr: expr ‘+’ term {$$ = $1 + $3; } | term ; term: term ‘*’ factor {$$ = $1 * $3; } | factor ; factor: ‘(’ expr ‘)’ {$$ = $2; } | DIGIT ;

Bison %union { char op_type; int value; } %token <value> DIGIT %type <op_type> op

Bison %union { char op_type; int value; } %token <value> DIGIT %type <op_type> op %type <value> expr factor %% 45

Bison expr: expr op factor {$$ = $2 == ‘+’ ? $1 + $3

Bison expr: expr op factor {$$ = $2 == ‘+’ ? $1 + $3 : $1 - $3; } | factor ; op: + {$$ = ‘+’; } | - {$$ = ‘-’; } ; factor: DIGIT ; 46

Bison program: { init_symbol_table(); } PROGRAM ID { declare_program_name($3); } IS declarations BODY statements

Bison program: { init_symbol_table(); } PROGRAM ID { declare_program_name($3); } IS declarations BODY statements END { build_program( $3, $6, $8 ); } ; 47

Recursive Evaluators l l 48 The parser constructs a syntax tree A recursive evaluator

Recursive Evaluators l l 48 The parser constructs a syntax tree A recursive evaluator is a function that traverses the syntax tree and evaluates attributes A recursive evaluator can traverse the syntax tree in any order A recursive evaluator can traverse the syntax tree multiple times

An Example E 1. val 49

An Example E 1. val 49

An Example S { B. ps : = 10 } B { S. ht

An Example S { B. ps : = 10 } B { S. ht : = B. ht } B { B 1. ps : = B. ps } B 1 { B 2. ps : = B. ps } B 2 { B. ht : = max(B 1. ht, B 2. ht) } B { B 1. ps : = B. ps } B 1 sub { B 2. ps : = shrink(B. ps) } B 2 { B. ht : = disp(B 1. ht, B 2. ht) } 50 B text { B. ht : = text. h B. ps }

An Example ps S ht ps B ht 51 ps B 1 B ht

An Example ps S ht ps B ht 51 ps B 1 B ht ps B ht B 2 ht text h

An Example 52 function B(n, ps); var ps 1, ps 2, ht 1, ht

An Example 52 function B(n, ps); var ps 1, ps 2, ht 1, ht 2; begin case production at node n of ‘B B 1 B 2’: ps 1 : = ps; ht 1 : = B(child(n, 1), ps 1); ps 2 : = ps; ht 2 : = B(child(n, 2), ps 2); return max(ht 1, ht 2); ‘B B 1 sub B 2’: ps 1 : = ps; ht 1 : = B(child(n, 1), ps 1); ps 2 : = shrink(ps); ht 2 : = B(child(n, 3), ps 2); return disp(ht 1, ht 2); ‘B text’: return ps text. h; default: error end;

An Example with Right-to-Left Order A → {L. i : = l(A. i); }

An Example with Right-to-Left Order A → {L. i : = l(A. i); } L {M. i : = m(L. s); } M {A. s : = f(M. s); } A → {Q. i : = q(R. s); } Q {R. i : = r(A. i); } R {A. s : = f(Q. s); } 53

An Example i i 54 L A s s i i M s i

An Example i i 54 L A s s i i M s i Q A s s i R s

An Example 55 function A(n, ai); var li, ls, mi, ms, ri, rs, qi,

An Example 55 function A(n, ai); var li, ls, mi, ms, ri, rs, qi, qs; begin case production at node n of ‘A L M’: li : = l(ai); ls : = L(child(n, 1), li); mi : = m(ls); ms : = M(child(n, 2), mi); return f(ms); ‘A Q R’: ri : = r(ai); rs : = R(child(n, 2), ri); qi : = q(rs); qs : = Q(child(n, 1), qi); return f(qs); default: error end;

An Example with Multiple Passes S→E E → E 1 E 2 E →

An Example with Multiple Passes S→E E → E 1 E 2 E → id 56 { E. i : = g(E. s); S. r : = E. t; } { E. s : = fs(E 1. s, E 2. s); E 1. i : = fi 1(E. i); E 2. i : = fi 2(E. i); E. t : = ft(E 1. t, E 2. t); } { E. s : = id. s; E. t : = h(E. i); }

An Example S S r i Es t i E 1 s t i

An Example S S r i Es t i E 1 s t i E 2 s t r i Es t id s i Es t 57 id s

An Example 58 function Es(n); var s 1, s 2; begin case production at

An Example 58 function Es(n); var s 1, s 2; begin case production at node n of ‘E E 1 E 2’: s 1 : = Es(child(n, 1)); s 2 : = Es(child(n, 2)); return fs(s 1, s 2); ‘E id’: return id. s; default: error end;

An Example 59 function Et(n, i); var i 1, t 1, i 2, t

An Example 59 function Et(n, i); var i 1, t 1, i 2, t 2; begin case production at node n of ‘E E 1 E 2’: i 1 : = fi 1(i); t 1 : = Et(child(n, 1), i 1); i 2 : = fi 2(i); t 2 : = Et(child(n, 2), i 2); return ft(t 1, t 2); ‘E id’: return h(i); default: error end;

An Example function Sr(n); var s, i, t; begin s : = Es(child(n, 1));

An Example function Sr(n); var s, i, t; begin s : = Es(child(n, 1)); i : = g(s); t : = Et(child(n, 1), i); return t end; 60

Type Systems l l l 61 A type system is a collection of rules

Type Systems l l l 61 A type system is a collection of rules for assigning types to the various parts of a program A type checker implements a type system Types are represented by type expressions

Type Expressions l A basic type is a type expression – l A type

Type Expressions l A basic type is a type expression – l A type constructor applied to type expressions is a type expression – – 62 boolean, char, integer, real, void, type_error – array: array(I, T) product: T 1 T 2 record: record((N 1 T 1) (N 2 T 2)) pointer: pointer(T) function: D R

Type Declarations P D “; ” E D D “; ” D | id

Type Declarations P D “; ” E D D “; ” D | id “: ” T { addtype(id. entry, T. type) } T char { T. type : = char } T integer { T. type : = int } T “*” T 1 {T. type : = pointer(T 1. type) } T array “[” num “]” of T 1 { T. type : = array(num. value, T 1. type) } 63

Type Checking of Expressions 64 E literal {E. type : = char} E num

Type Checking of Expressions 64 E literal {E. type : = char} E num {E. type : = int} E id {E. type : = lookup(id. entry)} E E 1 mod E 2 {E. type : = if E 1. type = int and E 2. type = int then int else type_error} E E 1 “[” E 2 “]” {E. type : = if E 1. type = array(s, t) and E 2. type = int then t else type_error} E “*” E 1 {E. type : = if E 1. type = pointer(t) then t else type_error}

Type Checking of Statements 65 P D “; ” S S id “: =”

Type Checking of Statements 65 P D “; ” S S id “: =” E {S. type : = if lookup(id. entry) = E. type then void else type_error} S if E then S 1 {S. type : = if E. type = boolean then S 1. type else type_error} S while E do S 1 {S. type : = if E. type = boolean then S 1. type else type_error} S S 1 “; ” S 2 {S. type : = if S 1. type = void and S 2. type = void then void else type_error}

Type Checking of Functions T T 1 “ ” T 2 {T. type :

Type Checking of Functions T T 1 “ ” T 2 {T. type : = T 1. type T 2. type} E E 1 “(” E 2 “)” {E. type : = if E 1. type = s t and E 2. type = s then t else type_error} 66