Compiler Design
Attribute Grammars / Worked Example: Expression Evaluation
Worked Example: Expression Evaluation
Let us trace how an expression is parsed and evaluated using only synthesized attributes. We will use a standard arithmetic grammar with a synthesized attribute .val.
Grammar & Semantic Rules
| Production Rule | Semantic Rule (Synthesized .val) |
|---|---|
| L → E \n | L.val = E.val; print(L.val) |
| E → E_1 + T | E.val = E_1.val + T.val |
| E → T | E.val = T.val |
| T → T_1 * F | T.val = T_1.val * F.val |
| T → F | T.val = F.val |
| F → ( E ) | F.val = E.val |
| F → digit | F.val = digit.lexval |
Step-by-Step Trace of: 3 + 5 * 2
Here is how the compiler evaluates 3 + 5 * 2 during a bottom-up (postorder) traversal of the parse tree:
- Lexical Scan: Lexer yields the tokens:
digit(3),+,digit(5),*,digit(2). - First leaf reduction:
F → digit(3).
Calculation:F.val = digit.lexval = 3. - Promote term:
T → F.
Calculation:T.val = F.val = 3. - Initialize expression:
E → T.
Calculation:E.val = T.val = 3(Left subtree completed). - Second leaf reduction:
F → digit(5).
Calculation:F.val = 5. - Promote second term:
T_1 → F.
Calculation:T_1.val = 5. - Third leaf reduction:
F → digit(2).
Calculation:F.val = 2. - Multiplication reduction:
T → T_1 * F.
Calculation:T.val = T_1.val * F.val = 5 * 2 = 10. - Addition reduction:
E → E_1 + T.
Calculation:E.val = E_1.val + T.val = 3 + 10 = 13. - Halting step:
L → E \n.
Calculation:L.val = 13, triggering the print action.
The annotated parse tree showing the values flowing upwards:
L [val=13]
|
E [val=13]
/ | \
E [val=3] + T [val=10]
| / | \
T [val=3] T [val=5] * F [val=2]
| | |
F [val=3] F [val=5] digit [lexval=2]
| |
digit(3) digit(5)