240 likes | 324 Views
Compiler design. Table-driven syntax-directed translation. Top-down table-driven syntax-directed translation. Top-down table-driven syntax-directed translation. Augment the parser algorithm to implement attribute migration.
E N D
Compiler design Table-driven syntax-directed translation Joey Paquet, 2000-2017
Top-down table-driven syntax-directed translation Joey Paquet, 2000-2017
Top-down table-driven syntax-directed translation • Augment the parser algorithm to implement attribute migration. • Introduce additional symbols in the grammar’s right hand sides for semantic actions that process semantic attributes. • The grammar becomes an attribute grammar. • When such a symbol is on top of the stack, execute the semantic action. • Problem: the attributes have to be pushed and popped at a different pace compared to symbols on the parsing stack. • Solution: use an additional stack (the semantic stack) to store the attributes. • The semantic actions typically pop semantic records from the semantic stack, do some processing, then push a semantic record on the stack. Joey Paquet, 2000-2017
Top-down table-driven syntax-directed translation Joey Paquet, 2000-2017
E' Attribute migration id1+id2*id3$ E B:{Es = E's} A:{E'i = Ts} T E' D:{E's = E's} G:{Ts = T's} C:{E'i = E'i+Ts} T + G:{Ts = T's} F T' E:{E's = E'i} F:{T'i = Fs} F T' J:{T's = T'i} F:{T'i = Fs} K:{Fs = id.val} K:{Fs = id.val} I:{T's = T's} id id F T' * H:{T'i = T'i * Fs} J:{T's = T'i} K:{Fs = id.val} id Joey Paquet, 2000-2017
E' Attribute migration id1*id2+id3$ E B:{Es = E's} A:{E'i = Ts} T E' D:{E's = E's} G:{Ts = T's} C:{E'i = E'i+Ts} T + F T' E:{E's = E'i} F:{T'i = Fs} G:{Ts = T's} I:{T's = T's} K:{Fs = id.val} id F:{T'i = Fs} F T' F T' * H:{T'i = T'i * Fs} J:{T's = T'i} J:{T's = T'i} K:{Fs = id.val} K:{Fs = id.val} id id Joey Paquet, 2000-2017
Parsing example using semantic stack for attribute migration Joey Paquet, 2000-2017
Parsing example using semantic stack for attribute migration Joey Paquet, 2000-2017
Top-down syntax-directed translation grammar transformation Joey Paquet, 2000-2017
a+b*c E E TE’ E’ +TE’ | T FT’ T’ FT’ | F id T1 E’1 T’1 E’2 F1 + T2 id (va : ) F2 T’2 T’3 id (vb : ) F3 * id (vc : ) Top-down syntax-directed translation • Problem: Left recursion is not allowed in predictive top-down parsing. We must transform the grammar. We saw how to transform a context-free grammar to remove left recursions. How is an attribute grammar transformed? Joey Paquet, 2000-2017
With left recursions E E+T {Es = Es+Ts} E T {Es = Ts} T T*F {Ts = Ts*Fs} T F {Ts = Fs} F id {Fs = lookup(id)} a+b*c E {Es = Es + Ts} E + T {Es = Ts} {Ts = Ts * Fs} T T F {Ts = Fs} * {Es = Ts} {Fs = lookup(c)} F F {Fs = lookup(a)} id (vc : ) {Fs = lookup(b)} id (va : ) id (vb : ) Joey Paquet, 2000-2017
Without left recursions E T{E’i=Ts}E’{Es=E’s} E’ +T{E’i=E’i+Ts}E’{E’s=E’s} E’ {E’s=E’i} T F{T’i=Fs}T’{Ts=T’s} T’ F{T’i=T’i*Fs}T’{T’s=T’s} T’ {T’s=T’i} F id{Fs=lookup(id)} a+b*c E {Es = E’s} T E’ {E’i = Ts} {E’s = E’s} {Ts = T’s} + F T’ T E’ {T’i = Fs} {E’i = E’i+Ts} {T’s = T’i} {E’s = E’i} {Fs = lookup(a)} {Ts = T’s} id (va : ) F T’ {T’i = Fs} {T’s = T’s} {Fs = lookup(b)} * id (vb : ) F T’ {T’i = Fs} {T’s = T’i} {Fs = lookup(c)} id (vc : ) Joey Paquet, 2000-2017
Top-down syntax-directed translation: attribute grammar transformation • Solution: The grammar is transformed as we saw before to eliminate left recursions in a context-free grammar. • But when we introduce attributes, the transformation spreads some attributes over multiple rules, thus introducing the need for attribute inheritance. The following transformation should be applied: A1 A2 A1 Q1 A3 Q2 Q3 Q4 A1 A2 {A1s=f(A2s, )} A1 {Q1i=g()}Q1{A1s=Q1s} A3 {A3s=g()} Q2 {Q3i=f(Q2i, )}Q3{Q2s=Q3s} Q4 {Q4s=Q4i} Joey Paquet, 2000-2017
where: A1,2,3 E1,2,3 Q1,2,3,4 E’1,2,3,4 Ts Ts f(As, ) +(Es,Ts) g() Ts Top-down syntax-directed translation: attribute grammar transformation A1 A2 A1 Q1 A3 Q2 Q3 Q4 E1 E2+T1E1 T2E1’ E3 T2 E2’ +T1E3’ E4’ A1 A2 {A1s=f(A2s,)} A1 {Q1i=g()}Q1{A1s=Q1s} A3 {A3s=g()} Q2 {Q3i=f(Q2i,)}Q3{Q2s=Q3s} Q4 {Q4s=Q4i} E1 E2+T1{E1s=E2s+T1s} E1 T2{E1’i=T2s}E1’{E1s=E1’s} E3 T2{E3s=T2s} E2’ +T1{E3’i=E2’i+T1s}E3’{E2’s=E3’s} E4’ {E4’s=E4’i} Joey Paquet, 2000-2017
Bottom-up syntax-directed translation Building an abstract syntax tree using syntax-directed translation Joey Paquet, 2000-2017
Bottom-up syntax-directed translation • Syntax-directed translation is much easier to implement bottom-up than top-down. • Synthetized attributes are propagated from the bottom-up, so we have this propagation mechanism for free in a bottom-up parse • The presence of inherited attributes generally comes from the elimination of left-recursions and ambiguities. As these are not a problem in bottom-up parsing, we seldom need to process inherited attributes in bottom-up translation • In bottom-up translation, the parse and semantic stacks move in synchronism, so there is no need for an additional semantic stack. • Semantic rules are triggered as handles are popped from the stack Joey Paquet, 2000-2017
Bottom-up syntax-directed translation: building an abstract syntax tree • The tree is built by grafting subtrees (handles) to the nodes. • The semantic actions build the subtrees by grafting generally through simple pointer manipulations. • Generally, all nodes (internal or leaves) are of the same type. Differences can be managed by using a variant record structure: nodeKind = (internal,leaf) treeNode = record token : tokenType case kind : nodeKind of internal : (left,right : *treeNode) leaf : (location : integer) end Joey Paquet, 2000-2017
nodePtr makeLeaf(tok tokenType, location integer){ leafPtr = new(nodePtr) leafPtr.kind = leaf leafPtr.token = tok leafPtr.location = location return leafPtr } nodePtr makeTree(op tokenType, rightSon,leftSon nodePtr){ rootPtr = new(nodePtr) rootPtr.kind = internal rootPtr.token = op rootPtr.left = leftSon rootPtr.right = rightSon return rootPtr } Bottom-up syntax-directed translation: building an abstract syntax tree • We need a makeTree function that will be used to create subtrees and a makeLeaf function that will be used to create tree leaves: Joey Paquet, 2000-2017
Bottom-up syntax-directed translation: building an abstract syntax tree Joey Paquet, 2000-2017
Bottom-up syntax-directed translation: building an abstract syntax tree Joey Paquet, 2000-2017
E4 + + + + + id1 id1 id1 id1 id1 = E2 E2 E5 S E1 E1 E4 * * * id2 id2 id2 id2 id2 id3 id3 id3 E5 E3 E6 E3 E6 id4 Bottom-up syntax-directed translation: building an abstract syntax tree 5 8 10 11 E E B D 14 15 16 E C A Joey Paquet, 2000-2017
Bottom-up syntax-directed translation • We can use a similar process to build other kinds of intermediate representations. • A similar process can also be used to generate target code directly, but that diminishes the possibilities of high-level code optimization. • A similar technique can also be adopted by top-down parsing to build syntax trees as an intermediate representation. Joey Paquet, 2000-2017
References • Fischer, Cytron, Leblanc. Crafting a Compiler, Chapter 7. Addison-Wesley. 2010. • Robert Paul Corbett. Static Semantics and Compiler Error Recovery.PhD thesis, University of California Berkeley. 1985. Joey Paquet, 2000-2017