1 / 20

Chapter 5

Chapter 5. Syntax-Directed Translation. Translation of languages guided by context-free grammars. Attach attributes to the grammar symbols. Values of the attributes are computed by semantic rules associated with the grammar productions. Two notations:

indiya
Télécharger la présentation

Chapter 5

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. Chapter 5 Syntax-Directed Translation

  2. Translation of languages guided by context-free grammars. • Attach attributes to the grammar symbols. Values of the attributes are computed by semantic rules associated with the grammar productions. • Two notations: -- Syntax–directed definitions: Each production has a set of semantic rules associated with it. --Translation Schemes: Embed the semantic actions within the productions. • Conceptually we parse the input token stream, build the parse tree and then traverse the tree as needed to evaluate the semantic rules. The rules may generate code, save information in the symbol table, issue error messages, etc.

  3. In some cases we don’t have to follow this outline literally. We may evaluate the rules during parsing. • Synthesized attribute: The value of the attribute at a parent node can be found from the attributes of its children. It can be evaluated by traversing the tree bottom-up. • Inherited attribute: The value of the attribute at a node can be found from the attributes at its parent node and/or its sibling nodes. Can be evaluated by traversing the tree top-down. • S-attributed definition: A syntax-directed definition where all attributes are synthesized (the “S” stands for synthesized).

  4. Production L En E  E1 + T E  T T  T1 * F T  F F  (E) F  digit Semantic Rules print(E.val) E.val := E1.val + T.val E.val := T.val T.val := T1.val * F.val T.val := F.val F.val := E.val F.val := digit.lexval Example: Simple desk calculator

  5. Example: Annotated parse tree for 3*5+4n L n E.Val = 19 E.Val = 15 + T.Val = 4 T.Val = 15 F.Val = 4 T.Val = 3 * F.Val = 5 digit.lexval = 4 F.Val = 3 digit.lexval = 5 digit.lexval = 3

  6. Example • Using inherited attributes to parse a declaration and add type information to the symbol table.

  7. Annotated Parse Tree for real, id1, id2, id3 D T.Type = real L.in = real real , id3 L.in = real , id2 L.In = real id1

  8. If all attributes are synthesized then a bottom – up parser can evaluate the attributes while it parses. • Add attribute fields to the nonterminals on the stack. • Before each reproduction apply the semantic rule associated with the production. • E.g. Assume the semantic rule associated with the A  XYZ production is : A.a := f (X.x, Y.y, Z.z).

  9. Before the reduction the parser stack looks like: • After the reduction the parser stack looks like:

  10. Many top-down and bottom-up translation methods can be obtained by applying a depth-first visit procedure to the root of the parse tree: Procedure dfvisit(n : node); Begin for each child m of n, from left to right do begin evaluate inherited attributes of m; dfvisit(m) end; evaluate synthesized attributes of n End.

  11. This method works as long as the inherited attributes of each child node just depend on attributes of the parent node and the children to its left; there is no dependence on attributes of children to the right. • A syntax-directed definition is L-attributed if each inherited attribute of Xj on the right side of a production A  x1, X2,…., Xn depends only on the attributes of X1, X2,…, Xj-1 to the left of Xj in the production and the inherited attributes of A. • The L stands for left. • There are no restrictions on the synthesized attributes of Xj so every S-attributed definition is L-attributed.

  12. Top-Down Translation • E.g. E  E1 + T {E.val := E1.val + T.val} E  E1 – T {E.val := E1.val – T.val} E  T {E.val := T.val} T  (E) {T.val := E.val} T  num {T.val := num.val} • To eliminate the left-recursion we add a nonterminal R to the grammar with an inherited attribute, R.i and a synthesized attribute, R.s. • The transformed translation scheme is:

  13. E  T {R.i := T.val} R {E.val := R.s} R  + T {R1.i := R.i + T.val} R1 {R.s := R1.s} R  - T {R1.i := R.i – T.val} R1 {R.s := R1.s} R  ε {T.val := num.val} • In general suppose the translation scheme has the folowing left-recursive structure: A  A1 Y {A.a := g (A1.a, Y.y)} A  X {A.a := f (X.x)} • f and g are arbitrary functions and A.a, A1.a, X.x and Y.y are synthesized attributes. • Add a new nonterminal R, with a synthesized attribute R.s and an inherited attribute, R.i.

  14. To eliminate the left-recursion the translation scheme is transformed to: A  X {R.i := f (X.x)} R {A.a := R.s} R  Y {R1.i := g (R.i, Y.y)} R1 {R.s := R1.s} R  ε {R.s := R.i} • E.g. A left recursive translation scheme for generating syntax trees: E  E1 + T {E.nptr := mknode (‘+’, E1.nptr, T.nptr)}

  15. E  E1 - T {E.nptr := mknode (‘-’, E1.nptr, T.nptr)} E  T {E.nptr := T.nptr} T  (E) {T.npte := E.nptr} T  id {T.nptr := mkleaf (id, id.entry)} T  num {T.nptr := mkleaf (num, num.value)}

  16. Eliminating left recursion gives : E  T {R.i := T.nptr} r {E.nptr := R.s} R  + T {R1.i := mknode (‘+’, R.i, T.nptr)} R1 {R.s := R1.s} R  - T {R1.i := mknode (‘-’, R.i, T.nptr)} R1 {R.s := R1.s} R  ε {R.s := R.i} T  (E) {T.nptr := E.nptr} T  id {T.nptr := mkleaf (id, id.entry)} T  num {T.nptr := mkleaf (num, num.value)}

  17. The technique to write predictive parsers using recursive procedures can be modified to include the actions of a translation scheme. • Use recursive functions instead of recursive procedures to pass the values of attributes. • For each nonterminal write a recursive function. • The function accepts the values of the imherited attributes in its formal parameters and returns the values of the synthesized attributes. • If there are multiple synthesized attributes their values can be returned in a record or a pointer to a record.

  18. Example • Consider three nonterminals E, R and T. Write three recursive functions. • E and T have no arguments. • Function E handles the production: E  T {R.i := T.nptr} R {E.nptr := R.s} function E : tree_node; begin e := R (T) end;

  19. Function R handles three productions: R  + T {R1.i := mknode (‘+’, R.i, T.nptr)} R1 {R.s := R1.s} R  - T {R1.i := mknode (‘-’, R.i, T.nptr)} R1 {R.s := R1.s} R  ε {R.s := R.i}

  20. function R (I : tree_node) : tree-node; var nptr, i1 : tree_node; begin if lookahead = ‘+’ then begin match (‘+’); nptr := T; i1 := mknode (‘+’, I nptr); R := R (i1) end else if lookahead = ‘-’ then begin match (‘-’); nptr := T; i1 := mknode (‘-’, I, nptr); R := R (i1) end else R := i end;

More Related