1 compiler construction 강의 8. 2 context-free languages the inclusion hierarchy for context-free...

86
1 Compiler Construction Compiler Construction 강강 강강 8 8

Upload: katherine-wood

Post on 24-Dec-2015

229 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

1

Compiler ConstructionCompiler Construction

강의 강의 88

Page 2: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

2

Context-Free Languages

The inclusion hierarchy for

context-free languages

Context-free languages

Deterministic languages (LR(k))

LL(k) languages Simple precedencelanguages

LL(1) languages Operator precedencelanguages

LR(k) ≡ LR(1)

Page 3: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

3

Context-Free Grammars

• Operator precedence includes some ambiguous grammars• LL(1) is a subset of SLR(1)

The inclusion hierarchy forcontext-free grammars

Context-free grammars

Floyd-EvansParsable

UnambiguousCFGs

OperatorPrecedenc

e

LR(k)

LR(1)

LALR(1)

SLR(1)

LR(0)

LL(1)

LL(k)

Page 4: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

4

Beyond Syntax

There is a level of correctness that is deeper than grammar

fie(a,b,c,d) int a, b, c, d;{ … }fee() { int f[3],g[0], h, i, j, k; char *p; fie(h,i,“ab”,j, k); k = f * i + j; h = g[17]; printf(“<%s,%s>.\n”, p,q); p = 10;}

What is wrong with this program?

(let me count the ways …)

Page 5: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

5

Semantics

There is a level of correctness that is deeper than grammar

fie(a,b,c,d) int a, b, c, d;{ … }fee() { int f[3],g[0], h, i, j, k; char *p; fie(h,i,“ab”,j, k); k = f * i + j; h = g[17]; printf(“<%s,%s>.\n”, p,q); p = 10;}

What is wrong with this program?(let me count the ways …)

• declared g[0], used g[17] • wrong number of args to fie() “• ab” is not an int • wrong dimension on use of f • undeclared variable q • 10 is not a character string

All of these are “deeper thansyntax”

Page 6: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

6

Syntax-directed translation

In syntax-directed translation, we attach ATTRIBUTES to grammar symbols.

The values of the attributes are computed by SEMANTIC RULES associated with grammar productions.

Conceptually, we have the following flow:

In practice, however, we do everything in a single pass.

Page 7: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

7

Syntax-directed translation

There are two ways to represent the semantic rules we associate with grammar symbols.

− SYNTAX-DIRECTED DEFINITIONS (SDDs) do not specify the order in which semantic actions should be executed

− TRANSLATION SCHEMES explicitly specify the ordering of the semantic actions.

SDDs are higher level; translation schemes are closer toan implementation

Page 8: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

8

Syntax-Directed Definitions

Page 9: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

9

Syntax-directed definitions

The SYNTAX-DIRECTED DEFINITION (SDD) is a generalization of the context-free grammar.

Each grammar symbol in the CFG is given a set of ATTRIBUTES.

Attributes can be any type (string, number, memory loc, etc)

SYNTHESIZED attributes are computed from the values of the CHILDREN of a node in the parse tree.

INHERITED attributes are computed from the attributes of the parents and/or siblings of a node in the parse tree.

Page 10: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

10

Attribute dependencies

Given a SDD, we can describe the dependencies between the attributes with a DEPENDENCY GRAPH.

A parse tree annotated with attributes is called an ANNOTATED parse tree.

Computing the attributes of the nodes in a parse tree is called ANNOTATING or DECORATING the tree.

Page 11: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

11

Form of a syntax-directed definition

In a SDD, each grammar production A -> α has associated with it semantic rules

b := f( c1, c2, …, ck )where f() is a function, and either

1. b is a synthesized attribute of A, and c1, c2, …, are attributes of the grammar symbols of α, or

2. b is an inherited attribute of one of the symbols on the RHS, and c1, c2, … are attributes of the grammar symbols of α

in either case, we say b DEPENDS on c1, c2, …, ck.

Page 12: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

12

Semantic rules

Usually we actually write the semantic rules with expressions instead of functions.

If the rule has a SIDE EFFECT, e.g. updating the symbol table, we write the rule as a procedure call.

When a SDD has no side effects, we call it an ATTRIBUTE GRAMMAR (Programming Languages course 에서 설명 ).

Page 13: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

13

Synthesized attributes

Synthesized attributes depend only on the attributes ofchildren. They are the most common attribute type.

If a SDD has synthesized attributes ONLY, it is called a S-ATTRIBUTED DEFINITION.

S-attributed definitions are convenient since theattributes can be calculated in a bottom-up traversal of the parse tree.

Page 14: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

14

Example SDD: desk calculator

Production Semantic RuleL -> E newline print( E.val )E -> E1 + T E.val := E1.val + T.valE -> T E.val := T.valT -> T1 * F T.val := T1.val x F.valT -> F T.val := F.valF -> ( E ) F.val := E.valF -> number F.val := number.lexval

Notice the similarity to the yacc spec from last lecture.

Page 15: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

15

Calculating synthesized attributesInput string: 3*5+4 newlineAnnotated tree:

Page 16: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

16

Inherited attributes

An inherited attribute is defined in terms of theattributes of the node’s parents and/or siblings.

Inherited attributes are often used in compilers for passing contextual information forward, for example, the type keyword in a variable declaration statement.

Page 17: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

17

Example SDD with an inherited attribute

Suppose we want to describe decls like “real x, y, z”

Production Semantic RulesD -> T L L.in := T.typeT -> int T.type := integerT -> real T.type := realL -> L1, id L1.in := L.in

addtype( id.entry, L.in )L -> id addtype( id.entry, L.in )

L.in is inherited since it depends on a sibling or parent.

addtype() is justa procedure that

sets the typefield in the

symbol table.

Page 18: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

18

Annotated parse tree for real id1, id2, id3

What are thedependencies

?

Page 19: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

19

Dependency Graphs

Page 20: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

20

Dependency graphs

If an attribute b depends on attribute c, then attribute b has to be evaluated AFTER c.

DEPENDENCY GRAPHS visualize these requirements.− Each attribute is a node− We add edges from the node for attribute c to the node

for attribute b, if b depends on c.− For procedure calls, we introduce a dummy synthesized

attribute that depends on the parameters of the procedure calls.

Page 21: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

21

Dependency graph example

Production Semantic RuleE -> E1 + E2 E.val := E1.val + E2.val

Wherever this rule appears in the parse, tree we draw:

Page 22: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

22

Example dependency graph

Page 23: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

23

Example dependency graph

Page 24: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

24

Finding a valid evaluation order

A TOPOLOGICAL SORT of a directed acyclic graph orders the nodes so that for any nodes a and b such that a -> b, a appears BEFORE b in the ordering.

There are many possible topological orderings for a DAG.

Each of the possible orderings gives a valid order for evaluation of the semantic rules.

Page 25: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

25

Example dependency graph

Page 26: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

26

Syntax Trees

Page 27: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

27

Application: syntax tree construction

One thing SDDs are useful for is construction of SYNTAX TREES.

Recall from Lecture 1 that a syntax tree is a condensed form of parse tree.

Syntax trees are useful for representing programming language constructs like expressions and statements.

They help compiler design by decoupling parsing from translation.

Page 28: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

28

Syntax trees

Leaf nodes for operators and keywords are removed.Internal nodes corresponding to uninformative non-terminals

are replaced by the more meaningful operators.

Page 29: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

29

SDD for syntax tree construction

We need some functions to help us build the syntax tree:− mknode(op,left,right) constructs an operator node with label op, a

nd two children, left and right− mkleaf(id,entry) constructs a leaf node with label id and a pointer

to a symbol table entry− mkleaf(num,val) constructs a leaf node with label num and the to

ken’s numeric value val

Use these functions to build a syntax tree for a-4+c:− P1 := mkleaf( id, st_entry_for_a )− P2 := …

Page 30: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

30

SDD for syntax tree construction

Production Semantic RulesE -> E1 + T E.nptr := mknode( ‘+’, E1.nptr,T.nptr)

E -> E1 - T E.nptr := mknode( ‘-’, E1.nptr,T.nptr)

E -> T E.nptr := T.nptrT -> ( E ) T.nptr := E.nptrT -> id T.nptr := mkleaf( id, id.entry )T -> num T.nptr := mkleaf( num, num.val )

Note that this is a S-attributed definition.Try to derive the annotated parse tree for a-4+c.

Page 31: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

31

Evaluating SDDs Bottom-up

Page 32: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

32

Bottom-up evaluation of S-attributed defn

How can we build a translator for a given SDD?For S-attributed definitions, it’s pretty easy!A bottom-up shift-reduce parser can evaluate the

(synthesized) attributes as the input is parsed.We store the computed attributes with the grammar

symbols and states on the stack.

When a reduction is made, we calculate the values of any synthesized attributes using the already-computed attributes from the stack.

Page 33: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

33

Bottom-up evaluation of S-attributed defns

In the scheme, our parser’s stack now stores grammar symbols AND attribute values.

For every production A -> XYZ with semantic rule A.a := f( X.x, Y.y, Z.z ), before XYZ is reduced to A, we should already have X.x Y.y and Z.z on the stack.

Page 34: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

34

Desk calculator example

If attribute values are placed on the stack as described, it is now easy to implement the semantic rules for the desk calculator.

Production Semantic Rule CodeL -> E newline print( E.val ) print val[top-1]E -> E1 + T E.val := E1.val + T.val val[newtop] = val[top-2]+val[top]E -> T E.val := T.val /*newtop==top, so nothing to do*

/T -> T1 * F T.val := T1.val x F.val val[newtop] = val[top-2]+val[top]T -> F T.val := F.val /*newtop==top, so nothing to do*

/F -> ( E ) F.val := E.val val[newtop] = val[top-1]F -> number F.val := number.lexval /*newtop==top, so nothing to do*/

Page 35: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

35

Desk calculator example

For input 3 * 5 + 4 newline, what happens?Assume when a terminal’s attribute is shifted when it is.

Input States Values Action3*5+4n shift*5+4n number 3 reduce F->number

reduce T->Fshiftshiftreduce F->numberreduce T->T*Freduce E->Tshiftshiftreduce F->numberreduce T->Freduce E->E+Tshiftreduce E->En

Page 36: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

36

L-attributed definitions

S-attributed definitions only allow synthesized attributes.

We saw earlier that inherited attributes are useful.

But we prefer definitions that can be evaluated in one pass.

L-ATTRIBUTED definitions are the set of SDDs whose attributes can be evaluated in a DEPTH-FIRST traversal of the parse tree.

Page 37: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

37

Depth-first traversal

algorithm dfvisit( node n ) {for each child m of n, in left-to-right order, do {

evaluate the inherited attributes of mdfvisit( m )

}evaluate the synthesized attributes of n

}

Page 38: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

38

L-attributed definitions

If a definition can be evaluated by dfvisit() we say it is L-attributed.

Another way of putting it: a SDD is L-attributed if each INHERITED attribute of Xi on the RHS of a production A -> X1 X

2 … Xn depends ONLY on:− The attributes of X1, …, Xi-1 (to the LEFT of Xi in the production)− The INHERITED attributes of A.

Since S-attributed definitions have no inherited attributes, they are necessarily L-attributed.

Page 39: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

39

L-attributed definitions

Is the following SDD L-attributed?

Production Semantic RulesA -> L M L.i := l(A.i)

M.i := m(L.s)A.s := f(M.s)

A -> Q R R.i := r(A.i)Q.i := q(R.s)A.s := f(Q.s)

Page 40: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

40

Translation Schemes

Page 41: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

41

Translation schemes

Translation schemes are another way to describe syntax-directed translation.

Translation schemes are closer to a real implementation because the specify when, during the parse, attributes should be computed.

Example, for conversion of INFIX expressions to POSTFIX:E -> T RR -> addop T { print ( addop.lexeme ) } | εT -> num { print( num.val ) }

This translation scheme will turn 9-5+2 into 95-2+

Page 42: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

42

Turning a SDD into a translation scheme

For a translation scheme to work, it must be the case that an attribute is computed BEFORE it is used.

If the SDD is S-attributed, it is easy to create the translation scheme implementing it:

Production Semantic RuleT -> T1 * F T.val := T1.val x F.val

Translation scheme:T -> T1 * F { T.val = T1.val * F.val }

That is, we just turn the semantic rule into an action and add at the far right hand side. This DOES NOT WORK for inherited attribs!

Page 43: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

43

Turning a SDD into a translation scheme

With inherited attributes, the translation scheme designer needs to follow three rules:

1. An inherited attribute for a symbol on the RHS MUST be computed in an action BEFORE the occurrence of the symbol.

2. An action MUST NOT refer to the synthesized attribute of a symbol to the right of the action.

3. A synthesized attribute for the LHS nonterminal can ONLY be computed in an action FOLLOWING the symbols for all the attributes it references.

Page 44: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

44

Example

This translation scheme does NOT follow the rules:

S -> A1 A2 { A1.in = 1; A2.in = 2 }

A -> a { print( A.in ) }

If we traverse the parse tree depth first, A1.in has not been set when referred to in the action print( A.in )

S -> { A1.in = 1 } A1 { A2.in = 2 } A2

A -> a { print( A.in ) }

Page 45: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

45

Bottom-up evaluation of inherited attributes

The first step is to convert the SDD to a valid translation scheme.

Then a few “tricks” have to be applied to the translation scheme.

It is possible, with the right tricks, to do one-pass bottom-up attribute evaluation for ALL LL(1) grammars and MOST LR(1) grammars, if the SDD is L-attributed.

This means when adding semantic actions to your yacc specifications, you might run into trouble. See section 5.6 of the text!

Page 46: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

46

Beyond Syntax

These questions are part of context-sensitive analysisAnswers depend on values, not parts of speechQuestions & answers involve non-local informationAnswers may involve computation

How can we answer these questions?Use formal methods

− Context-sensitive grammars?− Attribute grammars? (attributed grammars?)

Use ad-hoc techniques− Symbol tables− Ad-hoc code (action routines)

In scanning & parsing, formalism won; different story here.

Page 47: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

47

Beyond Syntax

Telling the storyThe attribute grammar formalism is important

− Succinctly makes many points clear− Sets the stage for actual, ad-hoc practice

The problems with attribute grammars motivate practice− Non-local computation− Need for centralized information

Some folks in the community still argue for attribute grammars

We will cover attribute grammars, then move on to ad-hoc ideas

Page 48: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

48

Attribute Grammars

What is an attribute grammar?A context-free grammar augmented with a set of rulesEach symbol in the derivation has a set of values, or attributesThe rules specify how to compute a value for each attribute

Example grammar

Number → Sign ListSign → + | –List → List Bit | BitBit → 0 | 1

This grammar describessigned binary numbers

We would like to augmentit with rules that computethe decimal value of eachvalid input string

Page 49: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

49

Examples

For “-1”For “-1”

NumberNumber → Sign List→ – List→ – Bit→ – 1

Number

Sign List

Bit–

1

For “-101”For “-101”

Number → Sign List → Sign List Bit → Sign List 1 → Sign List Bit 1 → Sign List 1 1 → Sign Bit 0 1 → Sign 1 0 1 → – 101

Number

Sign List

Bit–

1

List

BitList

Bit 0

1

Page 50: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

50

Attribute Grammars

Add rules to compute the decimal value of a signed binary number

Productions Attribution Rules

Number → Sign List List.pos ← 0If Sign.neg then Number.val ← – List.val else Number.val ← List.val

Sign → + Sign.neg ← false

| – Sign.neg ← true

List0 → List1 Bit List1.pos ← List0.pos + 1Bit.pos ← List0.posList0.val ← List1.val + Bit.val

| Bit Bit.pos ← List.posList.val ← Bit.val

Bit → 0 Bit.val ← 0

| 1 Bit.val ← 2Bit.pos

Symbol Attributes

NumberNumber val

Sign neg

List pos, val

Bit pos, val

Page 51: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

51

Back to The Examples

Knuth suggested a data-flow model for evaluation Independent attributes first Others in order as input values become available

One possible evaluation order:

1. List.pos2. Sign.neg3. Bit.pos4. Bit.val5. List.val6. Number.val

Other orders are possible

For “-1”

neg ← true

Number.val ← –List.val≡ –1

List.pos ← 0List.val ← Bit.val≡ 1

Bit.pos ← 0Bit.val ← 2Bit.pos ≡ 1

Number

Sign List

Bit–

1

Rules + parse treeimply an attributedependence graph

Evaluation ordermust be consistentwith the attributedependence graph

Page 52: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

52

Back to the Examples

This is the completeattribute dependencegraph for “–101”.

It shows the flow of allattribute values in theexample.

Some flow downward→ inherited attributes

Some flow upward→ synthesized attributes

A rule may use attributesin the parent, children, orsiblings of a node

Page 53: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

53

The Rules of The Game

Attributes associated with nodes in parse treeRules are value assignments associated with productionsAttribute is defined once, using local informationLabel identical terms in production for uniquenessRules & parse tree define an attribute dependence graph

− Graph must be non-circular

This produces a high-level, functional specification

Synthesized attribute− Depends on values from children

Inherited attribute− Depends on values from siblings & parent

Page 54: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

54

Using Attribute Grammars

Attribute grammars can specify context-sensitive actionsTake values from syntaxPerform computations with valuesInsert tests, logic, …

Synthesized Attributes• Use values from children & from constants• S-attributed grammars• Evaluate in a single bottom-up passGood match to LR parsing

Inherited Attributes• Use values from parent, constants, & siblings• directly express context• can rewrite to avoid them• Thought to be more naturalNot easily done at parse time

We want to use both kinds of attribute

Page 55: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

55

Evaluation Methods

Dynamic, dependence-based methodsBuild the parse treeBuild the dependence graphTopological sort the dependence graphDefine attributes in topological order

Rule-based methods (treewalk)Analyze rules at compiler-generation timeDetermine a fixed (static) orderingEvaluate nodes in that order

Oblivious methods (passes, dataflow)Ignore rules & parse treePick a convenient order (at design time) & use it

Page 56: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

56

Back to the Example

Number

Sign List

Bit–

1

List

List

Bit

Bit

0

1 For “-101”

Page 57: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

57

Back to the Example

Number

Sign List

Bit–

1

List

List

Bit

Bit

0

1

val:

neg:pos:0val:

pos:val:

pos:val:

pos:val:

pos:val:

pos:val:

For “-101”

Page 58: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

58

Back to the Example

Number

Sign List

Bit–

1

List

List

Bit

Bit

0

1 For “-101”

val:-5

neg:truepos:0val:5

pos:1val:4

pos:2val:4

pos:2val:4

pos:1val:0

pos:0val:1

Inherited Attributes

Page 59: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

59

Back to the Example

Number

Sign List

Bit–

1

List

List

Bit

Bit

0

1 For “-101”

val:-5

neg:truepos:0val:5

pos:1val:4

pos:2val:4

pos:2val:4

pos:1val:0

pos:0val:1

Synthesized Attributes

Page 60: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

60

Back to the Example

Number

Sign List

Bit–

1

List

List

Bit

Bit

0

1 For “-101”

val:-5

neg:truepos:0val:5

pos:1val:4

pos:2val:4

pos:2val:4

pos:1val:0

pos:0val:1

Synthesized Attributes

Page 61: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

61

Back to the Example

Number

Sign List

Bit–

1

List

List

Bit

Bit

0

1 For “-101”

val:-5

neg:truepos:0val:5

pos:1val:4

pos:2val:4

pos:2val:4

pos:1val:0

pos:0val:1

If we show the computation …

& then peel away the parse tree …

Page 62: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

62

Back to the Example

1

0

1 For “-101”

val:-5

neg:truepos:0val:5

pos:1val:4

pos:2val:4

pos:2val:4

pos:1val:0

pos:0val:1

All that is left is the attributedependence graph.

This succinctly represents theflow of values in the probleminstance.

The dynamic methods sort thisgraph to find independentvalues, then work along graphedges.

The rule-based methods try todiscover “good” orders byanalyzing the rules.

The oblivious methods ignorethe structure of this graph.

The dependence graph must be acyclic

Page 63: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

63

Circularity

We can only evaluate acyclic instancesWe can prove that some grammars can only generate instances with

acyclic dependence graphsLargest such class is “strongly non-circular” grammars (SNC )SNC grammars can be tested in polynomial timeFailing the SNC test is not conclusive

Many evaluation methods discover circularity dynamically⇒ Bad property for a compiler to have

SNC grammars were first defined by Kennedy & Warren

Page 64: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

64

A Circular Attribute Grammar

Productions Attribution Rules

Number → List List.a ← 0

List0 → List1 Bit List1.a ← List0.a + 1List0.b ← List1.b List1.c ← List1.b + Bit.val

| Bit List0.b ← List0.a + List0.c + Bit.val

Bit → 0 Bit.val ← 0

| 1 Bit.val ← 2Bit.pos

Page 65: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

65

An Extended Example

Block0 → Block1 Assign | AssignAssign → Ident = Expr ;Expr0 → Expr1 + Term | Expr1 – Term | TermTerm0 → Term1 * Factor | Term1 / Factor | FactorFactor → ( Expr ) | Number | Identifier

Let’s estimate cycle counts

• Each operation has a COST

• Add them, bottom up

• Assume a load per value

• Assume no reuse

Simple problem for an AG

Hey, this looks useful !

Grammar for a basic block (§ 4.3.3)

Page 66: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

66

An Extended ExampleAdding attribution rules

Block0 → Block1 Assign

| AssignAssign → Ident = Expr ;Expr0 → Expr1 + Term

| Expr1 – Term

| TermTerm0 → Term1 * Factor

| Term1 / Factor

| FactorFactor → ( Expr ) | Number | Identifier

Block0.cost ← Block1.cost + Assign.costBlock0.cost ← Assign.costAssign.cost ← COST(st ore) + Expr.costExpr0.cost ← Expr1.cost + COST(add) + Term.costExpr0.cost ← Expr1.cost + COST(add) + Term.costExpr0.cost ← Term.costTerm0.cost ← Term1.cost + COST(mult ) + Factor.costTerm0.cost ← Term1.cost + COST(div) + Factor.costTerm0.cost ← Factor.costFactor.cost ← Expr.costFactor.cost ← COST(loadI)Factor.cost ← COST(load)

All theseattributesaresynthesized!

Page 67: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

67

An Extended Example

Properties of the example grammarAll attributes are synthesized ⇒ S-attributed grammarRules can be evaluated bottom-up in a single pass

− Good fit to bottom-up, shift/reduce parserEasily understood solutionSeems to fit the problem well

What about an improvement?Values are loaded only once per block (not at each use)Need to track which values have been already loaded

Page 68: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

68

A Better Execution ModelAdding load tracking Need sets Before and After for each production Must be initialized, updated, and passed around the tree

Factor → ( Expr )

| Number

| Identifier

Factor.cost ← Expr.cost ;Expr.Before ← Factor.Before ;Factor.After ← Expr.AfterFactor.cost ← COST(loadi) ;Factor.After ← Factor.Beforeif(Identifier.name Factor.Before)∉ then Factor.cost ← COST(load); Factor.After ← Factor.Before ∪ Identifier.name else Factor.cost ← 0 Factor.After ← Factor.Before

This looks more complex!

Page 69: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

69

A Better Execution Model Load tracking adds complexity But, most of it is in the “copy rules” Every production needs rules to copy Before & After

A Sample Production

Expr0 → Expr1 + Term Expr0 .cost ← Expr1.cost + COST(add) + Term.cost ;Expr1.Before ← Expr0.Before ;Term.Before ← Expr1.After;Expr0.After ← Term.After

These copy rules multiply rapidlyEach creates an instance of the setLots of work, lots of space, lots of rules to write

Page 70: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

70

An Even Better Model

What about accounting for finite register sets?Before & After must be of limited sizeAdds complexity to Factor→IdentifierRequires more complex initialization

Jump from tracking loads to tracking registers is smallCopy rules are already in placeSome local code to perform the allocation

Page 71: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

71

The Extended Example

Tracking loadsIntroduced Before and After sets to record loadsAdded ≥ 2 copy rules per production

− Serialized evaluation into execution order

Made the whole attribute grammar large & cumbersome

Finite register setComplicated one production (Factor → Identifier)Needed a little fancier initializationChanges were quite limited

Why is one change hard and the other easy?

Page 72: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

72

The Moral of the Story

Non-local computation needed lots of supporting rulesComplex local computation was relatively easy

The ProblemsCopy rules increase cognitive overheadCopy rules increase space requirements

− Need copies of attributes− Can use pointers, for even more cognitive overhead

Result is an attributed tree− Must build the parse tree− Either search tree for answers or copy them to the root

Page 73: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

73

Addressing the Problem

Ad-hoc techniquesIntroduce a central repository for factsTable of names

− Field in table for loaded/not loaded state

Avoids all the copy rules, allocation & storage headachesAll inter-assignment attribute flow is through table

− Clean, efficient implementation− Good techniques for implementing the table (hashing, § B.4)− When its done, information is in the table !− Cures most of the problems

Unfortunately, this design violates the functional paradigmDo we care?

Page 74: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

74

The Realist’s Alternative

Ad-hoc syntax-directed translationAssociate a snippet of code with each productionAt each reduction, the corresponding snippet runsAllowing arbitrary code provides complete flexibility

− Includes ability to do tasteless & bad things

To make this workNeed names for attributes of each symbol on lhs & rhs

− Typically, one attribute passed through parser + arbitrary code (structures, globals, statics, …)

− Yacc introduced $$, $1, $2, … $n, left to right ANTLR allows defining variables

Need an evaluation scheme− Should fit into the parsing algorithm

Page 75: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

75

Reworking the Example

Block0 → Block1 Assign | AssignAssign → Ident = Expr ;Expr0 → Expr1 + Term | Expr1 – Term | TermTerm0 → Term1 * Factor | Term1 / Factor | FactorFactor → ( Expr ) | Number | Identifier

cost← cost + COST(store);cost← cost + COST(add);cost← cost + COST(sub);

cost← cost + COST(mult);cost← cost + COST(div);

cost← cost + COST(loadi);{ i← hash(Identifier); if(Table[i].loaded = false) then { cost ← cost + COST(load); Table[i].loaded ← true; }}

This lookscleaner &simpler thanthe AG sol’n !

One missing detail:initializing cost

Page 76: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

76

Reworking the Example

Before parser can reach Block, it must reduce Init Reduction by Init sets cost to zeroThis is an example of splitting a production to create a reductionin the middle — for the sole purpose of hanging an action routinethere!

Start → Init BlockInit → εBlock0 → Block1 Assign

| AssignAssign → Ident = Expr ;

cost ← 0;

cost← cost + COST(store);

… and so on as in the previous version of the example …

Page 77: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

77

Reworking the ExampleBlock0 → Block1 Assign | AssignAssign → Ident = Expr ;Expr0 → Expr1 + Term | Expr1 – Term | TermTerm0 → Term1 * Factor | Term1 / Factor | FactorFactor → ( Expr ) | Number | Identifier

$$ ← $1 + $2 ;$$ ← $1 ;$$ ← COST(store) + $3;$$ ← $1 + COST(add) + $3;$$ ← $1 + COST(sub) + $3;$$ ← $1;$$ ← $1 + COST(mult) + $3;$$ ← $1 + COST(div) + $3;$$ ← $1;$$ ← $2;$$ ← COST(loadi);{ i← hash(Identifier); if (Table[i].loaded = false) then { $$ ← COST(load); Table[i].loaded ← true; } else $$ ← 0}

This versionpasses thevalues throughattributes. Itavoids the needfor initializing“cost”

Page 78: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

78

Reworking the Example

Assume constructors for each node Assume stack holds pointers to nodes Assume yacc syntax

Goal → ExprExpr → Expr + Term | Expr – Term | TermTerm → Term * Factor | Term / Factor | FactorFactor → ( Expr ) | number | id

$$ = $1;$$ = MakeAddNode($1,$3);$$ = MakeSubNode($1,$3);$$ = $1;$$ = MakeMulNode($1,$3);$$ = MakeDivNode($1,$3);$$ = $1;$$ = $2;$$ = MakeNumNode(token);$$ = MakeIdNode(token);

Page 79: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

79

Reality

Most parsers are based on this ad-hoc style of context-sensitive analysis

AdvantagesAddresses the shortcomings of the AG paradigmEfficient, flexible

DisadvantagesMust write the code with little assistanceProgrammer deals directly with the detailsAnnotate action code with grammar rules

Page 80: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

80

Typical Uses

Building a symbol table− Enter declaration information as processed− At end of declaration syntax, do some post processing− Use table to check errors as parsing progresses

Simple error checking/type checking− Define before use → lookup on reference− Dimension, type, ... → check as encountered− Type conformability of expression → bottom-up walk− Procedure interfaces are harder

Build a representation for parameter list & typesCreate list of sites to checkCheck offline, or handle the cases for arbitrary orderings

Page 81: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

81

Is This Really “Ad-hoc” ?

Relationship between practice and attribute grammars

SimilaritiesBoth rules & actions associated with productionsApplication order determined by tools, not author(Somewhat) abstract names for symbols

DifferencesActions applied as a unit; not true for AG rulesAnything goes in ad-hoc actions; AG rules are functionalAG rules are higher level than ad-hoc actions

Page 82: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

82

Making Ad-hoc SDT Work

What about a rule that must work in mid-production?Can transform the grammar

− Split it into two parts at the point where rule must go− Apply the rule on reduction to the appropriate part

Can also handle reductions on shift actions− Add a production to create a reduction

Was: fee → fumMake it: fee → fie → fum and tie action to this reduction

ANTLR supports the above automatically

Together, these let us apply rule at any point in the parse

Page 83: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

83

Limitations of Ad-hoc SDT

Forced to evaluate in a given order: postorder− Left to right only− Bottom up only

Implications− Declarations before uses− Context information cannot be passed down

How do you know what rule you are called from within?Example: cannot pass bit position from right down

− Could you use globals?Requires initialization & some re-thinking of the solution

− Can we rewrite it in a form that is better for the ad-hoc sol’n

Page 84: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

84

Alternative Strategy

Build an abstract syntax treeUse tree walk routinesUse “visitor” design pattern to add functionality

TreeNodeVisitor

VisitAssignment(AssignmentNode)

VisitVariableRef(VariableRefNode)

TypeCheckVisitor

VisitAssignment(AssignmentNode)

VisitVariableRef(VariableRefNode)

AnalysisVisitor

VisitAssignment(AssignmentNode)

VisitVariableRef(VariableRefNode)

Page 85: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

85

Visitor Treewalk

Parallel structure of tree:Separates treewalk code from node handling code Facilitates change in processing without change to tree structure

TreeNode

Accept(NodeVisitor)

AssignmentNode

Accept(NodeVisitor v)

v.VisitAssignment(this)

VariableRefNode

Accept(NodeVisitor v)

v.VisitVariableRef(this)

Page 86: 1 Compiler Construction 강의 8. 2 Context-Free Languages The inclusion hierarchy for context-free languages Context-free languages Deterministic languages

86

Summary

Wrap-up of parsing− More example to build LR(1) table

Attribute Grammars− Pros: Formal, powerful, can deal with propagation strategies− Cons: Too many copy rules, no global tables, works on parse tree

Ad-hoc SDT− Annotate production with ad-hoc action code− Postorder Code Execution

Pros: Simple and functional, can be specified in grammar, does not require parse tree

Cons: Rigid evaluation order, no context inheritance− Generalized Tree Walk

Pros: Full power and generality, operates on abstract syntax tree (using Visitor pattern)

Cons: Requires specific code for each tree node type, more complicatedPowerful tools like ANTLR can help with this