Semantic Analysis and Attribute Grammars in Compiler Design, Study notes of Programming Languages

The role of semantic analysis in compiler design, focusing on attribute grammars as a formal framework for decorating parse or syntax trees. Static vs dynamic semantics, the process of evaluating attributes, and the difference between synthesized and inherited attributes. An example of an ll(1) grammar and its corresponding attribute grammar is provided.

Typology: Study notes

Pre 2010

Uploaded on 08/30/2009

koofers-user-jcf
koofers-user-jcf 🇺🇸

10 documents

1 / 12

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
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
pf3
pf4
pf5
pf8
pf9
pfa

Partial preview of the text

Download Semantic Analysis and Attribute Grammars in Compiler Design and more Study notes Programming Languages in PDF only on Docsity!

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

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

7

Attribute Grammars

  • We'll start with decoration of parse trees, then

consider syntax trees

  • Consider the following LR (bottom-up) grammar

for arithmetic expressions made of constants,

with precedence and associativity:

8

Attribute Grammars

E → E + T
E → E – T
E → T
T → T * F
T → T / F
T → F
F → - F
F → (E)

F → const

  • This says nothing about what the program

MEANS

9

Attribute Grammars

  • We can turn this into an attribute grammar as

follows (similar to Figure 4.1):

E → E + T E 1 .val = E 2 .val + T.val E → E – T E 1 .val = E 2 .val - T.val E → T E.val = T.val T → T * F T 1 .val = T 2 .val * F.val T → T / F T 1 .val = T 2 .val / F.val T → F T.val = F.val F → - F F 1 .val = - F 2 .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

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

15

Evaluating Attributes

  • The grammar above is called S-ATTRIBUTED

because it uses only synthesized attributes

  • Its ATTRIBUTE FLOW (attribute dependence

graph) is purely bottom-up

  • It is SLR(1), but not LL(1)
  • An equivalent LL(1) grammar requires inherited

attributes:

16

LL(1) Grammar

  • Example 1:

expr  const expr_tail

expr_tail  - const expr_tail | ε

Create the parse tree for 9 – 4 – 3 and evaluate it.

19

Evaluating Attributes– Example

  • Attribute grammar:

FT 1 → * F FT 2 FT 1 .val = FT 2 .val

FT 2 .st = FT 1 .st * F.val

FT 1 → / F FT 2 FT 1 .val = FT 2 .val

FT 2 .st = FT 1 .st / F.val

FT → ε FT.val = FT.st

F 1 → - F 2 F1.val = - F2.val

F → ( E ) F.val = E.val

F → const F.val = C.val

20

Evaluating Attributes– Example

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