160 likes | 300 Views
CSC 425– Compiler Design I Fall, 2011. November 1, 2011 Chapter 5 Syntax-Directed Translation. Strategy for Chapter 5. Authors’ course slides do not dwell on details in the textbook any more than I do. Syntax-Directed Translation actually deals with propagating info around the parse tree.
E N D
CSC 425– Compiler Design IFall, 2011 November 1, 2011 Chapter 5 Syntax-Directed Translation
Strategy for Chapter 5 • Authors’ course slides do not dwell on details in the textbook any more than I do. • Syntax-Directed Translation actually deals with propagating info around the parse tree. • The textbook obsesses somewhat with minimizing passes over the parse tree for historical cost reasons. • Multiple passes over the parse tree are OK. • We will spend our attention on defining some central nomenclature and concepts.
Syntax-Directed Definition • Associates semantic rules with productions. • A semantic rule contain expressions and assignments over attribute values of grammar symbols. • E -> E1 + T E.code = E1.code || T.code || ‘+’ • By including formal semantic rules as part of the grammar language used by the parser generator, the goals are to formalize and automate semantic processing of sentences. • A SDD without side effects is an Attribute Grammar.
Syntax-Directed Translation Scheme • Embeds semantic actions within productions. • Semantic action is code outside of the grammar language used by the parser generator. • {{ result.appendSection(scoreSection) }} • These can emulate attribute manipulation using object fields, side-effect-free discipline. • But, the compiler generator cannot reason about or ensure integrity of the semantic actions. • This is the approach of most industrial-strength tools. • It is potentially a disciplined, extensible approach.
Synthesized and Inherited Attributes • A synthesized attribute for nonterminal A at parse tree node N, where A is the head of the production, is defined in terms of the attribute values of N and its children. Terminals have only synthesized attributes. • An inherited attribute for nonterminal B at N is defined by a semantic rule associated with the production at the parent of N, with B in the production’s body. • Defined using attribute values of N’s parent, N, and N’s siblings, typically, N’s left siblings in a production.
Synthesized Attributes in YAPPS2 and PLY • Semantic actions can collect the bottom-up attributes initiated at the terminals and structured at the nonterminals after it has parsed them – completed deriving the nonterminal’s productions – in YAPPS2. • Semantic actions can collect the bottom-up attributes when it reduces PLY productions. • This is what our semantic actions have been doing.
Inherited Attributes in YAPPS2 • Nonterminal<<Attribute>> notation in YAPPS2 allows semantic actions to pass inherited attributes to the right-and-down in the grammar after deriving these attributes in semantic actions interleaved in productions. • yapps2/parsedesc.g • Tokens Rules<<Tokens>> passes parsed token definitions to parser for rule definitions. • A symbol table is technically a side effect.
Inherited Attributes in PLY • ply-3.0/doc/ply.html section 6.11 Embedded Actions • Normally PLY runs semantic actions after the entire left-hand-side is reduced. • Embedding an ε-matching marker nonterminal in the right hand side of a production allows its semantic actions to access attributes in the right hand side of the embedding production. • OR, reduction of symbols appearing in a right hand side can build a data structure that mirrors their reduction.
Inherited attributes for passing parameters to “partial expressions” • Textbook example, Figure 5.4., page 308 T -> F T’ T’.inh = F.val T.val = T’.syn T’ -> * F T1’ T1’.inh = T’.inh x F.val T’.syn = T1’.syn T’ = epsilon T’.syn = T’.inh F -> digit F.val = digit.lexval
Translate this YAPPS2 to BNF • yapps2/examples/calc.g rule expr<<V>>: factor<<V>> {{ n = factor }} ( "[+]" factor<<V>> {{ n = n+factor }} | "-" factor<<V>> {{ n = n-factor }} )* {{ return n }} # A factor is the product and division of terms rule factor<<V>>: term<<V>> {{ v = term }} ( "[*]" term<<V>> {{ v = v*term }} | "/" term<<V>> {{ v = v/term }} )* {{ return v }}
Dependency Graph • Synthesized dependency edges go up, inherited go down (and hopefully to right). • Cycles are undefined. • A topological sort of a graph finds at least one ordering where dependencies are not reversed. • Right-to-left dependencies require subsequent traversals of the annotated parse tree.
S-Attributed, L-Attributed Definitions • A SDD is S-attributed if every attribute is synthesized. • An SDD is L-attributed if every attribute is • Synthesized, or • Inherited, such that, for a production • A -> X1 X2 . . . Xn, to find inherited attribute Xi.a, use: • Inherited attributes from the head A. • Inherited or synthesized attributes from X1 .. Xi-1 • Inherited or synthesized attributes of this Xi that entail no cycles.
Syntax-directed Translation Schemes • Postfix Translation Schemes place all semantic actions at the right ends of production bodies. • ply-3.0/example/calc/calc.py • Postfix translation can generate code for a virtual stack machine by generating code to push constants and variable, and to pop-arguments-apply-and-push result for operators.
L-Attributed SDDs and LL Parsing • In a table-driven LL(1) parser, in addition to records representing terminals and nonterminals, the parser stack will hold the following. • Action records represent actions to be executed. • Synthesize records hold synthesized attributes for nonterminals. • In recursive descent (YAPPS2) just use parameters & return values of parsing functions.
Miscellaneous • Can we handle L-Attributed SDDs on LR Grammars? (p. 348) • “We cannot.” • We reach the strategy of “build the parse tree first and then perform the translation.” • Textbook does examine strategies for marker terminals. • Left recursion for LR grammars can make it easier to avoid inherited attributes.
Disciplined Software Engineering • Applying principles of functional programming, where possible, assists in making semantic actions more rigorous. • Side-effect-free data structure manipulation helps in safe construction and maintenance of parse trees. • Applying principles of object-oriented programming, where possible, assists in making semantic actions rigorous, extensible. • Use encapsulated attributes and orthogonal methods.