• Non ci sono risultati.

Principles of Programming Languages

N/A
N/A
Protected

Academic year: 2022

Condividi "Principles of Programming Languages"

Copied!
34
0
0

Testo completo

(1)

Principles of Programming Languages

h"p://www.di.unipi.it/~andrea/Dida2ca/PLP-16/

Prof. Andrea Corradini

Department of Computer Science, Pisa

•  Intermediate-Code Genera=on

–  Intermediate representa=ons

–  Syntax-directed transla=on to three address code

Lesson 11!

(2)

2

Intermediate Code Genera=on (II)

•  Facilitates retarge&ng: enables aGaching a back end for the new machine to an exis=ng front end

Parsing

Syntax-Directed Defini=ons Syntax-Directed Transla=on Schemes

Back end

Intermediate

code Target

code

Tokens

(3)

Summary

•  Intermediate representa=ons

•  Three address statements and their implementa=ons

•  Syntax-directed transla=on to three address statements

–  Expressions and statements

–  Logical and rela=onal expressions

–  Transla=ng short-circuit Boolean expressions and flow-of-

control statements with backpatching lists

(4)

4

Intermediate Representa=ons

•  Graphical representa&ons (e.g. AST and DAGs)

•  Pos2ix nota&on: opera=ons on values stored on operand stack (similar to JVM bytecode)

•  Three-address code: (e.g. triples and quads) x := y op z

•  Two-address code:

x := op y

which is the same as x := x op y

(5)

Syntax-Directed Transla=on of Abstract Syntax Trees

Produc=on S → id := E E → E

1

+ E

2

E → E

1

* E

2

E → - E

1

E → ( E

1

) E → id

Seman=c Rule

S.nptr := mknode(‘:=’, mkleaf(id, id.entry), E.nptr) E.nptr := mknode(‘+’, E

1

.nptr, E

2

.nptr)

E.nptr := mknode(‘*’, E

1

.nptr, E

2

.nptr) E.nptr := mknode(‘uminus’, E

1

.nptr) E.nptr := E

1

.nptr

E.nptr := mkleaf(id, id.entry)

(6)

6

Abstract Syntax Trees

E.nptr

* E.nptr

E.nptr a!

b!

+ E.nptr

*!

a! +!

b! c!

E.nptr c E.nptr

( )

a * (b + c)!

Pro: easy restructuring of code and/or expressions for

intermediate code op=miza=on

Cons: memory intensive

(7)

Abstract Syntax Trees versus DAGs

:=

a +

*

uminus b

c

*

uminus b

Tree c

:=

a +

*

uminus b

c DAG

a := b * -c + b * -c!

•  Repeated subtrees are shared

•  Implementa=on: mkleaf and makenode are redefined. They do

(8)

8

Pos]ix Nota=on

a := b * -c + b * -c!

iload 2 // push b iload 3 // push c ineg // uminus imul // *

iload 2 // push b iload 3 // push c ineg // uminus imul // *

iadd // +

istore 1 // store a

Bytecode (for example) a b c uminus * b c uminus * + assign

Pos]ix nota=on represents opera=ons on a stack

Pro: easy to generate

Cons: stack opera=ons are more

difficult to op=mize

(9)

Three-Address Code (1)

a := b * -c + b * -c!

t1 := - c t2 := b * t1 t3 := - c t4 := b * t3 t5 := t2 + t4 a := t5

Linearized representation of a syntax tree

:=

a +

*

uminus b

c

*

uminus b

Tree c

(10)

Three-Address Code (2)

a := b * -c + b * -c!

t1 := - c t2 := b * t1 t5 := t2 + t2 a := t5

Linearized representation of a syntax DAG

:=

a +

*

uminus b

c DAG

(11)

Three-Address Statements

“Addresses” are names, constants or temporaries

•  Assignment statements: x:= y op z, x:= op y

•  Indexed assignments: x:= y[i], x[i]:= y

•  Pointer assignments: x:= &y, x:= *y, *x:= y

•  Copy statements: x:= y

•  Unconditional jumps: goto lab

•  Conditional jumps: if x relop y goto lab

•  Function calls: param x… ; call p, n

(or y = call p, n) ; return y

(12)

Implementa=on of Three-Address Statements: Quads

# Op Arg1 Arg2 Res

(0) uminus c t1

(1) * b t1 t2

(2) uminus c t3

(3) * b t3 t4

(4) + t2 t4 t5

(5) := t5 a

Quads (quadruples) Pro: easy to rearrange code for global op=miza=on Cons: lots of temporaries

Three-address code

t1 := - c t2 := b * t1 t3 := - c t4 := b * t3 t5 := t2 + t4 a := t5

Sample expression

a := b * -c + b * -c

!

(13)

Implementa=on of Three-Address Statements: Triples

# Op Arg1 Arg2

(0) uminus c

(1) * b (0)

(2) uminus c

(3) * b (2)

(4) + (1) (3)

(5) := a (4)

Triples Pro: temporaries are implicit

Three-address code

t1 := - c t2 := b * t1 t3 := - c t4 := b * t3 t5 := t2 + t4 a := t5

Sample expression

a := b * -c + b * -c

!

(14)

Implementa=on of Three-Address Statements: Indirect Triples

# Op Arg1 Arg2

(14) uminus c

(15) * b (14)

(16) uminus c

(17) * b (16)

(18) + (15) (17)

(19) := a (18)

Triple container

Pro: temporaries are implicit & easier to rearrange code

# Stmt (0) (14) (1) (15) (2) (16) (3) (17) (4) (18) (5) (19)

Program

(15)

Syntax-Directed Transla=on into Three-Address Code

Synthesized attributes:

S.code three-address code for S S.begin label to start of S or nil S.after label to end of S or nil E.code three-address code for E

E.place a name holding the value of E ProducEons

S → id := E

| while E do S | S ; S

E → E + E | E * E | - E | ( E ) | id

| num gen(E.place ‘:=’ E

1

.place ‘+’ E

2

.place)

(16)

Syntax-Directed Transla=on into Three-Address Code (cont’d)

ProducEons S → id := E S → while E do S1 E → E1 + E2 E → E1 * E2 E → - E1 E → ( E1 ) E → id E → num S → S1 ; S2

Semantic rules

S.code := E.code || gen(id.place ‘:=’ E.place); S.begin := S.after := nil (see next slide)

E.place := newtemp();

E.code := E1.code || E2.code || gen(E.place ‘:=’ E1.place ‘+’ E2.place) E.place := newtemp();

E.code := E1.code || E2.code || gen(E.place ‘:=’ E1.place ‘*’ E2.place) E.place := newtemp();

E.code := E1.code || gen(E.place ‘:=’ ‘uminus’ E1.place) E.place := E1.place

E.code := E1.code E.place := id.name E.code := ‘’

E.place := newtemp();

E.code := gen(E.place ‘:=’ num.value)

S.code := S1.code || S2.code S.begin := S1. begin S.after := S2.after

(17)

Syntax-Directed Transla=on into Three-Address Code (cont’d)

ProducEon

S → while E do S1

Semantic rule

S.begin := newlabel() S.after := newlabel()

S.code := gen(S.begin ‘:’) ||

E.code ||

gen(‘if’ E.place ‘=‘ ‘0’ ‘goto’ S.after) ||

S1.code ||

gen(‘goto’ S.begin) ||

if E.place = 0 goto S.after S.code

E.code

goto S.begin

S.begin:

S.after:

(18)

18

Example (check it at home!)

i := 2 * n + k;


while i do


i := i - k!

t1 := 2

t2 := t1 * n t3 := t2 + k i := t3

L1: if i = 0 goto L2 t4 := i - k

i := t4 goto L1 L2:

(19)

How does the code access names?

•  The three-address code generated by the syntax- directed defini=ons shown is simplis=c

•  It assumes that the names of variables can be easily resolved by the back-end in global or local variables

•  We need local symbol tables to record global declara=ons as well as local declara=ons in procedures, blocks, and records (structs) to resolve names

•  We will see all this later in the course

(20)

Transla=ng Logical and Rela=onal Expressions

a or b and not c

t1 := not c

t2 := b and t1 t3 := a or t2

if a < b goto L1 t1 := 0

goto L2 L1: t1 := 1 L2:

a < b

Boolean expressions intended to represent values:

Boolean expressions used to alter the control flow:

(21)

Short-Circuit Code

•  The boolean operators &&, || and ! are translated into jumps.

•  Example:

if ( x < 100 || x > 200 && x != y ) x = 0;

may be translated into:

if x < 100 goto L2

ifFalse x > 200 goto L1 ifFalse x ! = y goto L1 L2: x=0

L1:

(22)

Transla=ng Flow-of-control Statements

22

·˨̊ᗮ

"Đdz 67.XÆ>dzƯ dz

ߖ੎ᗮྲྀအᑌᗮहအྲྀበೊ়੎ᅻᗮዔఀ੎ᗮዔᅻࡐྲྀበเࡐዔೊအྲྀᗮအ૤ᗮ࣒အအเ੎ࡐྲྀᗮ੎ᒏႼᅻ੎በበ೔အྲྀበᗮ೔ྲྀዔအᗮዔఀᅻ੎੎Ÿࡐ়়ᅻ੎በበᗮहအ়੎ᗮ

ೊྲྀᗮዔఀ੎ᗮहအྲྀዔ੎ᒏዔᗮအ૤ᗮበዔࡐዔ੎༌੎ྲྀዔበᗮበᎯहఀᗮࡐበᗮዔఀအበ੎ᗮஸ੎ྲྀ੎ᅻࡐዔ੎়ᗮ࣒ᒹᗮዔఀ੎ᗮ૤အเเအᑌ೔ྲྀஸᗮஸᅻࡐ༌༌ࡐᅻгᗮ

ŗ͆ ҿ

ҿ

Hҿ

ɼÎ׋æ׋ ŗ:͆

ɼÎ׋æ׋ f͆ ɼ %͆

'ɼ Î׋æ׋ :͆

צྮᗮዔఀ੎በ੎ᗮႼᅻအ়Ꭿहዔೊအྲྀበýᗮ࿘အྲྀዔ੎ᅻ༌೔ྲྀࡐเᗮ

ᅻ੎Ⴜᅻ੎በ੎ྲྀዔበᗮࡐᗮ࣒အအเ੎ࡐྲྀᗮ੎ᒏႼᅻ੎በበೊအྲྀᗮࡐྲ়ྀᗮྲྀအྲྀᔳ ዔ੎ᅻ༌ೊྲྀࡐเᗮ

ᅻ੎Ⴜᅻ੎በ੎ྲྀዔበᗮࡐᗮበዔࡐዔ੎༌੎ྲྀዔȪᗮ

ݫ౵ೊበᗮஸᅻࡐ༌༌ࡐᅻᗮஸ੎ྲྀ੎ᅻࡐเ೔ᔎ੎በᗮዔఀ੎ᗮᅻᎯྲྀྲྀ೔ྲྀஸᗮ੎ᒏࡐ༌Ⴜเ੎ᗮအ૤ᗮᑌఀ೔เ੎ᗮ੎ᒏწᅻ੎በበೊအྲྀበᗮዔఀࡐዔᗮᑌ੎ᗮ

ೊྲྀዔᅻအ়Ꭿह੎়ᗮೊగᗮիᒏࡐ༌Ⴜเ੎ᗮΥȪ ̊ДȪᗮ ӕበᗮೊྲྀᗮዔఀࡐዔᗮ੎ᒏࡐ༌Ⴜเ੎ýᗮ࣒အዔఀᗮԊ ࡐྲ়ྀᗮ

ఀࡐᐕ੎ᗮࡐᗮበᒹྲྀዽఀ੎ᔳ በೊᔎ੎়ᗮࡐዔዔᅻ೔࣒Ꭿዔ੎ᗮ

 ͆

ᑌఀೊहఀᗮஸೊᐕ੎በᗮዔఀ੎ᗮዔᅻࡐྲྀበเ࡭ዔೊအྲྀᗮೊྲྀዔအᗮዔఀᅻ੎੎Ÿࡐ়়ᅻ੎በበᗮೊྲྀበዔᅻᎯहዔೊအྲྀበȪᗮ

֏အᅻᗮበ೔༌Ⴜเೊह೔ዔᒹýᗮ ᑌ੎ᗮ࣒Ꭿ೔เ়ᗮᎯႼᗮዔఀ੎ᗮዔᅻࡐྲྀበเࡐዔೊအྲྀበᗮ

͆ ͆

ࡐྲ়ྀᗮ

Ɩ͆ ͆

ࡐኪᗮበዔᅻ೔ྲྀஸበýᗮᎯበᔳ

ೊྲྀஸᗮበᒹྲྀዔࡐᒏŸ়೔ᅻ੎हዔ੎়ᗮ়੎୪ྲྀ೔ዔೊအྲྀበȷᗮ ݫఀ੎ᗮበ੎༌ࡐྲྀዔೊहᗮᅻᎯเ੎በᗮ়੎୪ྲྀೊྲྀஸᗮዔఀ੎ ʗᗮ

ǎ ͆

ࡐዔዔᅻ೔࣒Ꭿዔ੎በᗮ हအᏆเ়ᗮ࣒੎ᗮೊ༌Ⴜเ੎༌੎ྲྀዔ੎়ᗮೊྲྀበዔ੎ࡐ়ᗮ࣒ᒹᗮ࣒Ꭿೊเ়ೊྲྀஸᗮᏅႼᗮ በᒹྲྀዔࡐᒏᗮዔᅻ੎੏በᗮࡐྲ়ྀᗮዔఀ੎ྲྀᗮ੎༌ೊዔዔೊྲྀஸᗮ हအ়੎ᗮ৲Ꭿᅻೊྲྀஸᗮࡐᗮዔᅻ੎਼ᗮዔᅻࡐᐕ੎ᅻበࡐเýᗮအᅻᗮ࣒ᒹᗮࡐྲྀᒹᗮအ૤ᗮዔఀ੎ᗮࡐႼზᅻအࡐहఀ੎በᗮအᎯዔเ೔ྲྀ੎়ᗮೊྲྀᗮܺ੎हዔೊအྯᗮΥȪΥȪᗮ ݫఀ੎ᗮዔᅻࡐྲྀበเࡐዔೊအྲྀᗮအ૤ᗮ

ɼǬ"͆:͆

हအྲྀበ೔በዔበᗮအ૤ᗮ

#  ͆

૤အเเအᑌ੎়ᗮ࣒ᒹᗮ

ŗ:   ͆

ࡐበᗮ೔เเᎯበᔳ ዔᅻࡐዔ੎়ᗮೊྲྀᗮ֏ೊஸȪᗮνȪͯΥ

Ï

ࡐÃ Ȫᗮ ߖೊዔఀ೔ྲྀᗮ

#  ͆

ࡐᅻ੎ᗮෟᎯ༌Ⴜበᗮ࣒ࡐበ੎়ᗮအྲྀᗮዔఀ੎ᗮᐕࡐเᎯ੎ᗮအ૤ᗮ

͆

צ૤ᗮ

೔በᗮዔᅻᎯ੎ýᗮहအྲྀዔᅻအเᗮ஛အᑌበᗮዔအᗮዔఀ੎ᗮ୪ᅻበዔᗮೊྲྀበዔᅻᎯहዔ೔အྲྀᗮအ૤ᗮ

: ͆ ͆

ࡐྲ়ྀᗮ೔૤ᗮ

ೊበᗮ૤ࡐเበ੎ýᗮहအྲྀዔᅻအเᗮ

஛အᑌበᗮዔအᗮዔఀ੎ᗮೊྲྀበዔᅻᎯहዔೊအྲྀᗮ೔༌༌੎়ೊࡐዔ੎เᒹᗮ૤အเเအᑌ೔ྲྀஸᗮ

: '͆ ͆

ዔအᗮ

( !͆

(¡  ͆

ዔအᗮ

(¡ď͆

ƾ֖֕֗֘ūҿ

(  ͆

ዔအᗮ

ƿ֛֚֙֜

ዔᗮ

(¡ !͆

(¡͆

(„ !͆ ¹͆

: Þ  ͆ (¡ !͆ ¹͆

2Ŵ   ͆

͆ ¹͆ 'Ϯ  i!͆

Ï

ࡐÃᗮ೔૤ᗮ

(ď͆ ¹͆

2%   ͆

¡ i!͆ ¹͆    ͆

0 ͆ ¹͆

ዔအᗮ

(¡ !͆

(  ͆

ዔအᗮ

(¡ď͆ Ï

Η׋

ೊ૤Ɖ੎เበ੎ᗮ

( !͆ ɧ͆

2Ŵ   ͆

'Ϯ0 ͆

(ď͆

हÃᗮ ᑌఀ೔เ੎ᗮ

֍ೊிᎯᅻ੎ᗮνȩͯΥюᗮ Ԧအ়੎ᗮ૤အᅻᗮೊ૤Ɓýᗮ೔૤Ÿ੎เበ੎ƅýᗮࡐྲ়ྀᗮᑌఆೊเ੎Ÿበዔࡐዔ੎༌੎ྲྀዔበᗮ

ݫఀ੎ᗮเࡐ࣒੎เበᗮ૤အᅻᗮዔఀ੎ᗮෟᎯ༌Ⴜበᗮ೔ྲྀᗮ

͆ ͆

ࡐྲ়ྀᗮ

2'͆ ͆

ࡐᅻ੎ᗮ༌ࡐྲྀࡐஸ੎়ᗮᎯበೊྲྀஸᗮ೔ྲྀఀ੎ᅻೊዔ੎়ᗮ ࡐዔዔᅻೊ࣒Ꭿዔ੎በȪᗮ ߖ೔ዔఀᗮࡐᗮ࣒အအเ੎ࡐྲྀᗮ੎ᒏႼᅻ੎በበ೔အྲྀᗮ

͆

ᑌ੎ᗮࡐበበအहೊࡐዔ੎ᗮዔᑌအᗮเࡐ࣒੎เበюᗮ

͆!͆

ዔఀ੎ᗮ

Synthesized A"ributes:

S.code, B.Code

Inherited A"ributes:

labels for jumps:

B.true, B.false, S.next

·˨̊ᗮ

"Đdz 67.XÆ>dzƯ dz

ߖ੎ᗮྲྀအᑌᗮहအྲྀበೊ়੎ᅻᗮዔఀ੎ᗮዔᅻࡐྲྀበเࡐዔೊအྲྀᗮအ૤ᗮ࣒အအเ੎ࡐྲྀᗮ੎ᒏႼᅻ੎በበ೔အྲྀበᗮ೔ྲྀዔအᗮዔఀᅻ੎੎Ÿࡐ়়ᅻ੎በበᗮहအ়੎ᗮ

ೊྲྀᗮዔఀ੎ᗮहအྲྀዔ੎ᒏዔᗮအ૤ᗮበዔࡐዔ੎༌੎ྲྀዔበᗮበᎯहఀᗮࡐበᗮዔఀအበ੎ᗮஸ੎ྲྀ੎ᅻࡐዔ੎়ᗮ࣒ᒹᗮዔఀ੎ᗮ૤အเเအᑌ೔ྲྀஸᗮஸᅻࡐ༌༌ࡐᅻгᗮ

ŗ͆ ҿ

ҿ

Hҿ

ɼÎ׋æ׋ ŗ:͆

ɼÎ׋æ׋ f͆ ɼ %͆

'ɼ Î׋æ׋:͆

צྮᗮዔఀ੎በ੎ᗮႼᅻအ়Ꭿहዔೊအྲྀበýᗮ࿘အྲྀዔ੎ᅻ༌೔ྲྀࡐเᗮᅻ੎Ⴜᅻ੎በ੎ྲྀዔበᗮࡐᗮ࣒အအเ੎ࡐྲྀᗮ੎ᒏႼᅻ੎በበೊအྲྀᗮࡐྲ়ྀᗮྲྀအྲྀᔳ ዔ੎ᅻ༌ೊྲྀࡐเᗮᅻ੎Ⴜᅻ੎በ੎ྲྀዔበᗮࡐᗮበዔࡐዔ੎༌੎ྲྀዔȪᗮ

ݫ౵ೊበᗮஸᅻࡐ༌༌ࡐᅻᗮஸ੎ྲྀ੎ᅻࡐเ೔ᔎ੎በᗮዔఀ੎ᗮᅻᎯྲྀྲྀ೔ྲྀஸᗮ੎ᒏࡐ༌Ⴜเ੎ᗮအ૤ᗮᑌఀ೔เ੎ᗮ੎ᒏწᅻ੎በበೊအྲྀበᗮዔఀࡐዔᗮᑌ੎ᗮ

ೊྲྀዔᅻအ়Ꭿह੎়ᗮೊగᗮիᒏࡐ༌Ⴜเ੎ᗮΥȪ ̊ДȪᗮ ӕበᗮೊྲྀᗮዔఀࡐዔᗮ੎ᒏࡐ༌Ⴜเ੎ýᗮ࣒အዔఀᗮԊ ࡐྲ়ྀᗮఀࡐᐕ੎ᗮࡐᗮበᒹྲྀዽఀ੎ᔳ በೊᔎ੎়ᗮࡐዔዔᅻ೔࣒Ꭿዔ੎ᗮ ͆ᑌఀೊहఀᗮஸೊᐕ੎በᗮዔఀ੎ᗮዔᅻࡐྲྀበเ࡭ዔೊအྲྀᗮೊྲྀዔအᗮዔఀᅻ੎੎Ÿࡐ়়ᅻ੎በበᗮೊྲྀበዔᅻᎯहዔೊအྲྀበȪᗮ

֏အᅻᗮበ೔༌Ⴜเೊह೔ዔᒹýᗮ ᑌ੎ᗮ࣒Ꭿ೔เ়ᗮᎯႼᗮዔఀ੎ᗮዔᅻࡐྲྀበเࡐዔೊအྲྀበᗮ͆ ͆ࡐྲ়ྀᗮƖ͆ ͆ࡐኪᗮበዔᅻ೔ྲྀஸበýᗮᎯበᔳ

ೊྲྀஸᗮበᒹྲྀዔࡐᒏŸ়೔ᅻ੎हዔ੎়ᗮ়੎୪ྲྀ೔ዔೊအྲྀበȷᗮ ݫఀ੎ᗮበ੎༌ࡐྲྀዔೊहᗮᅻᎯเ੎በᗮ়੎୪ྲྀೊྲྀஸᗮዔఀ੎ ʗᗮǎ ͆ࡐዔዔᅻ೔࣒Ꭿዔ੎በᗮ हအᏆเ়ᗮ࣒੎ᗮೊ༌Ⴜเ੎༌੎ྲྀዔ੎়ᗮೊྲྀበዔ੎ࡐ়ᗮ࣒ᒹᗮ࣒Ꭿೊเ়ೊྲྀஸᗮᏅႼᗮ በᒹྲྀዔࡐᒏᗮዔᅻ੎੏በᗮࡐྲ়ྀᗮዔఀ੎ྲྀᗮ੎༌ೊዔዔೊྲྀஸᗮ हအ়੎ᗮ৲Ꭿᅻೊྲྀஸᗮࡐᗮዔᅻ੎਼ᗮዔᅻࡐᐕ੎ᅻበࡐเýᗮအᅻᗮ࣒ᒹᗮࡐྲྀᒹᗮအ૤ᗮዔఀ੎ᗮࡐႼზᅻအࡐहఀ੎በᗮအᎯዔเ೔ྲྀ੎়ᗮೊྲྀᗮܺ੎हዔೊအྯᗮΥȪΥȪᗮ ݫఀ੎ᗮዔᅻࡐྲྀበเࡐዔೊအྲྀᗮအ૤ᗮɼǬ"͆:͆हအྲྀበ೔በዔበᗮအ૤ᗮ#  ͆૤အเเအᑌ੎়ᗮ࣒ᒹᗮŗ:   ͆ࡐበᗮ೔เเᎯበᔳ ዔᅻࡐዔ੎়ᗮೊྲྀᗮ֏ೊஸȪᗮνȪͯΥÏࡐÃ Ȫᗮ ߖೊዔఀ೔ྲྀᗮ#  ͆ࡐᅻ੎ᗮෟᎯ༌Ⴜበᗮ࣒ࡐበ੎়ᗮအྲྀᗮዔఀ੎ᗮᐕࡐเᎯ੎ᗮအ૤ᗮ͆ צ૤ᗮ

೔በᗮዔᅻᎯ੎ýᗮहအྲྀዔᅻအเᗮ஛အᑌበᗮዔအᗮዔఀ੎ᗮ୪ᅻበዔᗮೊྲྀበዔᅻᎯहዔ೔အྲྀᗮအ૤ᗮ: ͆ ͆ࡐྲ়ྀᗮ೔૤ᗮೊበᗮ૤ࡐเበ੎ýᗮहအྲྀዔᅻအเᗮ

஛အᑌበᗮዔအᗮዔఀ੎ᗮೊྲྀበዔᅻᎯहዔೊအྲྀᗮ೔༌༌੎়ೊࡐዔ੎เᒹᗮ૤အเเအᑌ೔ྲྀஸᗮ: '͆ ͆

ዔအᗮ( !͆

(¡  ͆ ዔအᗮ(¡ď͆

ƾ֖֕֗֘ūҿ

(  ͆ ዔအᗮ

ƿ֛֚֙֜

ዔᗮ (¡ !͆

(¡͆

(„ !͆ ¹͆

: Þ  ͆ (¡ !͆ ¹͆

2Ŵ   ͆

͆ ¹͆ 'Ϯ  i!͆

ÏࡐÃᗮ೔૤ᗮ (ď͆ ¹͆

2%   ͆

¡ i!͆ ¹͆    ͆

0 ͆ ¹͆ ዔအᗮ(¡ !͆

(  ͆ ዔအᗮ(¡ď͆ ÏΗ׋ೊ૤Ɖ੎เበ੎ᗮ

( !͆ ɧ͆

2Ŵ   ͆

'Ϯ0 ͆

(ď͆ हÃᗮ ᑌఀ೔เ੎ᗮ

֍ೊிᎯᅻ੎ᗮνȩͯΥюᗮ Ԧအ়੎ᗮ૤အᅻᗮೊ૤Ɓýᗮ೔૤Ÿ੎เበ੎ƅýᗮࡐྲ়ྀᗮᑌఆೊเ੎Ÿበዔࡐዔ੎༌੎ྲྀዔበᗮ

ݫఀ੎ᗮเࡐ࣒੎เበᗮ૤အᅻᗮዔఀ੎ᗮෟᎯ༌Ⴜበᗮ೔ྲྀᗮ͆ ͆ࡐྲ়ྀᗮ2'͆ ͆ࡐᅻ੎ᗮ༌ࡐྲྀࡐஸ੎়ᗮᎯበೊྲྀஸᗮ೔ྲྀఀ੎ᅻೊዔ੎়ᗮ ࡐዔዔᅻೊ࣒Ꭿዔ੎በȪᗮ ߖ೔ዔఀᗮࡐᗮ࣒အအเ੎ࡐྲྀᗮ੎ᒏႼᅻ੎በበ೔အྲྀᗮ͆ᑌ੎ᗮࡐበበအहೊࡐዔ੎ᗮዔᑌအᗮเࡐ࣒੎เበюᗮ ͆!͆ዔఀ੎ᗮ

(23)

23

˙ -$˙° ˙  $#ZKZ˙= $ ˙

แࡐ࣒੎แᗮዏအᗮᑌఀೊहఀᗮहအྲྀዏᅻအแᗮ஛အᑌበᗮೊ૤ᗮೊበᗮዏᅻᎯ੎ûᗮࡐྲ়ྀᗮ#͆ዏఀ੎ᗮแࡐ࣒੎แᗮዏအᗮᑌఀೊहఀᗮहအྲྀዏᅻအแᗮ

஛အᑌበᗮ ೊ૤ᗮೊበᗮ૤ࡐแበ੎ȩᗮ ߖೊዏఀᗮ ࡐᗮ በዏࡐዏ੎༌੎ྲྀዏᗮ/͆ ᑌ੎ᗮ ࡐበበအहೊࡐዏ੎ᗮ ࡐྲྀᗮ ೊྲྀఀ੎ᅻೊዏ੎ীᗮ ࡐዏዏᅻೊ࣒Ꭿዏ੎ᗮ

ɣȁϏi়͆੎ྲྀအዏೊྲྀஸᗮࡐᗮแࡐ࣒੎แᗮ૤အᅻᗮዏఀ੎ᗮೊྲྀበዏᅻᎯहዏೊအྲྀᗮೊ༌༌੎়ೊࡐዏ੎แᒹᗮ ࡐ૤ዏ੎ᅻᗮዏఀ੎ᗮहအ়੎ᗮ૤အᅻᗮ͆

צྲྀᗮበအ༌੎ᗮहࡐበ੎በûᗮዏఀ੎ᗮೊྲྀበዏᅻᎯहዏೊအྲྀᗮೊ༌༌੎়ೊࡐዏ੎แᒹᗮ૤အแแအᑌೊྲྀஸᗮ͆ ͆ೊበᗮࡐᗮෟᎯ༌Ⴜᗮዏအᗮበအཌ੎ᗮ แࡐ࣒੎แᗮ ^@ť ĕťෟᎯ༌ႼᗮዏအᗮࡐᗮෟᎯ༌Ⴜᗮዏအᗮ^ť૤ᅻအ༌ᗮᑌೊዏఀೊྲྀᗮ2͆ ͆ೊበᗮࡐᐕအೊ়੎়ᗮᎯበೊྲྀஸᗮ͆i͆

ݫఀ੎ᗮበᒹྲྀዏࡐᒏŸ়ೊᅻ੎हዏ੎়ᗮ়੎୪ྲྀೊዏೊအྲྀᗮೊྲྀᗮ֍ೊஸȪᗮνȩͯϕŸνȩͯϚᗮႼᅻအ়Ꭿह੎በᗮዏఀᅻ੎੎Ɖࡐ়়ᅻ੎በበᗮहအ৸੎ᗮ

૤အᅻᗮ࣒အအแ੎ࡐྲྀᗮ੎ᒏႼᅻ੎በበೊအྲྀበᗮೊྲྀᗮዏఀ੎ᗮहအྲྀዏ੎ᒏዏᗮအ଄ᗮೊ૤Ÿûᗮ್૤Ÿ੎แበ੎Ÿûᗮࡐྲ়ྀᗮᑌఀೊแ੎Ÿበዏࡐዏ੎༌੎ྲྀዏበȪᗮ

DF;VT);:u

ŏ؛

Ŵ؛ (ɼ

N!36T)u GV1!Ou

͆i͆ 90T͆

ΦϏ ͆ ͆ ͆© © ͆0͆͆i\͆

͆ ͆ (Iɼ ͆

Ď؛ ɼ͆ #͆ \͆ ɂ͆ #͆͆ ҿ 9ʿT͆

#͆ / 2h  i͆ / ƥ i͆

2  ͆ /

Ď؛ ȣɼ͆ #͆\͆ 2h͆ɼ%͆ #͆͆ ҿ 90T͆

#͆͆ / 90T͆

: Ǿ͆i͆/ % ͆i͆ ҿ ͆i͆

  ͆ / #  ͆

È͆ 0#\͆ È͆ 2h   ͆

Ù Ù ͆N͆'·Ϯ Ɠ͆i\͆

È͆ 0#\͆ È͆ % F  ͆

'ɼ͆ #͆ \͆ :͆ 0 ͆ / 90T͆

#͆͆ ҿ 90T͆

#͆ŏ͆ ҿ 2͆ˋi͆

2h ͆i͆ ҿ 0 ͆

2  ͆ ҿ 00 \͆ È͆ ɵ  ͆

È͆ 0# \͆ È͆ : F  ͆

È͆ N͆'·Ϯ 0 \͆

Ȟᗮ :͆ %͆ : ͆i͆ ҿ 90˼T͆

Ɋ% Ƌ͆i͆ҿ 2͆i͆

2  ͆ /

֍ೊஸᎯᅻ੎ᗮνȩͯνђᗮ ܺᒹྲྀዏࡐᒏŸ়ೊᅻ੎हዏ੎়ᗮ়੎୪ྲྀೊዏೊအྲྀᗮ૤းᅻᗮ஛အᑌŸအ૬Ɖहအྲྀዏᅻအแᗮበዏࡐዏ੎༌੎ྲྀዏበȪᗮ ߖ੎ᗮࡐበበᎯ༌੎ᗮዏఀࡐዏᗮ90T͆हᅻ੎ࡐዏ੎በᗮࡐᗮྲྀ੎ᑌᗮแࡐ࣒੎แᗮ੎ࡐहఀᗮዏೊ༌੎ᗮೊዏᗮೊበᗮहࡐแแ੎়ûᗮࡐྲ়ྀᗮዏఀࡐዏᗮ

Inherited AGributes

Not relevant for control flow

(24)

Transla=on of Boolean Expressions

24

 ˙ -8˙°Ž˙  8#ZKZ˙= 8 ˙ हအྲ়ྀഇዏഇအྲྀࡐแᗮࡐྲ়ྀᗮᎯྲྀहအྲ়ྀഇዏഇအྲྀࡐแᗮෟᎯ༌Ⴜበᗮዏအᗮ အྲྀ੎ᗮအ૤ᗮዏᑌအᗮแࡐ࣒੎แበгᗮ (͆!͆ഇ૤ᗮഇበᗮዏᅼᎯ੎ĉᗮ ࡐྲ়ྀᗮ(͆͆ഇ૤ᗮഇበᗮ૤ࡐแበ੎ȩᗮ

>F;VT*;6u N!56T)u GV1!Ou (͆ C͆ (c͆ l l ť(%͆ (c !͆/(4!͆

(c ͆/ Ě0T͆

(% 4 !͆/(4 !͆

(% ͆/(͆͆

Jҿ (c͆PPť(%͆ (c  !͆/Ě0T͆

(c ͆/(´͆

(% ƕ!͆/(  !͆

(% 4͆ҿ(͆͆

( ¡  ͆/

(͆ C͆ ᗮ(c͆ (c ͆!͆ҿ(͆͆

(c ͆/(4!͆

(  ͆/(c 4  ͆

(͆ C͆ c͆ Éɼ%͆ (  ͆/

Ù Z ͆N͆ȩϮ c ͆ ͆ÉIɼ ͆% ͆ ͆NK.‘.N͆ (4͆!\͆

Z Z ͆N͆K.‘.N͆ (͆´\͆

(͆ C͆ #ɼ (4  ͆/NK.‘.N͆ ( !\͆

(͆ C͆ ɼ (͆ ͆/N͆K.‘.«͆ (͆Þ\͆

֏ഇஸᎯᅼ੎ᗮνȩͯϚюᗮ ֿ੎ྲྀ੎ᅼࡐዏഇྲྀஸᗮዏఀᅼ੎੎Ÿࡐ়়ᅼ੎በበᗮहအ়੎ᗮ૤အᅼᗮ࣒အအแ੎ࡐྲྀበᗮ

ݫఀ੎ᗮ૤အᎯᅼዏఀᗮႼᅼအ়Ꭿहዏഇအྲྀᗮഇྲྀᗮ֏ഇஸȪᗮ νȩͯϚĉᗮ(͆ C͆ c͆ Éɼ % ͆ഇበᗮዏᅼࡐྲྀበแࡐዏ੎়ᗮ়ഇᅼ੎हዏแᒹᗮ ഇྲྀዏအᗮ ࡐᗮ हအ༌Ⴜࡐᅼഇበအྲྀᗮ ዏఀᅼ੎੎Ÿࡐ়়ᅼ੎በበᗮ ഇྲྀበዏᅼᎯहዏഇအྲྀᗮ ᑌഇዏఀᗮ ෟᎯ༌Ⴜበᗮ ዏအᗮ ዏఀ੎ᗮ ࡐႼႼᅼအႼᅼഇࡐዏ੎ᗮ Ⴜแࡐह੎በȪᗮ ֏အᅼᗮഇྲྀበዏࡐྲྀह੎ĉᗮအ૤ᗮዏఀ੎ᗮ૤အᅼ༌ᗮҿĨ͆ 0͆ዏᅼࡐྲྀበแࡐዏ੎በᗮഇྲྀዏအѓᗮ

Ϯ &Ϯ Ϯ Ϯ K.‘.͆ (!͆

K.‘.͆ (4͆

ݫఀ੎ᗮᅼ੎༌ࡐഇྲྀഇྲྀஸᗮႼᅼအ়Ꭿहዏഇအྲྀበᗮ૤အᅼᗮࡐᅼ੎ᗮዏᅼࡐྲྀበแࡐዏ੎়ᗮࡐበᗮ૤အแแအᑌበгᗮ

ܺᎯႼႼအበ੎ᗮഇበᗮအ૤ᗮዏఀ੎ᗮ૤အᅼ༌ᗮ(c͆ , , Ϗ(% 4͆ ר૤ᗮ(c͆ഇበᗮዏᅼᎯ੎ĉᗮዏఀ੎ྲྀᗮᑌ੎ᗮഇ༌༌੎়ഇࡐዏ੎แᒹᗮ คྲྀအᑌᗮዏఀࡐዏᗮഇዏበ੎แ૤ᗮഇበᗮዏᅼᎯ੎ĉᗮበအᗮ(c 4͆!͆ഇበᗮዏఀ੎ᗮበࡐ༌੎ᗮࡐበᗮ(4͆!͆ר૤ᗮ(c͆ഇበᗮ૤ࡐแበ੎Ńᗮ ዏఀ੎ྲྀᗮ(%͆༌Ꭿበዏᗮ࣒੎ᗮ੎ᐕࡐแᎯࡐዏ੎়ĉᗮበအᗮᑌ੎ᗮ༌ࡐค੎ᗮ(c ࣒͆੎ᗮዏఀ੎ᗮ้ࡐ࣒੎แᗮအ૤ᗮዏఀ੎ᗮ୪ᅼበዏᗮ ഇྲྀበዏᅼᎯहዏഇအྲྀᗮഇྲྀᗮዏఀ੎ᗮहအ়੎ᗮ૤အᅼᗮ(% ͆ ݫఀ੎ᗮዏᅼᎯ੎ᗮࡐྲ়ྀᗮ૤ࡐแበ੎ᗮ੎ᒏഇዏበᗮအ૤ᗮ(%͆ࡐᅼ੎ᗮዏఀ੎ᗮበࡐཌྷ੎ᗮ ࡐበᗮዏఀ੎ᗮዏᅼᎯ੎ᗮࡐྲ়ྀᗮ૤ࡐแበ੎ᗮ੎ᒏഇዏበᗮအ૤ᗮ(͆ᅼ੎በႼ੎हዏഇᐕ੎แᒹȪᗮ

Inherited AGributes

(25)

Example

if ( x < 100 || x > 200 && x != y ) x = 0;

is translated into:

if x < 100 goto L2 goto L3

L3: if x > 200 goto L4 goto L1

L4: if x != y goto L2 goto L1

L2: x=0 L1:

if x < 100 goto L2

ifFalse x > 200 goto L1 ifFalse x ! = y goto L1 L2: x=0

By removing several redundant jumps we can obtain the equivalent:

(26)

Transla=ng Short-Circuit Expressions Using Backpatching

E → E or M E | E and M E | not E

| ( E )

| id relop id | true

| false M → ε

M : marker nonterminal

Synthesized attributes:

E.truelist backpatch list for jumps on true E.falselist backpatch list for jumps on false

M.quad location of current three-address quad

Idea: avoid using inherited a"ributes by genera=ng par=al

code. Addresses for jumps will be inserted when known.

(27)

Backpatch Opera=ons with Lists

•  makelist(i) creates a new list containing three-address location i, returns a pointer to the list

  merge(p

1

, p

2

) concatenates lists pointed to by p

1

and p

2

, returns a pointer to the concatenated list

•  backpatch(p, i) inserts i as the target label for each of

the statements in the list pointed to by p

(28)

28

Backpatching with Lists: Example

a < b or c < d and e < f

100: if a < b goto _ 101: goto _

102: if c < d goto _ 103: goto _

104: if e < f goto _ 105: goto _

backpatch

100: if a < b goto TRUE 101: goto 102

102: if c < d goto 104 103: goto FALSE

104: if e < f goto TRUE 105: goto FALSE

(29)

Backpatching with Lists: Transla=on Scheme

M → ε { M.quad := nextquad() } E → E1 or M E2

{ backpatch(E1.falselist, M.quad);

E.truelist := merge(E1.truelist, E2.truelist);

E.falselist := E2.falselist } E → E1 and M E2

{ backpatch(E1.truelist, M.quad);

E.truelist := E2.truelist;

E.falselist := merge(E1.falselist, E2.falselist); } E → not E1 { E.truelist := E1.falselist;

E.falselist := E1.truelist } E → ( E1 ) { E.truelist := E1.truelist;

E.falselist := E1.falselist }

(30)

Backpatching with Lists: Transla=on Scheme (cont’d)

E → id1 relop id2

{ E.truelist := makelist(nextquad());

E.falselist := makelist(nextquad() + 1);

emit(‘if’ id1.place relop.op id2.place ‘goto _’);

emit(‘goto _’) }

E → true { E.truelist := makelist(nextquad());

E.falselist := nil;

emit(‘goto _’) }

E → false { E.falselist := makelist(nextquad());

E.truelist := nil;

emit(‘goto _’) }

(31)

Flow-of-Control Statements and Backpatching: Grammar

S → if E then S

| if E then S else S | while E do S

| begin L end | A

L → L ; S | S

Synthesized attributes:

S.nextlist backpatch list for jumps to the next statement after S (or nil)

L.nextlist backpatch list for jumps to the next statement after L (or nil)

S1 ; S2 ; S3 ; S4 ; S5 backpatch(S1.nextlist, 200) backpatch(S2.nextlist, 300)

100: Code for S1 200: Code for S2 300: Code for S3

Jumps out of S1

(32)

Flow-of-Control Statements and Backpatching

The grammar is modified adding suitble marking non-terminals S → A { S.nextlist := nil }

S → begin L end

{ S.nextlist := L.nextlist } S → if E then M S1

{ backpatch(E.truelist, M.quad);

S.nextlist := merge(E.falselist, S1.nextlist) } L → L1 ; M S { backpatch(L1.nextlist, M.quad);

L.nextlist := S.nextlist; } L → S { L.nextlist := S.nextlist; } M → ε { M.quad := nextquad() }

A → …

Non-compound statements, e.g. assignment, func&on call

(33)

Flow-of-Control Statements and Backpatching (cont’d)

S → if E then M1 S1 N else M2 S2

{ backpatch(E.truelist, M1.quad);

backpatch(E.falselist, M2.quad);

S.nextlist := merge(S1.nextlist,

merge(N.nextlist, S2.nextlist)) } S → while M1 E do M2 S1

{ backpatch(S1.nextlist, M1.quad);

backpatch(E.truelist, M2.quad);

S.nextlist := E.falselist;

emit(‘goto M1.quad’) }

N → ε { N.nextlist := makelist(nextquad());

(34)

Summarizing…

•  Transla=on from source code to intermediate representa=on can be performed in a syntax- directed way during parsing

•  We considered transla=on of expressions and statements to three address code, with a

simplified handling of names (for example: no defini=ons)

•  More effec=ve transla=on of boolean expressions for flow control require inherited aGributes

•  They can be avoided using backpatching

34

Riferimenti

Documenti correlati

•  Every nonterminal has one (recursive) procedure responsible for parsing the nonterminal’s syntactic category of input tokens. •  When a nonterminal has multiple

•  An NFA accepts an input string x (over Σ ) if and only if there is some path with edges labeled with symbols from x in sequence from the start state to some.. accepting state

special end symbol # to make accepting states important: the new expression is r#. •  Construct a syntax tree

•  A backward analysis propagates informa@on in the opposite direc@on in which the program flows. •  A forward analysis propagates informa@on in the same direc@on in which

/* Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to

•  LALR parsing (Look-Ahead LR) merges two or more LR(1) state into one state to reduce table size. •  Less powerful

§  The types of variables and parameters are not declared, and cannot be inferred by the Python compiler.. So run-time type checks are needed to detect

•  Each state is a mul=way branch based on the next input character.. Puxng the