400 likes | 789 Views
Attribute Grammars. In syntax-directed semantics (or semantics-directed syntax ), attributes are associated directly with the grammar symbols in the language (the terminal and nonterminal symbols)
E N D
Attribute Grammars • In syntax-directed semantics (or semantics-directed syntax), attributes are associated directly with the grammar symbols in the language (the terminal and nonterminal symbols) • If X is a grammar symbol and a is an attribute associated to X, then we write X.a for the value of a associated to X
Attribute Grammars… • Given a collection of attributes, a1,…,ak, the principle of syntax-directed semantics implies that for each grammar rule: A X1 X2 … Xn the Xi.aj of each grammar symbol Xi are related to the values of the attributes of the other symbols in the rule • This relationship is specified by an attribute equation or semantic rule
Attribute Grammars… • Formally, Xi.am = fim(X0a1,…,X0ak, X1.a1,… Xn.ak) • In other words, the resulting attribute is a function of all the attributes associated with the symbols on the right-hand-side of a production
Attribute Grammars… • An attribute grammar for the attributes a1…ak is the collection of all such equations for all productions of the grammar of the language • Looked at this formally, attribute grammars may appear to be quite complicated • In practice, however, they’re not…
Attribute Grammars… • Usually the functions are very simple, and the number of symbols that actually contribute in an such equation is quite small • Typically attribute grammars are written in tabular form, with each grammar rule listed with the set of attribute equations, or semantic rules associated to that rule, as follows…
Attribute Grammars… Grammar RuleSemantic Rules Rule 1 Assoc’d attr. eqn. . . . Rule 2 Assoc’d attr. eqn. . . . . . . . . .
Unsigned Numbers • Consider this simple grammar for unsigned numbers: number number digit | digit digit 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8| 9 • The most significant attribute of a number is its value • For example, the rule: digit 0 implies that digit has value zero • I.e., digit.val = 0
Unsigned Numbers… • This is true for each of the ten digit rules, with corresponding values • Now, if a number is derived using the rule: number digit, then the number contains but a single digit, and its value should be: number.val = digit.val
Unsigned Numbers… • If a number is derived using the rule: number number digit, then we must express the relationship between the value of the symbol on the LHS of the grammar rule and the values of the symbols on the RHS of the grammar rule
Unsigned Numbers… • We’ll need a way to distinguish the number on the LHS from the number on the RHS – we’ll use subscripts for this purpose: number1 number2 digit • Now we can write: number1.val 10*number2.val+digit.val
Unsigned Numbers… • The complete attribute grammar for our productions is:
Simple Integer Arithmetic • Consider this grammar for simple integer arithmetic expressions:
Simple Integer Arithmetic… • An attribute grammar for our productions is:
Simple Integer Arithmetic… • Using these syntax rules and semantics rules, one can create a parse tree for (34 – 3) * 42, and then express the semantics associated with each node by executing the appropriate semantics equations
(34 – 3) * 42 Simple Integer Arithmetic…
Extensions to Attribute Grammars • It should almost go without saying that the (meta-)language(s) you use in order to specify the attributes of an attribute grammar can be quite general • The “code” must be unambiguous, algorithmic, could be in almost any programming language, could be in some form of pseudocode, etc…
Extensions and Simplifications • The syntax that is used by an attribute grammar does NOT have to be the identical syntax that is used for parsing (although most frequently, in fact, it is…)
Extensions and Simplifications… • For example, consider the following grammar for expressions… It is ambiguous, and it’s the one we started with before removing the ambiguities exp=exp + exp |exp – exp |exp * exp|( exp )|number
Extensions and Simplifications… • Here’s an attribute grammar based on that grammar:
Extensions and Simplifications… • You can see quite easily that the ambiguity doesn’t “hurt” at all • And, this ambiguous grammar is simpler than the unambiguous one that we came up with for expressions
Synthetic and Inherited Attributes • Rule-based attribute evaluation depends upon an explicit or implicit traversal of the parse tree or the syntax tree • Different kinds of traversals vary in power in terms of the kinds of attribute dependencies that can be handled
Synthetic and Inherited Attributes… • An attribute is synthesized if all its dependencies (properties) point from child to parent in the parse tree • For such a situation, it is natural to think of moving from bottom up in order to propagate the attribute information
Synthetic and Inherited Attributes… • The expression attribute grammar that we’ve looked at is a fine example of synthetic attributes
Synthetic and Inherited Attributes… • An attribute that is not synthesized is called an inherited attribute • Such attributes typically descend from parent to children • In fact, inheritance (using this definition) can move from sibling to sibling • The base (radix) and the number of significant digits are good examples of inherited attributes
Synthetic and Inherited Attributes… • The natural traversal order in this situation is top-down rather than bottom-up • Of course, information can flow in both directions regardless of the kind of traversal – using suitable coding…
Computing Attributes • The actual mechanisms involved in computing the attributes (computing the attribute values) in an attribute grammar may take several different forms
Computing Attributes… • Storing attribute information in the parse/syntax tree • Here one uses the nodes of the tree to store the various attribute values • As one traverses the tree (one or more times) additional information is computed and stored there • A simple example of this is the storing of type information for a variable
Computing Attributes… • Using parameters and return values • Here one uses the input (and output) parameters (and return values) of the functions that one calls as the semantics of the attribute grammar to store the attribute value information • This approach is much more “dynamic” and does not lend itself as easily to making multiple passes over the parse/syntax tree
Computing Attributes… • A simple example of this approach is the calculation of the value of a number in a given radix – the radix value is an inherited attribute, and it’s easily passed to sub-functions during the evaluation of the attribute grammar
Computing Attributes… • Using external data structures to store attribute values • Here one uses tables, lists, trees, etc., to store the attribute value information • This is the most general and most powerful approach • Building and maintaining a symbol table is a good example of this approach
Computing Attributes While Parsing • What about computing attributes during the parsing process – and avoiding the one or more passes over the syntax tree to calculate the attribute values? • This certainly is possible – especially for simple languages with simple semantics
Computing Attributes While Parsing… • Some programming languages fall into the category of such appropriate cases • But, if one wants to do a good job of optimization (as one really should/must do in production compilers), then having attributes around (statically) during code generation “is a must”