1 / 44

Semantic Analysis

Semantic Analysis. Mooly Sagiv & Greta Yorsh html://www.cs.tau.ac.il/~msagiv/courses/wcc05.html. Outline. What is Semantic Analysis Why is it needed? Scopes and type checking for imperative languages (Chapter 6) Attribute grammars (Chapter 3). Semantic Analysis.

Download Presentation

Semantic Analysis

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Semantic Analysis Mooly Sagiv & Greta Yorsh html://www.cs.tau.ac.il/~msagiv/courses/wcc05.html

  2. Outline • What is Semantic Analysis • Why is it needed? • Scopes and type checking for imperative languages (Chapter 6) • Attribute grammars (Chapter 3)

  3. Semantic Analysis • The “meaning of the program” • Requirements related to the “context” in which a construct occurs • Context sensitive requirements - cannot be specified using a context free grammar(Context handling) • Requires complicated and unnatural context free grammars • Guides subsequent phases

  4. Basic Compiler Phases Source program (string) Front-End lexical analysis Tokens syntax analysis Abstract syntax tree semantic analysis Back-End Fin. Assembly

  5. Example Semantic Condition • In C • breakstatements can only occur insideswitchor loop statements

  6. Partial Grammar for C Stm  Exp; Stm  if (Exp) Stm StList  StList Stm Stm  if (Exp) Stm else Stm StList   Stm  while (Exp) do Stm Stm  break; Stm {StList }

  7. LStm  Exp; LStm  if (Exp) LStm LStm if (Exp) LStm else LStm LStList  LStList LStm LStm  while (Exp) do LStm LStm  {LStList } LStList   LStm  break; Refined Grammar for C StmExp; Stm  if (Exp) Stm StList  StList Stm Stm  if (Exp) Stm else Stm StList   Stm while (Exp) do LStm Stm {StList }

  8. A Possible Abstract Syntax for C package Absyn; abstract public class Absyn { public int pos ;} class Exp extends Absyn { }; class Stmt extends Absyn {} ; class SeqStmt extends Stmt { public Stmt fstSt; public Stmt secondSt; SeqStmt(Stmt s1, Stmt s2) { fstSt = s1; secondSt s2 ; } } class IfStmt extends Stmt { public Exp exp; public Stmt thenSt; public Stmt elseSt; IfStmt(Exp e, Stmt s1, Stmt s2) { exp = e; thenSt = s1; elseSt s2 ; } } class WhileStmt extends Stmt {public Exp exp; public Stmt body; WhileSt(Exp e; Stmt s) { exp =e ; body = s; } class BreakSt extends Stmt {};

  9. Partial CUP Specification ... %% stm::= IF ‘(‘ exp: e ‘)’ stm:s {: RESULT = new IfStm(e, s, null) ; :} | IF ‘(‘ exp: e ‘)’ stm:s1 ELSE stm: s2 {: RESULT = new IfStm(e, s1, s2) ; :} | WHILE ‘(‘ exp: e ‘)’ stm: s {: RESULT= new WhileStm(e, s); :} | ‘{‘ s: stmList ‘}’ {: RESULT = s; :} | BREAK `;' {: RESULT = new BreakStm(); :} ; stmList :=:stmList:s1 stmt:s2 {: RESULT = new SeqStm(s1, s2) ; :} | /* empty */ {: RESULT = null ; :}

  10. A Semantic Check(on the abstract syntax tree) • static void checkBreak(Stmt st) • { • if (st instanceof SeqSt) { • SeqSt seqst = (SeqSt) st; • checkBreak(seqst.fstSt); checkBreak(seqst.secondSt); • } • else if (st instanceof IfSt) { • IfSt ifst = (IfSt) st; • checkBreak(ifst.thenSt); checkBreak(ifst elseSt); • } • else if (st instanceof WhileSt) ; // skip • else if (st instanceof BreakeSt) { • System.error.println(“Break must be enclosed within a loop”. st.pos); } • }

  11. parser code {: public int loop_count = 0 ; :} stm : := exp ‘;’ | IF ‘(‘ exp ‘)’ stm | IF ‘(‘ exp ‘)’ stm ELSE stm | WHILE ‘(‘ exp ‘)’ m stm {: loop_count--; :} | ‘{‘ stmList ‘}’ | BREAK ‘;’ {: if (loop_count == 0) system.error.println(“Break must be enclosed within a loop”); :} ; stmList ::=stmList st | /* empty */ ; m ::= /* empty */ {: loop_count++ ; :} ; Syntax Directed Solution

  12. Problems with Syntax Directed Translations • Grammar specification may be tedious (e.g., to achieve LALR(1)) • May need to rewrite the grammar to incorporate different semantics • Modularity is impossible to achieve • Some programming languages allow forwarddeclarations (Algol, ML and Java)

  13. Example Semantic Condition: Scope Rules • Variables must be defined within scope • Dynamic vs. Static Scope rules • Cannot be coded using a context free grammar

  14. Dynamic vs. Static Scope Rules procedure p; var x: integer procedure q ; begin { q } … x … end { q }; procedure r ; var x: integer begin { r } q ; end; { r } begin { p } q ; r ; end { p }

  15. Example Semantic Condition • In Pascal Types in assignment must be “compatible”'

  16. Partial Grammar for Pascal Stm id Assign Exp Exp  IntConst Exp  RealConst Exp Exp + Exp Exp Exp -Exp Exp ( Exp )

  17. Refined Grammar for Pascal Stm RealId Assign RealExp StmIntExpAssign IntExp StmRealId Assign IntExp RealExp  RealConst IntExp  IntConst RealIntExp  RealId IntExp  IntId RealExp RealExp + RealExp RealExp RealExp + IntExp IntExp IntExp + IntExp RealExp IntExp + RealExp IntExp IntExp -IntExp RealExp RealExp -RealExp RealExp RealExp -RealExp IntExp ( IntExp ) RealExp RealExp -IntExp RealExp IntExp -RealExp RealExp ( RealExp )

  18. Syntax Directed Solution %% ... stm : := id:i Assign exp:e {: compatAss(lookup(i), e) ; :} ; exp ::= exp:e1 PLUS exp:e2 {: compatOp(Op.PLUS, e1, e2); RESULT = opType(Op.PLUS, e1, e2); :} | exp:e1 MINUS exp:e2 {:compatOp(Op.MINUS, e1, e2); RESULT = opType(Op.MINUS, e1, e2); :} | ID: i {: RESULT = lookup(i); :} | INCONST {: RESULT = new TyInt() ; :} | REALCONST {: RESULT = new TyReal(); :} | ‘(‘ exp: e ‘)’ {: RESULT = e ; :} ;

  19. Type Checking (Imperative languages) • Identify the type of every expression • Usually one or two passes over the syntax tree • Handle scope rules

  20. Types • What is a type • Varies from language to language • Consensus • A set of values • A set of operations • Classes • One instantiation of the modern notion of types

  21. Why do we need type systems? • Consider assembly code • add $r1, $r2, $r3 • What are the types of $r1, $r2, $r3?

  22. Types and Operations • Certain operations are legal for values of each type • It does not make sense to add a function pointer and an integer in C • It does make sense to add two integers • But both have the same assembly language implementation!

  23. Type Systems • A language’s typesystem specifies which operations are valid for which types • The goal of type checking is to ensure that operations are used with the correct types • Enforces intended interpretation of values because nothing else will!

  24. Type Checking Overview • Three kinds of languages • Statically typed: (Almost) all checking of types is done as part of compilation • Semantic Analysis • C, Java, Cool, ML • Dynamically typed: Almost all checking of types is done as part of program execution • Code generation • Scheme • Untyped • No type checking (Machine Code)

  25. Type Wars • Competing views on static vs. dynamic typing • Static typing proponents say: • Static checking catches many programming errors • Prove properties of your code • Avoids the overhead of runtime type checks • Dynamic typing proponents say • Static type systems are restrictive • Rapid prototyping difficult with type systems • Complicates the programming language and the compiler • Compiler optimizations can hide costs

  26. Type Wars (cont.) • In practice, most code is written in statically typed languages with escape mechanisms • Unsafe casts in C Java • union in C • It is debatable whether this compromise represents the best or worst of both worlds

  27. From English to an inference rule • [Easy to read with practice] • Start with a simplified system and gradually add features • Building blocks • Symbol  is ‘and’ • Symbol  is ‘if then’ • Symbol x:T is ‘x has type T’

  28. From English to an inference rule(2) • If e1 has type Int and e2 has type Int, then e1 + e2 has type Int • (e1 has type Int  e2 has type Int)  e1 +e2 has type Int • (e1: Int  e2: Int)  e1+e2: Int

  29. From English to an inference rule(3) • The statement(e1: Int  e2: Int)  e1+e2: Int is a special case ofHypothesis1  ...  Hypothesisn  Conclusion • This is an inference rule

  30. Notation for Inference Rules • By tradition inference rules are written Hypothesis1  ...  HypothesisnConclusion • Type rules have hypothesis and conclusion e: T •  means “it is provable that ...”

  31. i is an integer  i : Int [Int] • e1 : Int • e2 : Int •  e1+e2 : Int [Add] Two Rules

  32. Type Rules (cont.) • These rules give templates describing how to type integers and + expressions • By filling the templates, we can produce complete typings for expressions

  33. 1 is an integer  1 : Int 2 is an integer  2: Int [Int] [Int]  1+2: Int [Add] Example 1 +2

  34. Soundness of type systems • For every expression e, • for every value v of e at runtime • v val(type(e)) • The type may actually describe more values • The rules can reject correct programs • Becomes more complicated with subtyping (inheritance)

  35. Attribute Grammars [Knuth 68] • Generalize syntax directed translations • Every grammar symbol can have several attributes • Every production is associated with evaluation rules • Context rules • The order of evaluation is automatically determined • declarative • Multiple visits of the abstract syntax tree

  36. Attribute Grammar for Types stm id Assign exp {compat_ass(id.type, exp.type) } exp exp PLUS exp {compat_op(PLUS, exp[1].type,exp[2].type) exp[0].type = op_type(PLUS, exp[1].type, exp[2].type) } exp exp MINUS exp {compat_op(MINUS, exp[1].type, exp[2].type) exp[0].type = op_type(MINUS, exp[1].type, exp[2].type) } exp ID { exp.type = lookup(id.repr) } exp INCONST { exp.type= ty_int ; } exp REALCONST { exp.type = ty_real ;} exp ‘(‘ exp ‘)’ { exp[0].type = exp[1].type ; }

  37. Example Binary Numbers Z L Z L.L L L B L B B 0 B 1 Compute the numeric value of Z

  38. Z L { Z.v = L.v } Z L.L { Z.v = L[1].v + L[2].v } L L B { L[0].v = L[1].v + B.v } L  B { L.v = B.v } } B  0 {B.v = 0 } B  1 {B.v = ? }

  39. Z L { Z.v = L.v } Z L.L { Z.v = L[1].v + L[2].v } L L B { L[0].v = L[1].v + B.v } L  B { L.v = B.v } B  0 {B.v = 0 } B  1 {B.v = 2B.s }

  40. Z L { Z.v = L.v } Z L.L { Z.v = L[1].v + L[2].v } L L B { L[0].v = L[1].v + B.v B.s = L[0].s L[1].s = L[0].s + 1} } L  B { L.v = B.v B.s = L.s } B  0 {B.v = 0 } B  1 {B.v = 2B.s }

  41. Z L { Z.v = L.v L.s = 0 } Z L.L { Z.v = L[1].v + L[2].v L[1].s = 0 L[2].s=? } L L B { L[0].v = L[1].v + B.v B.s = L[0].s L[1].s = L[0].s + 1} } L  B { L.v = B.v B.s = L.s } B  0 {B.v = 0 } B  1 {B.v = 2B.s }

  42. Z L { Z.v = L.v L.s = 0 } Z L.L { Z.v = L[1].v + L[2].v L[1].s = 0 L[2].s=-L[2].l } LL B { L[0].v = L[1].v + B.v B.s = L[0].s L[1].s = L[0].s + 1 L[0].l = L[1].l +1} } L  B { L.v = B.v B.s = L.s L.l = 1 } B  0 {B.v = 0 } B  1 {B.v = 2B.s }

  43. Z.v=1.625 Z L.v=0.625 L.v=1 L.l=3 L.s=-3 L . L L.s=0 L.l=1 L.v=0.5 B.s=-3 L.l=2 B.s=0 B L L.s=-2 B B.v=1 B.v=0.125 B.s=-2 L.s=-1 1 B L L.l=1 B.v=0 L.v=0.5 1 0 B B.v=0.5 B.s=-1 1

  44. Summary • Several ways to enforce semantic correctness conditions • syntax • Regular expressions • Context free grammars • syntax directed • traversals on the abstract syntax tree • later compiler phases? • Runtime? • There are tools that automatically generate semantic analyzer from specification(Based on attribute grammars)

More Related