Download Semantic Analysis and Attribute Grammars in Compiler Design and more Study notes Programming Languages in PDF only on Docsity! 1 1 Programming Languages Tevfik Koşar Lecture - IX February 14th, 2006 2 Roadmap • Semantic Analysis – Role of Semantic Analysis – Static vs Dynamic Analysis – Attribute Grammars – Evaluating Attributes • Decoration of Parse Trees • Synthesized and Inherited Atributes 2 3 Role of Semantic Analysis • Following parsing, the next two phases of the "typical" compiler are – semantic analysis – (intermediate) code generation • The principal job of the semantic analyzer is to enforce static semantic rules – constructs a syntax tree (usually first) – information gathered is needed by the code generator 4 Static vs Dynamic Semantics • Static Semantics – At compile time • Type checking • Dynamic Semantics – At runtime • Division by zero • Out-of-bound indexing an array 5 9 Attribute Grammars • We can turn this into an attribute grammar as follows (similar to Figure 4.1): E → E + T E1.val = E2.val + T.val E → E – T E1.val = E2.val - T.val E → T E.val = T.val T → T * F T1.val = T2.val * F.val T → T / F T1.val = T2.val / F.val T → F T.val = F.val F → - F F1.val = - F2.val F → (E) F.val = E.val F → const F.val = C.val 10 Attribute Grammars • The attribute grammar serves to define the semantics of the input program • Attribute rules are best thought of as definitions, not assignments • They are not necessarily meant to be evaluated at any particular time, or in any particular order, though they do define their left-hand side in terms of the right-hand side 6 11 Evaluating Attributes • The process of evaluating attributes is called annotation, or DECORATION, of the parse tree [see Figure 4.2 for (1+3)*2] – When a parse tree under this grammar is fully decorated, the value of the expression will be in the val attribute of the root • The code fragments for the rules are called SEMANTIC FUNCTIONS – Strictly speaking, they are cast as functions, e.g., E1.val = sum (E2.val, T.val), cf., Figure 4.1 12 Evaluating Attributes 7 13 Evaluating Attributes • This is a very simple attribute grammar: – Each symbol has at most one attribute • the punctuation marks have no attributes • These attributes are all so-called SYNTHESIZED attributes: – They are calculated only from the attributes of things below them in the parse tree 14 Evaluating Attributes • In general, we are allowed both synthesized and INHERITED attributes: – Inherited attributes may depend on things above or to the side of them in the parse tree – Tokens have only synthesized attributes, initialized by the scanner (name of an identifier, value of a constant, etc.). – Inherited attributes of the start symbol constitute run-time parameters of the compiler 10 19 Evaluating Attributes– Example • Attribute grammar: FT1 → * F FT2 FT1.val = FT2.val FT2.st = FT1.st * F.val FT1 → / F FT2 FT1.val = FT2.val FT2.st = FT1.st / F.val FT → ε FT.val = FT.st F1 → - F2 F1.val = - F2.val F → ( E ) F.val = E.val F → const F.val = C.val 20 Evaluating Attributes– Example 11 21 Evaluating Attributes– Example • Attribute grammar in Figure 4.3: – This attribute grammar is a good bit messier than the first one, but it is still L-ATTRIBUTED, which means that the attributes can be evaluated in a single left-to-right pass over the input – In fact, they can be evaluated during an LL parse – Each synthetic attribute of a LHS symbol (by definition of synthetic) depends only on attributes of its RHS symbols 22 Evaluating Attributes – Example • Attribute grammar in Figure 4.3: – Each inherited attribute of a RHS symbol (by definition of L-attributed) depends only on • inherited attributes of the LHS symbol, or • synthetic or inherited attributes of symbols to its left in the RHS – L-attributed grammars are the most general class of attribute grammars that can be evaluated during an LL parse 12 23 Evaluating Attributes • There are certain tasks, such as generation of code for short-circuit Boolean expression evaluation, that are easiest to express with non-L-attributed attribute grammars • Because of the potential cost of complex traversal schemes, however, most real-world compilers insist that the grammar be L- attributed