CIS 324: Language Design and Implementation Syntax Directed Translation 1. Syntax Directed Definitions There are two notations for associating semantic actions with productions: syntax-directed definitions and translation schemes. The Syntax-Directed Definitions are a mechanism for specifying translations for the programming language constructs. A syntax-directed definition specifies the translation of a construct in terms of the attributes associated with its syntactic components. A syntax-directed definition uses a context-free grammar to specify the structure of the input: with each grammar symbol it associates a set of attributes; and with each production a set of semantic rules for computing the values of the attributes associated with the symbols in it. A Translation Scheme is like a syntax-directed translation except that the order of evaluation of the semantic rules is explicitly shown. A translation scheme is a context-free grammar in which program fragments called semantic actions are embedded within the right sides of the productions. Translation schemes show the order in which the semantic rules has to be evaluated, so they show implementation details. With both syntax-directed definitions and translation schemes the input token stream is parsed, the parse tree is constructed, and next it is traversed in order to execute the corresponding semantic actions. The evaluation of the semantic actions could be code generation, storing symbol table information, or printing error messages. 2. Synthesized and Inherited Attributes Both syntax-directed definitions and translation schemes has associated sets of attributes with each grammar symbol, which indicate a relevant semantic action. An attribute can represent various things, such as: a string, a number, a memory address, etc.. There are two kinds of attributes: synthesized and inherited. The value of a synthesized attribute is computed from the values of attributes at the children nodes of the current in the parse tree. The value of an inherited attribute is computed from the values of attributes at the parent nodes of the current in the parse tree. Example: This a syntax-directed definition of a language for implementing an arithmetic calculator (using synthesized attributes) Production L En E E1 + T E T T T1 * F T F F (E) F digit Semantic rule 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 Using the above grammar there can be constructed the following parse tree with synthesized attributes for the arithmetic expression: 3 * 5 + 4n L n E.val=19 E.val=15 + T.val=15 T.val=3 F.val=3 digit .lexval=3 * T.val=4 F.val=4 F.val=5 digit .lexval=5 digit .lexval=4 Example: This a syntax-directed definition for specifying declarations in a programming language (using inherited attributes) Production D TL T int T real L L1 , D L id Semantic rule L.in := T.type T.type := integer T.type := real L1.in := L.in addtype( id.entry, L.in ) addtype( id.entry, L.in ) Using the above grammar there can be constructed the following parse tree with inherited attributes for the expression: real id1, id2, id3 D L.in=real T.type=real real L.in=real L.in=real , id1 , id2 id3 3. Syntax Trees and Parse Trees Example: Consider the following syntax-directed Production E E1 + T E E1 - T E T T (E) T id T num Semantic rule E.nptr := mknode( '+', E1.nptr, T.nptr) E.nptr := mknode( '-', E1.nptr, T.nptr) E.nptr := T.nptr T.nptr := E.nptr T.nptr := mkleaf( id, id.entry ) T.nptr := mkleaf( num, num.val ) The figure below illustrates a syntax tree and a parse tree drawn with dotted lines for the expression: a - 4 + c E.nptr E.nptr E - T.nptr id id T.nptr + T.nptr num id + id a num 4 c