Attribute Grammars

Notes by Kshama Pawar and Bhargavi Panjala
Attribute Grammars
Context Sensitive Languages:
Language which has variables and its correct usage depends on the context.
Var i, j :: integer;
Var b:: Boolean;
i swap j
Æ This statement is valid since i and j are of same type and can be swapped.
i swap b
Æ This statement is invalid since i and b are of different type and cannot be swapped.
To solve context sensitive problems we use Attribute grammars. An Attribute grammar is a context free
grammar that has been extended to provide context sensitive information by appending attributes to some
of its non terminals.
•
•
•
Each attribute has a domain of possible values.
An attribute may be assigned values from its domain during parsing.
Attributes can be given values and evaluated in conditions.
Two classes of Attributes
•
•
Synthesized attribute – An attribute that gets its values from the attribute attached to the
children of its non terminal.
Inherited attribute – An attribute that gets its values from the attributes attached to the parent
(or siblings) of its non terminal.
Example:
Context Sensitive Language:
L1 = { anbncn | n ≥ 1}
No context free grammar generates L1.
An attempt:
<s> Æ <as> <bs> <cs>
<as> Æ a | <as> a
<bs> Æ b | <bs> b
<cs> Æ c | <cs> c
This context free grammar generates the language
a+b+c+ = { apbqcr | p,q,r ≥ 1}
Using an Attribute Grammar:
•
•
•
•
A context free grammar in BNF.
Defines attributes on same non terminals.
Rules are used for evaluation of attributes
Conditions are imposed that make a given program right or wrong.
Attribute grammar is used to solve context sensitive problems of L1 = { anbncn | n ≥ 1}.
Attach a synthesized attribute, count, to each of the non terminals : <as>, <bs>, <cs>
Impose a condition on first production:
count <as> = count <bs> = count <cs>
<as> = a
count <as> Å |
| <as1>a
Count <as> Å count<as1> + 1
<bs> = b
count <bs> Å |
| <bs1>b
Count <bs> Å count<bs1> + 1
<cs> = c
count <cs> Å |
| <cs1>c
count <cs> Å count<cs1> + 1
Parse Tree:
Example 2:
L2 = { anbkcn -k | n ≥ 2, 1 ≤ k ≤ n-1}
Attach a synthesized attribute, count, to each of the non terminals : <as>, <bs>, <cs>
Impose a condition on first production:
count <as> = count <bs> - count <cs>
<as> = a
count <as> Å |
| <as1>a
count <as> Å count<as1> + 1
<bs> = b
count <bs> Å |
| <bs1>b
count <bs> Å count<bs1> + 1
<cs> = c
count <cs> Å |
| <cs1>c
count <cs> Å count<cs1> + 1
Parse Tree:
Another example for attribute grammar :
L1 = { anbn | n ≥ 1}
<S>
<as>
<bs>
::= <as> <bs>
::= a | <as1> a
::= b | <bs1> b
This context-free grammar generates the language a+b+ = { ambk | m ≥ 1, k ≥ 1}, where
the number of a’s and b’s might not be the same. To overcome this we define attributes
and conditions for the above grammar.
Attributes: As we are considering the number of a’s and b’s in this grammar we define a
attribute “count”.
count <as> is defined as an integer that denotes the number of a’s
count <bs> is defined as an integer that denotes the number of b’s
Condition:
count<as> = count<bs>
Rule of evaluation of attributes: changes to BNF grammar above to:
<S>
::=
<as> <bs>
Condition: count<as> = count<bs>
<as>
::=
a
|
count(<as>) ← 1
<bs>
::=
b
count(<bs>) ← 1
<as1> a
count(<as>) ← count(<as1>) + 1
|
<bs1> b
count(<bs>) ← count(<bs1>) + 1
Dangling ‘else’ problem:
Example: if B1 then S1 if B2 then S2 else S3
else is executed if
1. B1 Λ not B2
2. not B1
Similar, but simple example of the above problem
a( ab ) √
aab
(( aa )b)
The parse trees for the above example: aab
<S>
<S>
<S>
<S>
<S>
a
<S>
a
<S>
<S>
<S>
<S>
a
a
b
b
There is more than one parse tree for a given sentence in the language hence it is known
as Ambiguous language.
For every non-terminal N for every production rule in which N appears in the LHS make
sure you give value to every synthesized attribute for every path the rule may follow.
For every non-terminal N, for every instance in the RHS in which N appears make sure to
give a value to every inherited attribute of N.