51
UNIVERSITETET I OSLO Det matematisk-naturvitenskapelige fakultet Eksamen i : INF5110 Eksamensdag : Torsdag 9. juni 2005 Tid for eksamen : 09.00 - 12.00 Oppgavesettet er på : 5 sider Vedlegg : intet Tillatte hjelpemidler : Alle trykte og skrevne Les gjennom hele oppgavesettet før du begynner å løse den første oppgaven. Dersom du savner opplysninger i oppgaven, kan du selv legge dine egne forutsetninger til grunn og gjøre rimelige antagelser, så lenge de ikke bryter med oppgavens "ånd". Gjør i så tilfelle rede for disse forutsetningene og antagelsene. Oppgave 1 a) Bruk Thompson’s konstruksjon til å lage en NFA for det regulære uttrykket (aa|b)*(a|cc)* b) Skriv følgende NFA ut som et regulært uttrykk: c) Gjør om NFAen fra pkt b) til en DFA. 2 a a b 4 1 3 a ε b b 1

UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

UNIVERSITETET I OSLO

Det matematisk-naturvitenskapelige fakultet

Eksamen i : INF5110 Eksamensdag : Torsdag 9. juni 2005 Tid for eksamen : 09.00 - 12.00 Oppgavesettet er på : 5 sider Vedlegg : intet Tillatte hjelpemidler : Alle trykte og skrevne Les gjennom hele oppgavesettet før du begynner å løse den første oppgaven. Dersom du savner opplysninger i oppgaven, kan du selv legge dine egne forutsetninger til grunn og gjøre rimelige antagelser, så lenge de ikke bryter med oppgavens "ånd". Gjør i så tilfelle rede for disse forutsetningene og antagelsene. Oppgave 1 a) Bruk Thompson’s konstruksjon til å lage en NFA for det regulære uttrykket (aa|b)*(a|cc)* b) Skriv følgende NFA ut som et regulært uttrykk:

c) Gjør om NFAen fra pkt b) til en DFA.

2

aa

b 4

1 3

a

ε

bb

1

Page 2: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

Oppgave 2 Betrakt følgende grammatikk G1: E → S E | num S → - S | + S | ε hvor E og S er ikke-terminalsymboler, E er startsymbol og: +, -, num er terminalsymboler (med vanlig tolkning). a) Beskriv kort hvordan setninger som G1 kan produsere ser ut, og gi ett eksempel på en setning med 4

terminalsymboler.

b) Gi et regulært uttrykk som lager de samme setningene som G1.

c) Gi et kort argument som bestemmer hvike(n) av følgende fem grupper G1 hører med i: 1. LR(0) 2. SLR(1) 3. LALR(1) 4. LR(1) 5. Ingen av de overstående.

Hint: Finn ut om G1 er entydig.

---- Vi skal nå se på en annen grammatikk G2: F → + F | - F | num Hvor F er ikke-terminalsymbol (og startssymbol) og +, -, num igjen er terminalsymboler. d) Du skal nå lage LR(0)-DFA-en for G2 rett fra denne grammatikken hvor du har utvidet

grammatikken med en ny produksjon F’ → F (og hvor F’ nå er startsymbolet). Nummerér hver av tilstandene.

e) Ut fra det svaret på d), angi med en kort begrunnelse hvilke(n) type grammatikk G2 er (jfr. spørsmål c) ovenfor).

f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er.

g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet og input for hver av skift- eller reduser-operasjonene du gjør under parseringen.

Oppgave 3 a) Det følgende er et fragment av en grammatikk for et språk med klasser: class → class name superclass { decls } decls → decls ; decl | decl decl → variable-decl decl → method-decl method-decl → type name ( params ) body type → int |bool | void superclass → name

2

Page 3: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

Ord i kursiv er meta-symboler, ord og tegn i fet skrift er terminal-symboler, mens name representerer et navn som scanneren leverer. Det kan antas at name har attributtet ’name’. Metoder med samme navn som klassen er ’konstruktører’, og det gjelder følgende regel: Konstruktører må være spesifisert med typen void Lag semantiske regler for hver regel i følgende fragment av en attributtgrammatikk. Sett først opp hvilke attributter du trenger Hint: Du kan klare deg uten en hel symboltabell.

Grammar Rule Semantic Rule

class → class name { decls }

decls → decls ; decl

decls → decl

Decl → variable-decl Skal ikke fylles ut

Decl → method-decl

method-decl → type name ( params ) body

Type → int

Type → bool

Type → void

(skriv av tabellen og fyll den ut på et innføringsark; fyll ikke direkte inn på oppgavearket) b) Anta ta vi har et språk med klasser og subklasser. Alle metoder er virtuelle, slik at de kan redefineres i subklasser. Gitt følgende klassedefinisjoner: class A { int i; void P {... AP ...}; void Q {... AQ ...}; } class B extends A { int j; void Q {... BQ ...}; void R {... BR ...}; } class C1 extends B { void P {... C1P ...}; void S {... C1S ...}; }

3

Page 4: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

class C2 extends B { int k; void R {... C2R ...}; void T {... C2T ...}; } Vis hvordan objekter av klassene C1 og C2 vil være strukturert (layout) og tegn virtuell-tabellen for hver av klassene. Bruk navnene i metodekroppene over til å angi elementene i virtuell-tabellene. c) Vi innfører nå muligheten for å kunne spesifisere en metode til å være final. Det skal bety, som i Java, at den ikke lenger er virtuell, dvs at den ikke kan redefineres i subklasser. Anta at vi i klassen B spesifiserer metoden Q til å være final. Må vi da endre på virtuell-tabellen for B-objekter? Begrunn svaret. d) Vi innfører nå operatoren instanceof som i Java: Det boolske uttrykket ’<refExpr> instanceof <class>’ er True hvis objektet som <refExpr> peker på har en klasse som ikke er ’null’, og som er klassen <class> eller en subklasse av klassen <class>, ellers False. For å kunne implementere denne operatoren utvider vi virtuell-tabellen med en peker til klasse-deskriptoren, som det er en av for hver klasse i programmet. Klassedeskriptoren har da en variabel ’super’, som peker til klasse-deskriptoren for superklassen. Klasser uten eksplisitt superklasse har den spesielle klasse Object som super. Eksemplet under viser dette for et objekt av klassen B:

vt

B-objektsuper

klassedeskriptor

for B super

klassedeskriptor

for A

012

cl

klassedeskriptorfor Object

Skisser algoritmen som beregner verdien av ’<refExpr> instanceof <class>’. e) For å effektivisere testen på ’instanceof’ innfører vi (inspirert av display/kontekst vektor for nestede blokker) at en klassedeskriptor har en tabell ’supers’, som inneholder alle superklassene for klassen samt klassen selv. Denne tabellen har som indeks klassens ’subklassenivå’ startende med 0 for Object, 1 for rotklassen i et subklassehierarki, 2 for neste nivå, osv. I vårt eksempel har klassen A subklasseniv1, B har 2, C1 og C2 har begge 3. For klassene A og B ser klassedeskriptorene med supers-tabellene slik ut:

4

Page 5: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

Du skal forklare hvordan denne tabellen kan effekstivisere instanceof-testen, og til å illustrere dette skal vi innføre ytterligere to klasser: class C11 extends C1 { ...} class C21 extends C2 {...} Lag supers-tabellene for klassedeskriptorene for C11 og C21, og vis hvordan følgende tester gjøres: rC11 = new C11; rC11 instanceof C1 (1) rC11 instanceof C2 (2)

------------- o 0 o ----------------

Slutt på oppgavesettet – lykke til!

Arne Maus og Birger Møller-Pedersen

5

Page 6: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

1

UNIVERSITETET I OSLO

Det matematisk-naturvitenskapelige fakultet

Eksamen i : INF5110 Eksamensdag : Tirsdag 6. juni 2006 Tid for eksamen : 09.00 - 12.00 Oppgavesettet er på : 5 sider Vedlegg : Intet Tillatte hjelpemidler : Alle trykte og skrevne Les gjennom hele oppgavesettet før du begynner å løse den første oppgaven. Dersom du savner opplysninger i oppgaven, kan du selv legge dine egne forutsetninger til grunn og gjøre rimelige antagelser, så lenge de ikke bryter med oppgavens "ånd". Gjør i så tilfelle rede for disse forutsetningene og antagelsene.

Oppgave 1 Det følgende er et fragment (dvs ikke-interessante deler av grammatikken er ikke tatt med) av en grammatikk for et språk med prosedyrer. Alle prosedyrer har én parameter, og den er enten ’by value’, ’by reference’ (keyword ref), eller ’by-value-result’ (keyword result).

procedure → proc id (param) stmt param → type id | ref type id | result type id call → id(exp) exp → id exp → id[exp] exp → exp aritop exp

Følgende programmer erklærer begge en integer variabel i og en prosedyre change, og programmene assigner 1 til i, kaller prosedyren change(i) og skriver ut verdien av i. Forskjellen er at Program 1 har prosedyren med ’call by reference’, mens Program 2 har prosedyren med ’call by value result’. Språket følger vanlige statiske skopregler. Program 1:

{ int i; proc change(ref int p) { p=2; i=0; }; i=1; change(i); write(i) }

Page 7: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

2

Program 2: { int i; proc change(result int p) { p=2; i=0; }; i=1; change(i); write(i) }

1a Anta at semantikken for ’ by-value-result’ er slik at adressen (location) til den aktuelle parameter beregnes ved prosedyrekallet (procedure entry). Hva skriver Program 1 og Program 2 ut når de utføres? 1b Anta at semantikken for ’ by-value-result’ er slik at adressen (location) til den aktuelle beregnes på nytt ved avslutning av prosedyrekallet (prosedyre exit). Hva skriver Program 1 og Program 2 ut når de utføres? 1c Den enkle reglen i dette språket er at prosedyrer med en parameter ’by reference’ eller ’by-value-result’ bare kan kalles med et uttrykk som enten er en enkel variabel (id) eller en indisert variabel (id[exp]). Fyll ut de tomme felter i følgende attributtgrammatikk slik at attributtet ok for call er true hvis kallet er gjort ifølge denne regel, ellers false. Symboltabellen er innrettet på akkurat denne reglen, slik at navn på prosedyrer er assosiert med en verdi som sier om denne prosedyre har en parameter ’by reference’ (verdien ref), ’by value-result’ (verdien result) eller ’by value’ (value). lookupkind(id.name)gir verdien som svarer til hvordan prosedyren med navn id.name er definert. Det er ikke behov for å sjekke om prosedyrenavnet (id) i en call-setning faktisk er deklarert.

Grammar Rule Semantic Rule

procedure → proc id (param) stmt

insert(id.name, param.kind)

param → type id

param → ref type id

param → result type id

call → id (exp) call.ok =

exp1 → id [exp2]

exp → id

exp1 → exp2 aritop exp3

Page 8: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

3

Oppgave 2 Betrakt følgende grammatikk G, hvor S og T er ikketerminal-symboler, # og a er terminalsymboler, og S er startsymbolet.

S → TS S → T T → #T T → a

a) Finn First og Follow-mengdene til T og S (og la $ betegne ’end-of-file’ som i boka). b) Formulér med dine egne ord hvilke sekvenser av terminalsymboler du kan lage ut fra S’.

c) Avgjør om du kan lage et regulært uttrykk som uttrykker disse sekvensene av # og a som du

kan utlede fra S, og hvis svaret er ’ja’, gi et slikt regulært uttrykk. d) Innfør et nytt start-symbol S’ → S og lag LR(0)-DFA-en for G rett fra denne grammatikken.

Nummerér tilstandene.

e) Gi et kort argument som bestemmer hvike(n) av følgende fem grupper G hører med i: a. LR(1) b. LALR(1) c. SLR(1) d. LR(0) e. Ingen av de overstående.

Hint: Finn ut hvilke mulige konflikter du har i DFA-en og/eller om grammatikken er entydig..

f) Lag parseringstabellen for G ut fra den typen grammatikk den er.

g) Vis hvordan setningen: ”a#a” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet og input

for hver av skift- eller reduser-operasjonene du gjør under parseringen. Få også med numrene til tilstandene på stakken (som i boka).

Page 9: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

4

Oppgave 3 3a Anta ta vi har et språk med klasser og subklasser. Alle metoder er virtuelle, slik at de kan redefineres i subklasser. Klassen Graph definerer (sammen med klassene Node, Edge) grafer som består av Node-objekter som er forbundet med Edge-objekter. Et objekt av klassen Graph representerer en graf. Alle noder i en graf antas å være forbundet via attributen startNode, som er en referanse til ett Node- objekt. Deler av klassedefinisjoner som ikke er signifikante for oppgaven er antydet med ’...’

class Node{ ... } class Edge{ ... } class Graph { Node startNode; void connect(Node n1,n2) { ... connects two Nodes by creating an Edge-object ...}; }

De følgende klasser definerer subklasser (City og Road) til henholdsvis Node og Edge, en subklasse (RoadAndCityGraph) til Graph, og en subklasse (TravelingSalesmanGraph) til RoadAndCityGraph. Metoden display vil tegne grafen med utgangspunkt i startNode.

class City extends Node { String name; ... } class Road extends Edge { String name; int distance; ... } class RoadAndCityGraph extends Graph { String country; void connect(Node n1,n2) { ... connects two City objects (treated as Nodes), by creating a Road object ... }; void display() { ... displays Roads and Cities with names...}; } class TravelingSalesmanGraph extends RoadAndCityGraph { void display() { ... displays Cities with names, and Roads with name and distance ... }; }

Vis hvordan objekter av klassene Graph, RoadAndCityGraph og TravelingSalesmanGraph vil være strukturert (layout) og tegn virtuell-tabellen for hvert av objektene. Bruk navn av formen <klassenavn>::<metodenavn> til å angi hvilken definisjon som gjelder for hvert objekt.

Page 10: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

5

3b Anta at klassene Node og Edge er definert som indre klasser til klassen Graph, og at slike indre klasser kan redefineres i subklasser, på samme måte som virtuelle metoder. Vi kan altså snakke om at indre klasser er virtuelle klasser. Redefinerte klasser blir automatisk subklasser av de tilsvarende virtuelle klasser; f.eks. vil klassen Node i RoadAndCityGraph være en subklasse til klassen Node i Graph.

class Graph { class Node{ ... } class Edge{ ... } Node startNode; void connect(Node n1,n2) { ... connects two Nodes by creating an Edge-object ...}; } class RoadAndCityGraph extends Graph { class Node { String name; ... } class Edge { String name; int distance; ... } String country; void connect(Node n1,n2) { ... connects two Node objects by creating an Edge-object ... }; void display() { ... displays Edges and Nodes with names...}; } class TravelingSalesmanGraph extends RoadAndCityGraph { void display() { ... displays Edges and Nodes with names, and Edges with distance ... }; }

På samme måte som virtuell-tabellen for virtuelle metoder brukes ved kall på virtuelle metoder, så vil man nå også trenge en annen virtuell-tabell ved generering av objekter av virtuelle klasser. F.eks. innholder metoden connect i klassen Graph en generering av et Edge-objekt. Hvis denne metoden kalles i et RoadAndCityGraph-objekt, skal man generere et Edge-objekt slik det er definert i klassen RoadAndCityGraph. Vis hvordan en slik virtuell-tabell for virtuelle klasser kan se ut. Ikke ta med virtuell-tabellen fra spørsmål 3a. Forklar hvordan man bruker virtuell-tabellen ved utførelse av new Edge() i metoden connect i klassen Graph.

------------- o 0 o ----------------

Slutt på oppgavesettet – lykke til!

Arne Maus og Birger Møller-Pedersen

Page 11: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

MED SVARFORSLAG

UNIVERSITETET I OSLO Det matematisk-naturvitenskapelige fakultet

Eksamen i : INF5110 - Kompilatorteknikk Eksamensdag : Onsdag 1. juni 2011 Tid for eksamen : 14.30 - 18.30 Oppgavesettet er på : 7 sider (pluss vedlegg) Vedlegg : 1 side (side 8 rives ut, fylles ut og leveres i ”hvit” besvarelse) Tillatte hjelpemidler : Alle trykte og skrevne Les gjennom hele oppgavesettet før du begynner å løse oppgavene. Dersom du savner opplysninger i oppgavene, kan du selv legge dine egne forutsetninger til grunn og gjøre rimelige antagelser, så lenge de ikke bryter med oppgavens "ånd". Gjør i så tilfelle rede for disse forutsetningene og antagelsene.

Oppgave 1 (25%) Vi skal se på et antall grammatikker, nemlig følgende:

i. A → b A c | ε ii. A → b A b | b

iii. A → b A b | c

1a Her er A startsymbol og eneste ikke-terminal, mens b og c er terminaler. For hver av de tre grammatikkene: Beregn First og Follow til A, tegn LR(0)-DFA’en (etter utvidelese med A’ → A), og angi om den er en SLR-grammatikk eller ikke. Angi også hvilke av grammatikkene, om noen, som er LR(0)-grammatikker. Svar 1a Grammatikk i: A → b A c | ε First(A) = { b, ε } Follow(A) = { c, $ }

Page 12: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

2

SLR(1): Det kunne være tilstand 2 som gav problemer, men siden b (eneste terminal-kant ut av tilst. 2) ikke er med i etterfølger-mengden til A, så går det bra. LR(0): Nei. Både i tilstand 0 og 2 må man lese neste tegn for å avgjøre hva man skal gjøre. Grammatikk ii: A → b A b | b First(A) = { b } Follow(A) = { b, $ }

SLR(1): Nei. Siden b er med i etterfølgermengden til A vet vi ikke om vi skal redusere eller skifte i tilstand 2. LR(0): Nei. Når den ikke er SLR(1) er den heller ikke LR(0) Grammatikk iii: A → b A b | c First(A) = { b, c } Follow(A) = { b, $ }

SLR(1): Ja, den er faktisk LR(0) som angitt under, og da er den også SLR(1) LR(0): Ja, for i hver tilstand er det bare snakk om enten å skifte eller å redusere.

A’ → . A A → . b A c A → .

A’ → A .

A → b . A c A → . b A c A → .

A → b A . c A → b A c .

0 1

2 3 4

A

b A c

b

A’ → . A A → . b A b A → . b

A’ → A .

A → b . A b A → b . A → . b A b A → . b

A → b A . b A → b A b .

0 1

2 3 4

A

b A c

b

A’ → . A A → . b A b A → . c

A’ → A .

A → b . A b A → . b A b A → . c

A → b A . b A → b A b .

0 1

2 3 4

A

b A c

b

A → c .

c c

Page 13: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

3

1b For hver av de tre grammatikkene, avgjør om grammatikken er LR(1). Det er her mulig å avgjøre dette og forklare det uten å tegne opp LR(1)-DFA’en, men det er også en OK besvarelse om du tegner opp denne og avgjør det ut fra den. Svar 1b Grammatikk i: Siden grammatikken er SLR(1) er den også LR(1) Grammatikk ii: Denne er ikke LR(1). Under en parsering etter denne grammatikken skal man gå over fra å skifte til å redusere når vi har lest inn den midterste b-en, men vi kan ikke generelt vite når vi er der om vi bare kan lese ett tegn framover. Grammatikk iii: Siden grammatikken er LR(0) er den også LR(1) 1c Angi for hver av grammatikkene over om det språket de genererer er regulært, og for de som er det skal du angi et regulært uttrykk for språket. For de grammatikker du mener ikke genererer et regulært språk, forklar hvorfor. Svar 1c Grammatikk i: Den generelle formen for en setning er først null eller flere b-er, som er fulgt av like mange c-er, og dette språket er ikke regulært. Det er vel OK bare å vise til at det er angitt på foilene et sted (i en fasit?) at språk der man skal ha like mange ”sånne” som ”slike” (f.eks. ”…((((()))))…”) ikke er regulære. Ellers kan man f.eks. argumentere slik: Et språk er som kjent regulært hvis og bare hvis man kan parsere det ved bare å huske en endelig mengde informasjon om den delen man har lest (eller være i én av et endelig antall tilstander) når man leser fra venstre mot høyre. Men i grammatikk i må man kunne huske hvor mange b-er man har lest når man finner første c, og det antallet kan være ubergrenset stort. Grammatikk ii: Den generelle setningen her er rett og slett et odde antall b-er. Dette språket er regulært siden det kan beskrives ved følgende regulære uttrykk b ( b b )* Grammatikk iii: Den generelle setningen her er to sekvenser med like mange b-er, og med en c i midten. Dette språket er ikke regulært, av samme grunn som for grammatikk i. 1d Tegn opp en parseringstabell for grammatikk i, og sørg for at den blir uten konflikter. Angi så en steg-for-steg LR-analyse av setningen ”bbcc”, på samme måte som øverst på side 213 i boka (tabell 5.8).

Page 14: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

4

Svar 1d Ut fra LR(0)-DFA’en og de SLR(1)-betrakninger som er gjort over, får vi følgende entydige tabell: b c $ A ------------------------------------------------------------------------------- 0 s2 r(A→ε) 1 1 accept 2 s2 r(A→ε) r(A→ε) 3 3 s4 4 r(A→bAc) r(A→bAc) ------------------------------------------------------------------------------- Parseringen blir da som følger: $ 0 b b c c $ $ 0 b 2 b c c $ $ 0 b 2 b 2 c c $ Så skjer det mest interessante: $ 0 b 2 b 2 A 3 c c $ $ 0 b 2 b 2 A 3 c 4 c $ $ 0 b 2 A 3 c $ $ 0 b 2 A 3 c 4 $ $ 0 A 1 $ Og dette gir “accept”

Oppgave 2 (20%) Anta at vi har et objekt-orientert språk, hvor en virtuell metode i en klasse kan redefineres (”overriding”) i en subklasse av denne klassen. En virtuell metode deklareres med en virtual modifier, mens en redefinisjon deklareres med modifieren redef. Metoder uten virtual er vanlige metoder og kan altså ikke redefineres. Merk at dette ikke er helt som i Java. I Java er alle metoder virtuelle, mens her gjelder det bare de som har modifieren virtual. Det følgende er klasser definert i dette språket: class A { virtual void m(int x,y){...} void p(){...} virtual void q(){...} } class B extends A{ redef void m(int x,y){...} void r(){...} } class C extends A{ redef void q(){...} } class D extends B{ redef void m(int x,y){...} } class E extends B{ redef void q(){...} class F extends C{ redef void m(int x,y){...}

Page 15: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

5

2a Vi antar nå først at klassen for et gitt objekt bestemmer, på vanlig måte, hvilken versjon av en virtuell metode som kalles. Lag virtuell-tabellene for klassene A, B, C, D,E og F. For hvert element i tabellene skal du bruke notasjonen A::m for å angi hvilken metode som gjelder. Indeksen i disse tabeller starter på 1. Svar 2a

2b I resten av oppgaven skal vi for virtuelle metoder ha den semantikk at en redefinert virtuell metode, for eksempel m, skal, som det første den gjør, kalle den tilsvarende virtuelle eller redefinerte metode (dvs m ) i den nærmeste superklasse som har en slik, før den utfører sin egen body. Dette vil i sin tur føre til at redefinerte eller virtuelle metoder m i videre superklasser utføres. Dette kunne man implementere ved å sette inn det riktige kall som første statement i bodies på redefinerte metoder. Men semantikken rundt parameteroverføring skal her være litt spesiell slik at denne enkle måten ikke vil fungere. Parametrene som gis med i det opprinnelige kallet skal nemlig gå direkte som parametre til den metoden som utføres først, altså den som er merket virtual i programmet. Når denne er ferdig utført skal de verdiene som da står i dens parametervariable overføres som aktuelle parametre til den neste dypere redefinerte metode, osv. Dette gjør at stakken av kall må settes opp først, og de aktuelle parametre må gis til den første virtuelle metode som skal utføres. Hvis for eksempel m kalles med m(1,2) på et D-objekt, så skal stakken settes opp og de aktuelle parametre gis til aktiveringsblokken tilsvarende A::m, og utførelsen skal starte med utførelsen av A::m. Ved exit av A::m skal verdiene av parametrene x og y gis som aktuelle til den versjon av m som da skal utføres. For å implementere denne nye semantikk utvides virtuell-tabellen, slik at det for hvert indeks blir en liste av metode-angivelser. Denne listen vil dermed angi sekvensen av de metoder som skal kalles. Tegn de nye virtuell-tabeller for klassene D og F. Tabellene for B og C er gitt under. For metode-angivelser brukes samme notasjon som før.

Page 16: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

6

Svar 2b

2c I denne del av oppgaven skal du skissere hvordan stakken i 2b kan lages ved hjelp av de nye virtuell-tabeller. Du kan anta at du har en run-time rutine makeActivationRecord(metode). Denne tar som parameter en metode-angivelse (for eksempel A::m) med nok informasjon til å lage en aktiveringsblokk med riktig størrelse, men du skal skissere hvordan control-link og retur-adresse settes i aktiveringsblokken. Anta at den aktuelle virtuell-tabell holdes i en variabel med navn vt, den aktuelle metoden holdes i en variabel method, og funksjonen index(method) gir deg index i vt. Anta videre at inngangen i tabellen gir en peker til første metode-angivelse, og at hver av disse har en next peker. For metode-angivelsen som svarer til den virtuelle metode hvor den defineres for første gang (i eksemplet her m i A) er denne peker none. Du kan gjerne illustrere resultatet for et kall m(1,2) på et D-objekt, men om resten er riktig er det OK uten.

Page 17: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

7

Svar 2c caller = fp; method = vt(index(method)); while method =/= none do { ar = makeActivationRecord(method); ar.conrolLink = caller; ar.returAdresse = første statement i metoden som tilsvarer fp method = method.next; caller = ar; } 2d Overføring av parametre mellom de enkelte utførelser av en virtuell metode kan åpenbart ikke gjøres som en del av det å sette opp stakken i 2c, men må gjøres ved bl.a. å sette inn ekstra kode i metoder merket virtual eller redef. Du må også innføre en ekstra variabel i de aktuelle aktiveringsblokkene. Hvilken kode skal settes inn og hvor? Koden kan gjøre bruk av alle deler av den aktuelle aktiveringsblokk. Svar 2d

Utfør følgende kode, som det siste før exit, i alle aktiveringer bortsett fra den dybeste: controlLink.x = x controlLink.y = y

Oppgave 3 (30%) Det følgende er et fragment av en grammatikk for et språk med klasser. En klasse kan ikke ha noen superklasse, men den må implementere en eller flere interfacer:

class → class name implements interfaces { decls } decls → decls ; decl | decl decl → variable-decl | method-decl method-decl → type name ( params ) body type → int | bool | void interfaces → interfaces, interface | interface interface → name

Ord i kursiv er ikke-terminaler, ord og tegn i fet skrift er terminal-symboler, mens name representerer et navn som scanneren leverer. Det kan antas at name har attributtet ’name’. Det som er spesielt med dette språk er at de av en klasses metoder som har samme navn som en av interfacene klassen implementerer er ’konstruktører’ for klassen. Det kan i klassen gjerne være flere metoder, som har samme navn som et interface, men da med forskjellige parametre; dette er imidlertid ikke temaet i denne oppgave. Generering av objekter har formen ”new <class-name>.<interface-name>(<actual parameters>)”, da forskjellige klasser kan implementere samme interfacen. En krav i dette språket er at konstruktører må være spesifisert med typen void, og det er dette kravet som skal sjekkes med de semantiske regler du skal sette opp. Lag semantiske regler for dette kravet i følgende fragment av en attributtgrammatikk.

Page 18: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

8

For å lage reglene kan du bruke de funksjoner og de mengder du trenger, bare du definerer dem. Besvar dette spørsmålet ved å bruke vedlegget side 8.

Page 19: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

9

Grammar Rule Semantic Rule

class → class name implements interfaces { decls }

decls1 → decls2 ; decl

decls → decl

decl → method-decl

method-decl → type name ( params ) body

type → int type.type = int

type → bool type.type = bool

type → void type.type = void

interfaces1 → interfaces2, interface

interfaces → interface

interface → name interface.interfaceName = name

Svar 3

Page 20: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

10

Grammar Rule Semantic Rule

class → class name implements interfaces { decls }

decls.setOfInterfaceNames = interfaces.setOfInterfaceNames

decls1 → decls2 ; decl decls2.setOfInterfaceNames = decls1.setOfInterfaceNames decl.setOfInterfaceNames = decls1.setOfInterfaceNames

decls → decl decl.setOfInterfaceNames = decls.setOfInterfaceNames

decl → method-decl method-decl.setOfInterfaceNames = decl.setOfInterfaceNames

method-decl → type name ( params ) body

if method-decl.setOfInterfaceName.has(name.name) then if (not(type.type = void))then error(“constructor not of type void”)

type → int type.type = int

type → bool type.type = bool

type → void type.type = void

interfaces1 → interfaces2, interface

interfaces1.setOfInterfaceNames= interfaces2.setOfInterfaceNames + [interface.interfaceName]

interfaces → interface

interfaces.setOfinterfaceNames.insert( interface.interfaceName)

interface → name interface.interfaceName= name

Oppgave 4 (25%) (Jeg kunne her tenke meg at hver av oppgavene får samme % etter oppdeling av 4a i 4a1 og 4a2, altså 5% på hver). Vi skal her se på verifikasjon (omtrent som i en Java/JVM-loader) av en enkel type P-kode. Den har få instruksjoner, og alle verdier er heltall. Vår P-kode utføres på vanlig måte, med en stakk med verdier under utførelsen. Under er v en programvariabel, og L er adressen til et sted i programmet. Vår spesielle P-kode har følgende instruksjoner: lda v Henter adressen til variablen v opp på toppen av stakken. En adresse er også et heltall. ldv v Henter verdien av variablen v opp på toppen av stakken ldc k Henter konstanten k opp på stakken add Legger sammen de to øverste verdier på stakken, fjerner (popper) dem fra stakken og legger svaret på toppen av stakken.

Page 21: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

11

sto Her tolkes det som ligger på toppen av stakken som en verdi, og det nest øverst som en adresse. Instruksjonen kopierer verdien inn til den angitte adressen i lageret, og popper både verdien og adressen. jmp L Hopp til program-adressen L jge L (og likeledes: jgt L, jle L, jlt L, jeq L, jne L) Denne instruksjonen er litt enklere enn vanlig, nemlig slik: Om verdien på toppen av stakken er større eller lik 0 så hoppes det (og tilsvarende for de andre fem). Verdien på toppen av stakken poppes uansett om det hoppes eller ikke. lab L Angir at program-adressen L er på dette stedet i programmet. 4a (Jeg ser at denne burde vært delt i to oppgaver, og under kommer først den opprinnelige oppgaven, og så den oppdelte utgaven (delt i 4a1 og 4a2). Merk at den siste setningen i den opprinnelige er tatt med i 4a1, men den ble vel egentlig et litt dummy spørsmål) (Opprinnelig 4a:) Vi tenker oss at vi skal lage en verifikator for programmer i vår P-kode (altså for sekvenser av P-instruksjoner). Angi flest mulig ting som denne verifikatoren bør/kan teste angående et gitt slikt program, og skisser hvilke datastrukturer m.m. du vil bruke for å utføre testen. Beskriv tingene direkte i forhold til vår spesielle P-kode. Et program skal både starte og avslutte med tom stakk. Du kan anta at programmets hoppinstruksjoner faktisk går til en instruksjon i programmet, så dette behøver du ikke teste Forklar også i hvilken forstand et P-kode-program er ”riktig” om det passerer testen din. 4a1 (Oppdelt utgave) Vi tenker oss at vi skal lage en verifikator for programmer i vår P-kode (altså for sekvenser av P-instruksjoner). Angi flest mulig ting som denne verifikatoren bør/kan teste angående et gitt slikt program. Forklar også i hvilken forstand et P-kode-program er ”riktig” om det passerer testen din. Svar 4a1 Alt som skal på stakken er her heltall (også adresser), så verifikatoren kan ikke se noen typemessig forskjell på forskjellige stakker. Det eneste den kan se på er størrelsen av stakken. Vi vet at vi skal starte med tom stakk på toppen av programmet, og det er naturlig å sjekke følgende tre ting:

- At det alltid er nok elementer på stakken til å gjøre en angitt operasjon. For eksempel må de være minst to elementer på stakken for å gjøre en add-operasjon, og minst ett element for å gjøre en jge-instruksjon.

- Sjekke at stakken er tom ved slutten av programmet. - Når man gjør et hopp til en gitt label L (eller kommer til lablen L fra forrige

instruksjon) skal stakken alltid ha samme størrelse.

Om et program er kommet vel gjennom denne testen vet vi at stakken alltid vil ha de nødvendige heltall på stakken når en operasjon skal utføres, og det gjelder samme hvilken vei man går gjennom programmet. 4b2 (Oppdelt utgave) Skisser hvilke datastrukturer m.m. du vil bruke for å utføre testen. Beskriv tingene direkte i forhold til vår spesielle P-kode. Et program skal både starte og avslutte med tom stakk. Du kan anta at programmets hoppinstruksjoner faktisk går til en instruksjon i programmet, så dette behøver du ikke teste. Svar 4a2 (Det var jo egentlig bare spørsmål etter datastrukturen, men for å forstå den må man jo

Page 22: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

12

også kjenne bruken. Om datastrukturen og antydninger av hvordan den skal brukes henger sånn rimelig sammen, så skal vi vel ikke forlange så mye mer) Det er det siste punktet i svaret på 4a1 som krever litt ekstra, og man bør ved hver ”lab L” i programmet gjøre plass til en liten data-record som her kalles S(L) (”status ved L) som har én variabel SD (stakkdybde, som fra starten er -1) og en boolsk variabel ”SV” (som fra starten er FALSE, og som sier om man har sjekket programmet videre fra L). Dessuten trenger vi en global mengde av labler som vi kaller ”LabelKurven”. Utføring av verifikasjonen: De to første punktene over går greit å sjekke ved bare løpende å holde greie på stakkdybden mens man ”utfører” programmet. Selve testen startes så med tom stakk, og man begynner å ”utføre programmet” fra toppen f.eks. slik som angitt under. (Dette er egentlig bare et søk gjennom alle kantene i en graf, der de betingede hoppene er noder med to ut-kanter, og der labler er noder med flere inn-kanter. Søket kan også godt gjøres rekursivt, men under gjøres det mer som bredde først. Hoved-vitsen er altså å sjekke at alle veier til hver node har samme stakk-dybde):

- Man har altså en løpende stakkdybde (heltall), og ved hver instruksjon gjør man de forandringer av denne som den aktuelle instruksjonen foreskriver (og man sjekker hele tiden at det alltid er nok elementer på stakken til den aktuelle instruksjonen, ellers forkastes programmet).

- Ved hver ”lab L”-instruksjon gjør man følgende test: Anta at stakkdybden langs den veien du har fulgt vil være sd ved L. Dersom lablens SD er -1, setter vi SD til sd (dette er første gang vi hører om denne lablen, og vi angir at vi nå har sett en vei dit som har stakkdybde SD=sd). Ellers tester vi at sd er lik SD, og om det ikke stemmer skal programmet forkastes (det finnes da to veier til lablen som har forskjellige SD). Til slutt sjekker vi om S(L).SV er FALSE, og i så fall setter vi den til TRUE, og fortsetter på vanlig måte. Om S(L).SV er TRUE avslutter vi sjekken på dette punkt (det er gjort allerede), og henter en label L (med S(L).SV = FALSE) fra ”Label-Kurven”. Om kurven er tom er vi ferdig med hele sjekken, ellers går vi til L, setter vår løpende stakkdybde til S(L).SD, setter S(L).SV til TRUE, og fortsetter på vanlig måte.

- Om man kommer til et betinget hopp til L ser man først på S(L).SD og gjør en test av denne slik som angitt i forrige punkt. Om S(L).SV = FALSE legger vi L i LabelKurven (vi må starte herfra senere). Deretter fortsetter man på vanlig måte med instruksjonen etter det betingede hoppet.

- Om man kommer til et ubetinget hopp ”jmp L” gjør man også først den samme testen som angitt over. Om S(L).SV er FALSE setter vi den til TRUE og fortsetter sjekken fra L med den aktuelle stakkdybden. Om S(L).SV er TRUE gjør vi som over: Vi avslutter sjekken på dette punkt, og henter en label L (med S(L).SV = FALSE) fra ”Label-Kurven”. Om kurven er tom er vi ferdig med hele sjekken, ellers går vi til L setter vår løpende stakkdybde til S(L).SD, setter S(L).SV til TRUE, og fortsetter på vanlig måte.

Page 23: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

13

4b Under står tre programmer i vår P-kode. Sjekk for hver av dem om de passerer testen din, og angi hva som eventuelt går galt om de ikke gjør det. Program 1: lda x ldv y ldv z jge L1 add add ldc 5 lab L1 ldc 8 sto Program 2: lda x ldv y ldv z jge L1 ldc 5 add lab L1 sto Program 3: lda x ldv y ldv z jge L1 ldc 5 add ldv u lab L1 sto Svar 4b Det første programmet er galt fordi det bare vil være ett element på stakken ved den siste add-instruksjonen. Det andre programmet er OK Det tredje programmet er galt fordi de to veiene som fører til lablen L1 gir stakkdybde 3 (uten hopp) og 2 (med hopp). 4c Vi vil oversette vår P-kode til maskinkode for en maskin der alle operasjoner (inkl. sammenlikninger) må gjøres mellom verdier som ligger i registre, og der kopiering mellom lageret

Page 24: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

14

og registre bare kan gjøres med egne LOAD- og STORE-instruksjoner. Under oversettelsen har vi en stakk med diskriptorer. Vi skal se på det å oversette P-instruksjonen ”ldv v”. Spørsmålet er om det da er fornuftigst å produsere en LOAD-instruksjon som henter verdien av variabelen ”v” opp i et register, eller om det er best bare å legge en diskriptor på stakken som sier at denne verdien ligger i variabelen ”v”. Drøft dette ut fra forskjellige forutsetninger, f.eks. ut fra hva språket som vi oversetter fra lover om rekkefølgen ved beregning av uttrykk (men også ut fra andre ting som du mener er aktuelle). Svar 4c Grovt sett: Dersom språk-reglene sier at man må utføre uttrykk i rekkefølge fra venstre mot høyre, så må man lage LOAD-instruksjon fra v (program-variabel) til et register med en gang. Om man er fri til å beregne uttrykket i vilkårlig rekkefølge er det lurt å lage en diskriptor. Da står man fritt til å vente med opphentingen til en operasjon faktisk trenger den verdien, slik at den ikke har tatt opp et register fram til den faktisk skal brukes. Her kan man optimalisere mye ved f.eks. å sjekke om det finnes noen prosedyrekall i det aktuelle uttrykket slik at verdier på variable kan forandre seg. 4d Vi vil igjen oversette vår P-kode til maskinkode, slik som i oppgave 4c, og vi skal anta at vi skal oversette én og én basal blokk, og at alle registre skal tømmes på kontrollert måte etter utførelsen av en basal blokk. Spørsmålet her er hvilke data diskriptorene på stakken skal inneholde, og hva du eventuelt trenger av andre typer diskriptorer. Vi antar at vi kan tillate oss å lete gjennom alle kompilator-stakkens diskriptorer hver gang vi lurer på hvor visse verdier er etc., slik at informasjon vi kan finne på denne måten ikke behøver å lagres i ekstra diskriptorer. Forklar også kort hvordan du kan finne den informasjonen du trenger under kodegenereringen, og hvordan du eventuelt vil bruke de ekstra diskriptorene du vil ha. Svar 4d Diskriptorene på stakken bør hvertfall inneholde følgende:

- Om det er en konstant (og da hvilken), - om det er verdien til en program-variabel (og da hvilken), eller - om det er en verdi som ligger i et register (og i så fall hvilket).

Diskriptorene på stakken vil generelt ikke inneholde nok informasjon til å holde orden på hva som er i hvilke registere, om en variabel-verdi er i sin ”hjemmeposisjon”, etc. Dette blir opplagt når man ser at stakken kan bli tom mellom setningene inne i den basale blokken, og at det da fremdeles kan være variabel-verdier som ligger i registre i påvente av at verdiene kanskje skal brukes en gang til. Det fører til at man får omtrent de samme behov som i kodegenererings-algoritmen i boka, og at det kan være greit med både en register-diskriptor og en adresse-deskriptor. Vi skal jo også, ved slutten av den basale blokka, sette alle verdier tilbake til deres ”hjemmeposisjon” i sine variable, og da er disse diskriptorene viktige.

Lykke til!

Stein Krogdahl og Birger Møller-Pedersen

Page 25: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

15

Vedlegg til besvarelse av Oppgave 3 Kandidat nr: ................... Dato: .............................. Grammar Rule Semantic Rule

class → class name implements interfaces { decls }

decls1 → decls2 ; decl

decls → decl

decl → method-decl

method-decl → type name ( params ) body

type → int type.type = int

type → bool type.type = bool

type → void type.type = void

interfaces1 → interfaces2, interface

interfaces → interface

interface → name interface.interfaceName = name

Page 26: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

MED SVARFORSLAG

UNIVERSITETET I OSLO

Det matematisk-naturvitenskapelige fakultet

Eksamen i : INF5110 - Kompilatorteknikk Eksamensdag : Onsdag 6. juni 2012 Tid for eksamen : 14.30 - 18.30 Oppgavesettet er på : 6 sider (pluss vedlegg) Vedlegg : 1 side (side 7 rives ut, fylles ut og leveres i ”hvit” besvarelse) Tillatte hjelpemidler : Alle trykte og skrevne Les gjennom hele oppgavesettet før du begynner å løse oppgavene. Dersom du savner opplysninger i oppgavene, kan du selv legge dine egne forutsetninger til grunn og gjøre rimelige antagelser, så lenge de ikke bryter med oppgavens "ånd". Gjør i så tilfelle rede for disse forutsetningene og antagelsene. Deler av oppgave 3 besvares ved bruk av vedlegg.

Oppgave 1 (25%) Vi skal se på følgende grammatikk G1: S → a | S # S | S @ S Her er S startsymbol og eneste ikke-terminal, mens a, # og @ (samt avslutnings-symbolet $) er teminalsymboler. 1.a Gi en konkret begrunnelse for at G1 er flertydig. Svar 1.a Setningen a # a @ a har i det minste to syntakstrær: S S S # S S @ S a S @ S S # S a a a a a 1.b Anta at:

-­‐ Operasjonen # har lav presedens, og er høyreassosiativ -­‐ Operasjonen @ har høy presedens, og er venstreassosiativ

Page 27: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

2

Angi en ny grammatikk G2 som er entydig, som beskriver samme språket som G1 og som gir et syntaks-tre som følger de to reglene over. Du kan innføre nye ikke-terminaler, og du behøver ikke argumentere for at G2 er entydig ut over å vise til at den likner tilsvarende entydige grammatikker i pensum. Svar 1.b Det er to rimelige svar: S -> T + S | T S -> T + S | T T -> T @ F | F T -> T @ a | a F -> a Dette er satt opp etter samme prinsipp som på side 119 i læreboka 1.c Vi ser på grammatikkene G1, G2, samt følgende grammatikk G3 (der + er et nytt terminal-symbol): S → a | S # S | S @ S | + S + Angi for hver av språkene L(G1), L(G2) og L(G3) om de er eller ikke er regulære. Forklar, og angi et regulært uttrykk for de som eventuelt er regulære. Svar 1.c G1 og G2 er jo samme språket, og det er regulært og kan beskrives f.eks. slik: a ( (# | @) a)* For G3 er alle setninger som kan dannes med bare «+» og «a» følgende: a +a+ ++a++ +++a+++ … Det må her altså være like mange «+»-er både foran og bak «a»-en. Det er kjent fra pensum at et slikt språk ikke er regulært. Ser man på hele språket til G3 vil setningene også inneholde «@» og «#», men «+»-ene vil komme inn på en liknende måte som over, så språket er ikke regulært. 1.d Tegn opp LR(0)-DFA’en til den flertydige grammatikken G1 (med vanlig bruk av S’).

Page 28: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

3

Svar 1.d

1.e Beregn First og Follow til S i G1 (med vanlig bruk av $). Angi så hvilke tilstander i DFA’en fra 1.d som har:

A. konflikter som ikke kan løses med LR(0)-betrakninger, men som kan løses med SLR(1)-betrakninger. Forklar.

B. konflikter som ikke kan løses med SLR(1)-betrakninger. Forklar.

Svar 1.e First(S) = { a } Follow (S) = { # @ $ }

A. Det er en LR(0)-konflikt i tilstand 1, som kan løses i SLR(1) ved at man reduserer (aksept) ved $, og skifter ved # og @

B. Det er LR(0)-konflikter både i tilstand 5 og 6. Disse kan ikke løses med SLR-betrakninger siden det er aktuelt både å skifte og redusere for # og @ (men om det kommer $ vet vi at det skal reduseres).

Kommentar: Vi visste at det her ville bli konflikter som ikke er løselige av noen type LR-betraktninger, siden grammatikken er flertydig. 1.f For tilstandene under punkt B i spørsmål 1.e, angi hvordan du ville løse konfliktene i disse «for hånd», om du skal få den presedensen og assosiativiteten som er angitt i 1.b? Tilsand 5: Her ligger nå S @ S på toppen av stakken. Derfor: For #: Reduser, siden @ binder sterkere enn # For @: Reduser, fordi @ er venstreassosiativ For $: Reduser (ingen konflikt) Tilstand 6: Her ligger nå S # S på toppen av stakken. Derfor:

S’ -> .S S -> .a S -> .S # S S -> .S @ S

S’ -> S. S -> S. # S S -> S. @ S

S -> S # .S S -> .a S -> .S # S S -> .S @ S

S -> S @ .S S -> .a S -> .S # S S -> .S @ S

S -> S # S. S -> S. # S S -> S. @ S

S -> S @ S. S -> S. # S S -> S. @ S

S -> a.

a

#

@ #

a

a

S

S S #

@

@ 6

3

2

1 0

5

4

Page 29: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

4

For #: Skift, siden # er høyreassossiativ For @: Skift, fordi @ binder sterkere enn # For $: Reduser (ingen konflikt) 1.g Sett opp en SLR(1)-parseringstabell for L(G1) ut fra svaret på spørsmålene 1.d og 1.f. Tabellen skal altså ha maks én aksjon i hver rute, og den resulterende syntaksanalysen skal altså følge reglene fra 1.b. Svar 1.g a # @ $ S 0 s2 1 1 s4 s3 acc. 2 r(S -> a) r(S -> a) r(S -> a) 3 s2 5 4 s2 6 5 r(S->S @ S) r(S->S @ S) r(S->S@S) 6 s4 s3 r(S->S # S)

Oppgave 2 (25%) 2.a Vi tenker oss i denne oppgaven at vi har et Java-lignende språk hvor metoder kan ha lokalt definerte metoder. Dessuten kan man deklarere variable og metoder også på ytterste programnivå. Dette skal fungere som vanlig i språk som er statisk skopet. Det følgende er et program i dette språket. Oppstart av programmet skjer ved å kalle main-metoden.

{ class C { void m1(){ void f() {}; f(); } void m2() { int i; void g() { int j; j=i; }; i=1; rC.m1(); }; }; C rC; void main() { rC = new C (); rC.m2(); } }

Tegn kall-stakken som den ser ut når aktiveringsblokken (’activation record’) for f er på toppen av

Page 30: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

5

stakken for første gang, inklusive variable, access-linker og control-linker, bortsett fra access-linker for metoder som er direkte deklarert i en klasse (kan da anta at access-linken peker til C-objektet, men dette er ikke viktig for oppgaven). Svar 2.a

2.b I resten av oppgave 2 innfører vi metoder som parametere. Det er en regel at aktuelle parametere til slike må være metoder som er direkte synlige fra kallstedet. Eksemplet over blir så endret slik at f blir en metodeparameter, og kallet på f i m1 blir da et kall på en metodeparameter:

{ class C { void m1(void f()){ f(); } void m2() { int i; void g() { int j; j=i; }; i=1; rC.m1(g); }; }; C rC; void main() { rC = new C (); rC.m2(); } }

Tegn kall-stakken som den ser ut når aktiveringsblokken for kallet rC.m1(g)er på toppen av stakken. Hvordan representeres metoden g i denne aktiveringsblokken slik at kallet på parameteren f (dvs kallet f() i m1) kan utføres?

Page 31: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

6

Svar 2.b Parameteren f er representert ved et par <ip, ep>, hvor ip peker ut koden for den aktuelle parameteren og hvor ep peker ut aktiveringsblokken for den blokken som tekstlig omslutter definisjonen av den aktuelle parameteren. I det aktuelle kall peker ip ut koden for g og ep peker ut aktiveringsblokken for m2, hvor g er definert.

2.c Tegn kall-stakken som den ser ut når aktiveringsblokken for kallet av f i m1 er på toppen av stakken. Forklar hvordan access-link for aktiveringsblokken på toppen av stakken settes i dette spesielle tilfellet.

Page 32: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

7

Svar 2.c

Oppgave 3 (25%) Det følgende er en del av en grammatikk for et språk med klasser. Det er bare tatt med de produksjoner som har betydning. Klasser har for eksempel også variable, men de er ikke viktige her. class → class name { methodDecls } methodDecls → methodDecls ; methodDecl methodDecls → methodDecl methodDecl → type name ( parameters ) body parameters → parameters , parameter parameters → parameter parameter → type name type → int type → bool

Den regel som skal spesifiseres ved hjelp av en attributtgrammatikk er at en klasse kan ha flere enn én constructor, men de må ha forskjellige signaturer i form av antall og/eller typer av parametere. Lag attributtgrammatikken basert på ideen om at methodDecl har et attributt constructorName som er satt sammen av navnet på metoden og strenger som tilsvarer typene på parameterne. En constructor C med parametertypene (int, int) vi således få constructorName ’C_i_i’, mens en constructor C med parametertyper (int, bool) vil få constructorName ’C_i_b’. Testen vil derfor

Page 33: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

8

være, som antydet i første rekke i tabellen under, at alle navne i mengden av constructornavne er forskjellige. Vi innrømmer at dette ikke er det mest optimale, men det er ikke poenget her. Definer de regler som gjør denne testen mulig. Anta at du har funksjoner og operatorer for å innsette navne i en menge og for å konkatenere strenge og tegn. Svar oppgave 3

Grammar Rule Semantic Rule

class → class name { methodDecls }

class.OK = all names in methodDecls.constructorNameSet are different

methodDecls1 → methodDecls2 ; methodDecl

methodDecls1.constructorNameSet = methodDecls2.constructorNameSet + methodDecl.constructorNameSet

methodDecls → methodDecl methodDecls.constructorNameSet = methodDecl.constructorName

methodDecl → type name ( parameters ) body

methodDecl.constructorName = name.name + ‘_’ + parameters.paramTypes

parameters1 → parameters2 , parameter

parameters1.paramTypes = parameters2.paramTypes + ‘_’ + parameter.typeName

parameters → parameter

parameters.paramTypes = parameter.typeName

parameter → type name

parameter.typeName = type.typeString

type → int type.typeString = ‘i’

type → bool type.typeString = ‘b’

Page 34: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

9

Oppgave 4 (25%) En metode med to value-parametere er oversatt til følgende sekvens av TA-instruksjoner. Den eneste typen i språket er heltall. x = <verdien av første aktuelle parameter> (Du kan skrive dette slik: «x = par1») y = <verdien av andre aktuelle parameter> (Tilsvarende) z = x + y label L1 u = x + 1 x = u + y if (y < x) goto L4 // Vi antar at det finnes en TA-instruksjon av denne formen y = u + 1 u = y + x label L2 z = 5 if (x < u) goto L1 x = u + y v = x + y u = v + 1 goto L5 label L4 v = z + 3 x = y + u label L5 z = v + 4 z = x + z return z 4.a Del programmet opp i basale blokker, og tegn opp flyt-grafen for programmet. Sett navnene B0, B1, osv. på blokkene.

Page 35: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

10

Svar 4.a, 4.b og 4.c

4.b For hver basal blokk, finn hvilke variable som faktisk er i live både foran og etter blokka (altså inLive og outLive for blokka). Du kan bruke metoden fra pensum til å finne svaret, eller gjøre egne betraktninger. Det er greit å enten gi svaret direkte på flytgrafen fra 4.a, eller du kan tegne opp flyt-grafen en gang til (gjerne uten kode i nodene) med alle mengdene inLive og outLive satt på der de hører hjemme. 4.c Ut fra informasjonen fra 4.b og detaljene i TA-instruksjonene er det mulig å se

(1) om noen av TA-instruksjonene i programmet kan fjernes uten at det forandrer sluttresultatet når programmet utføres. Angi i så fall disse

(2) om det er variable som, i en eller annen eksekvering, kan bli brukt før de har fått verdi. Angi i så fall disse.

Om du ikke har fått til 4.b kan du likevel forsøke å svare på denne oppgaven enten direkte fra programmet, eller fra flyt-grafen.

x = par1 y = par2 z = x + y

label L1 u = x + 1 x = u + y if (y < x) goto L4

y = u + 1 u = y + x label L2 z = 5 if (x < u) goto L1

x = u + y v = x + y u = v + 1 goto L5

label L4 v = z + 3 x = y + u

z = v + 4 z = x + z return z

B1

B0

B2

B3 B4

B5

TOM = Ø

{ x y z } { x y z }

{ u x y z }

{ u x }

{ v x }

TOM = Ø

{ v x }

{ u y z }

{ u x y z } { v x }

{ u y }

4.c.2: Siden denne, altså inLive(B0), er tom er det ingen variable som kan tenkes å bli brukt før de har fått verdi

4.c.1: Siden u ikke er med i outLive(B3), så er denne tre-adresse-setningen helt uten virkning på resultatet

4.b: Denne mengden, altså outLive(B2), blir i første omgang bare { u y }, men etter at også inLive(B1) er beregnet og blir tilbakeført, får den også x og z

Page 36: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

11

4.d (Er uavhengig av det over) I pensum er det diskutert hvordan man kan lage TA-kode for kortsluttede boolske uttrykk som står som betingelser i if- eller while-setninger. Dette gjøres rekursivt, og den rekursive kodegenererings-metoden har to label-parametere som koden skal hoppe til når man vet at det lokale uttrykket er h.h.v. true eller false. Programmet for dette er gjengitt under. Vi oversatte i pensum til TA-kode og ikke til P-kode bl.a. for å slippe å tenke på at det under beregning av uttykket kan være noe på stakken ved hopp, som kanskje ikke stemmer med det stedet det hoppes til. Vi skal her se nærmere på hvor stort dette problemet blir, og hvordan vi eventuelt kan korrigere for det. Som svar forklar først i detalj hvordan ting vil forholde seg med stakkdybder under uttrykksberegningen, og skissér så hvordan dette kan håndteres under kodegenereringen, gjerne ved å henvise til koden under. Merk: Vi antar at P-koden skal lages slik at stakken under kjøring er tom mellom setninger, og at den derved er tom når beregningen av det boolske uttrykket starter. Hint: Det er sikkert lurt å se på hvordan P-koden blir for noen konkrete boolske uttrykk. Program fra pensum. Det genererer TA-kode for logiske uttrykk i if- og while-setninger:

void genBoolCode(String labT, labF) { … case ”||”: { String labx = genLabel(); left.genBoolCode(labT, labx); emit2(”label”, labx); right.genBoolCode(labT, labF); } case ”&&”: { String labx = genLabel(); left.genBoolCode(labx, labF); emit2(”label”, labx); right.genBoolCode(labT, labF); } case ”not”: { // Har bare ”left”-subtre left.genBoolCode(labF, labT); } case ”<”: { String temp1, temp2, temp3; temp1 = left.genIntCode(); temp2 = right.genIntCode(); temp3 = genLabel(); emit4(temp3, temp1, «lt», temp2); // Lager instruksjonen: ”temp3 = temp1 < temp2” emit3(«jmp-false», temp3, labF);

emit2(«ujp», labT); } }

Page 37: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

12

Svar 4.d Saken her er at så lenge man skal generere kode som kortslutter de boolske uttrykkene så blir det ingen problemer med stakkdybden i det hele tatt. Det kommer av at man, så fort det er en boolsk verdi på stakken, vil teste om denne er true/false, og enten hoppe eller fortsette rett til neste instruksjon. Teste-instruksjonen er slik at den i begge tilfelle vil ta bort det som er på toppen av stakken, og dermed vil det aldri bygge seg opp noe på stakken. Vi kan se på følgende eksempel, der a, b c og d er boolske variable. Beregningen vil da følge pilene, ut fra at alle grener som ligger over teksten er TRUE-grener, og de under er FALSE-grener:

Her vil stakken alltid være tom når kontrollen går langs en kant, og ved hver av variablene blir denne variabelen pushet på stakken, men forsvinner igjen i og med TRUE/FALSE-testen Dette betyr at en kodegenererings-prosedyre som skal lage P-kode kan lages etter nøyaktig samme mal som den angitt i oppgaven som lager TA-kode. Vi behøver ikke tenke på stakkdybden i det hele tatt.

if ( a and b ) or ( c and d ) then … else ...

Page 38: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

UNIVERSITETET I OSLO Med svarforslag

Det matematisk-naturvitenskapelige fakultet

Eksamen i : INF5110 - Kompilatorteknikk Eksamensdag : Onsdag 5. juni 2013 Tid for eksamen : 14.30 - 18.30 Oppgavesettet er på : 8 sider (pluss vedlegg) Vedlegg : 1 side (side 9 rives ut, fylles ut og leveres i ”hvit” besvarelse) Tillatte hjelpemidler : Alle trykte og skrevne Les gjennom hele oppgavesettet før du begynner å løse oppgavene. Dersom du savner opplysninger i oppgavene, kan du selv legge dine egne forutsetninger til grunn og gjøre rimelige antagelser, så lenge de ikke bryter med oppgavens "ånd". Gjør i så tilfelle rede for disse forutsetningene og antagelsene.

Oppgave 1 (35%) Vi ser først på følgende grammatikker: G1: S → ( S ) | ε   G2: S → ( S ) | a Her er S eneste ikke-terminal og dermed også startsymbol. Symbolene ’(’, ’)’ og ’a’ er terminalsymboler (sammen med ’$’, som har den vanlige funksjonen).

1a Er ett av eller begge språkene L(G1) og L(G2) regulære? Angi et regulært uttrykk for det/de som eventuelt er regulære. Svar 1a Ingen av grammatikkene er regulære. Dette kommer av at setningene vil ha formen ”((…()…))” eller ”((…(a)…))”, med like mange parenteser på begge sider. Dette å beskrive at to sekvenser av symboler i en setning skal være like lange (når det ikke er noen begrensning på lengden av sekvensene) kan ikke gjøres med regulære uttrykk (eller, en endelig automat kan ikke sjekkes at det er slik).

1b Vi skal så se på en grammatikk G3 som minner om de over, men som er litt mer komplisert, og vi vil undersøke hvilke egenskaper den har. G3: A → ( S ) | ( B ]

Page 39: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

2

B → S | ( B S → ( S ) | ε Her er A, B og S ikke-terminaler og A er startsymbol. Symbolene ’(’, ’)’ og ’]’ er terminalsymboler (sammen med ’$’, som har den vanlige funksjonen). Angi fire setninger i språket L(G3), slik at de best mulig dekker de forskjellige setningstypene som forekommer i L(G3). Gi også, med ord, en felles, generell beskrivelse av setningene i L(G3). Svar 1b Setningene kan f.eks. være: () (((()))) (((()] (] Den tomme strengen er altså ikke i L(G3), og heller ikke ”((()))]”. En generell beskrivelse kan være: ”Setningene starter med en eller flere venstre-parenteser, og avsluttes enten med like mange høyre-parenteser, eller med ekte færre (gjerne null) høyre-parenteser samt en høyre-hakeparentes”.

1c Finn First- og Follow-mengdene til A, B og S i G3, med bruk av ε  som  i  boka. Du behøver bare å oppgi svaret. Svar 1c First Follow A ( $ B ( ε ] S ( ε                                                  )  ]

1d Tegn opp LR(0)-DFAen til G3 (etter å ha innført et nytt startsymbol A’ på vanlig måte). Hint: Det blir rundt 10 tilstander, og to av dem har 6 itemer. Vær nøye med å få med alle tillukninger og å slå sammen like tilstander. Svar 1d G3 på helt basal form, og med den ekstra ytterste produksjonen, er angitt ved siden av LR(0)-DFAen i svaret under  Det  blir  11  tilstander,  som  angitt  under.    Vi  nummererer  også  tilstandene  for  oppgave  1e  

Joakim
Notat
?? Follow ??
Page 40: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

3

1e Sett nummer på tilstandene fra 0 og oppover. Se gjennom alle tilstandene, og diskuter kort de som har (minst) én LR(0)-konflikt. Hvilke av disse har også en SLR(1)-konflikt? Er G3 en SLR-grammatikk? Svar 1e Her er det fire tilsander som har LR(0)-konflikter, nemlig 2, 3, 6 og 9. Det er itemet ”S → .”  som  lager  problemer  alle  fire  steder.    Dette  sier  at  å  redusere  med  ”S → ε”  er  en  mulighet,  mens  alle  de  andre  itemene  i  alle  disse  tilstandene  angir  skift.      Om  man  ser  på  etterfølger-­‐mengder  (og  dermed  med  SLR(1)-­‐filosofi)  så  lar  de  seg  imidlertid  løse.    Etterfølgermengden  til  S  er    altså  ’)’  og  ’]’  og  den  til  B  er  bare    ’]’    Tilst.  2  og  3:    Her  kan  det  bare  skiftes  for  ’(’,  mens  reduksjon  med  ”S  → ε”  bare  er  aktuelt  for    ’)’  og  ’]’.    Altså  SLR(1).    Tilst.  6  og  9:  Her  kan  det  bare  skiftes  for  ’)’,  mens  det  bare  kan  reduseres  for  ’]’.    Altså  SLR(1).  

1f Du skal tegne opp deler av parserings-tabellen for G3 ut fra SLR(1)-filosofi, nemlig de to radene (linjene) som tilsvarer de to tilstander med 6 itemer. Dersom G3 ikke er SLR(1) skal du angi alle aktuelle alternativer i de rutene der det er SLR(1)-konflikt. Pass på å få med alle de riktige

A’ → . A A → . ( S ) A → . ( B ]

A’ → A .

A → ( . S ) A → ( . B ] S → . ( S ) S → .  B → . S B → . ( B

S → ( . S ) B → ( . B S → . ( S ) S → .  B → . S B → . ( B

A → ( S . ) B → S .

B → ( B .

A → ( B . ]

A → ( B ] . A → ( S ) .

0 1

2 3

A

5 6

7 8

B

(

S S

(

B

] )

(

4

S → ( S . ) B → S .

10

9

S → ( S ) .

)

Grammatikken:

A’→ A A → ( S ) A → ( B ] B → S B → ( B S → ( S ) S → ε       First Follow A ( $ B ( ε ] S ( ε                                )  ]  

Page 41: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

4

symbolene langs øvre kant av tabellen. Svar 1f Ut  fra  konklusjonen  fra  forrige  oppgave,  og  LR(0)-­‐DFA-­‐en,  blir  tabellen  for  tilstandene  2  og  3  slik ( ) ] $ A B S 2 s3 r(S → ε)              r(S → ε)                                                                                                  5                          6 3 s3 r(S → ε)              r(S → ε)                                                                                                  4                          9    

Oppgave 2 (20%) Anta at vi har et objekt-orientert språk, hvor alle metoder i klasser er virtuelle slik at de kan redefineres i subklasser. En standard måte å implementerer tilstandsmaskiner i et slikt språk er å representere tilstandene ved objekter av klasser i et tilstandshierarki, med transisjoner som virtuelle metoder som redefineres i de forskjellige state subklasser. De følgende klasser implementerer en tilstandsmaskin for klassen Switch (på norsk: Bryter) med tilstandene Off og On. Tilstanden On inneholder nye tilstander (Green og Red) og transisjoner mellom disse gjøres ved kall på metoden shift(). En slik ’composite state’ representeres ved en abstrakt klasse, som brukes som superklasse til alle tilstander som den skal inneholde: dermed gjelder de transisjoner som er definert for On også for tilstandene Green og Red.

State

Off

On

GreenRed

onOff

onOffshift

shift

Page 42: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

5

class Switch{ State state = new Off(); int noOfShifts = 0; void onOff(){state.onOff()}; void shift(){state.shift()}; void print() {out.println(noOfShifts); noOfShifts = 0}; void setState(State s) {state = s}; } abstract class State{ Switch s; void onOff (){}; void shift(){}; } class Off extends State{ void onOff(){s.setState(new Green())} } abstract class On extends State{ void onOff(){s.setState(new Off())} } class Green extends On{ void shift(){ s.noOfShifts=s.noOfShifts+1; s.setState(new Red())} } class Red extends On{ void shift(){ s.noOfShifts=s.noOfShifts+1; s.setState(new Green())} }

Alle tilstandsobjekter har en peker (s) til det Switch-objekt, som har tilstandsmaskinen. Vi har ikke tatt med hvordan denne settes, da det ikke er viktig for oppgaven. Et program som bruker disse klasser vil lage et objekt av klassen Switch og kalle metodene onOff og shift på dette. Alt etter hvilken tilstand Switch–objektet er i (representert ved variablen state) vil de aktuelle redefinisjoner av transisjons-metodene bli utført.

2a Lag virtuell-tabellene for alle klassene som trenger dette. For hvert element i tabellene skal du bruke notasjonen C::m for å angi hvilken metode som gjelder.

Page 43: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

6

Svar 2a

2b Hvordan ser stakken ut rett før skift av tilstand (endring av variablen state i Switch-objektet) gitt at en metode main kaller metoden onOff på et Switch-objekt aSwitch: aSwitch = new Switch(); aSwitch.onOff () Svar 2b

2c I denne siste del av oppgaven har språket blitt utvidet slik at funksjoner nå kan være parametere til metoder, og at metoder kan ha lokale funksjoner. Funksjoner defineres som vanlige metoder.

State::onOff

State::shift

1

2

State

Off::onOff

State::shift

1

2

Off

On::onOff

State::shift

1

2

On

On::onOff

Green::shift

1

2

Green

On::onOff

Red::shift

1

2

Red

main

Switch::onOff

Off::onOffcl

cl

Page 44: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

7

Med denne utvidelse kan man få tilstandsmaskinen til ikke bare å skifte tilstand ved å kalle en transisjonsmetode, men samtidig få utført ting som brukeren av tilstandsmaskinen ønsker å få gjort. Dette gjøres ved å tilføye en funksjonsparameter til transisjons-metodene onOff og shift i Switch, overføre den til kallene på de tilsvarende metoder i State objektene, og kalle den som en del av disse: class Switch{ State state = new Off(); int noOfShifts = 0; void onOff(void action()){state.onOff(action)}; void shift(void action()){state.shift(action)}; void print() {out.println(noOfShifts); noOfShifts = 0}; void setState(State s){state = s}; } abstract class State{ Switch s; void onOff (void action()){}; void shift(void action()){}; } class Off extends State{ void onOff(void action()){ action(); s.setState(new Green())} } abstract class On extends State{ void onOff(void action()){ action(); s.setState(new Off())} } class Green extends On{ void shift(void action()){ s.noOfShifts=s.noOfShifts+1; action(); s.setState(new Red())} } class Red extends On{ void shift(void action()){ s.noOfShifts=s.noOfShifts+1; action(); s.setState(new Green())} }

Anta at vi har følgende main-metode, med en lokalt definert funksjon som overføres som parameter til onOff og shift: void main{ void enFinAction(){out.println(’så skifter vi tilstand’)}; Switch aSwitch = new Switch(); aSwitch.onOff(enFinAction); }

Spørsmålene til 2c er: 1) Skisser og forklar hvordan action-parameteren (til for eksempel metoden onOff i klassen

Switch) implementeres, hvordan den overføres i kallet state.onOff(action), og hvordan den kalles i utførelsen av action() i metoden onOff i klassen Off.

2) Tegn stakken (med control og static links) som den ser ut når action() i metoden onOff i klassen Off utføres.

Page 45: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

8

Svar 2c 1)

2)

main

Switch::onOff

Off::onOffcl

cl

action: <ep, ip>

code for enFinAction

action: <ep, ip>

main

Switch::onOff

Off::onOffcl

cl

action: <ep, ip>

enFinAction

action: <ep, ip>

cl sl

Page 46: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

9

Oppgave 3 (20%) I stedet for å lage tilstandsmaskiner ved hjelp av klasser og subklasser, så vil vi i denne oppgaven lage et språk spesielt for å programmere tilstandsmaskiner. Vi har ikke tatt med alle detaljer i språket, bare de som er aktuelle for det vi skal se på. Definisjoner av events og bruk av dem i transisjoner er med i grammatikken, men de har ingen betydning for oppgaven og derfor ikke med i de semantiske regler. Det følgende er et fragment av grammatikken for språket:

statemachine → state state → state name ({events states transitions entryPoints})?

events → events, event events → event

event → name

states → states, state states → state transitions → transitions, transition transitions → transition transition → on eventId from endPoint to endPoint entryPoints → entryPoints → entryPoints, entryPoint entryPoints → entryPoint entryPoint → entry name on name

endPoint → name eventId → name

Ord i kursiv er ikke-terminaler, ord og tegn i fet skrift er terminal-symboler, mens name representerer et navn som scanneren leverer. Det kan antas at name har attributtet ’name’. En state er enten en ’simple state’ (med bare et name) eller en ’composite state’. En transisjon defineres ved hvilket event som utløser transisjonen, samt ’source’ og ’target’ endPoint, som hver er et navn som identifiserer en simple state, en composite state eller et entryPoint. Et entryPoint er et punkt på en composite state, og det defineres ved to navn: (entryPoint navn, composite state navn). Et krav i dette språket er at transisjoner ikke kan krysse grensen for en composite state som vi så i oppgave 2, hvor onOff fra tilstanden Off gikk direkte til tilstanden Green i tilstanden On. Reglene er som følger:

1. transisjoner kan bare være mellom states på samme nivå eller mellom states og entryPoints på states på samme nivå

2. ’target’ for en transisjon kan ikke være en composite state, bare en ’simple state’ eller et entryPoint på en composite state.

Page 47: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

10

Lag semantiske regler for dette kravet i følgende fragment av en attributtgrammatikk. Du kan bruke følgende funksjoner: insert(name, kind, level): Setter inn i symboltabellen sammenhengen mellom name (på en state eller entryPoint) og (kind, level) lookupKind(name): Gir kind (dvs simple, composite eller entryPoint) for name. lookupLevel(name): Gir nivå for state eller entryPoint med navnet name. Besvar dette spørsmålet ved å bruke vedlegget side 9.

State

Off

On

GreenRed

onOff

onOffshift

shift

Page 48: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

11

Svar 3 Grammar Rule Semantic Rule

statemachine → state state.level=0

state → state name insert(name.name, simple, state.level)

state → state name {events states transitions entryPoints}

insert(name.name, composite, state.level) states.level=state.level+1 transitions.level=state.level+1 entryPoints.level=state.level+1

states1 → states2, state

states2.level=states1.level state.level=states1.level

states → state state.level=states.level

transitions1 → transitions2, transition

transitions2.level= transitions1.level transition.level= transitions1.level

transitions → transition

transition.level= transitions.level

transition → on eventId from endPoint1 to endPoint2

if lookupKind(endPoint2.name)= composite then notOK else if lookupKind(endPoint1.name)= simple and lookupKind(endPoint2.name)= simple then if lookupLevel(endPoint1.name)= lookupLevel(endPoint2.name) then OK else if (lookupKind(endPoint1.name)= simple or composite) and lookupKind(endPoint2.name)= entryPoint then if lookupLevel(endPoint1.name)= lookupLevel(endPoint2.name)-1 then OK else if lookupKind(endPoint1.name)= entryPoint and lookupKind(endPoint2.name)= simple then if lookupLevel(endPoint2.name)= transition.level then OK else notOK

entryPoints1 → entryPoints2, entryPoint

entryPoints2.level= entryPoints1.level entryPoint.level= entryPoints1.level

entryPoints → entryPoint

entryPoint.level= entryPoints.level

entryPoint → entry name1 on name2

insert(name1.name, entryPoint, entryPoint.level)

endPoint → name endPoint.name = name.name

Page 49: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

12

Oppgave 4 (25%) 4a Vi deler opp en metode i et program i basale blokker, og tegner opp flytgrafen for metoden. Til slutt finner vi (f.eks. med den gjennomgåtte iterasjons-metoden) hvilke variable som er i live (”live”) foran og bak hver basal blokk (altså inLive og outLive for hver blokk). Svar så på spørsmålene:

(1) Hvordan kan du nå finne TA-instruksjoner (om noen) som helt sikkert ikke vil ha noen betydning for utførelsen av programmet?

(2) Hvordan kan vi se om det er variable (og eventuelt hvilke) som kan bli brukt (avlest) før de har blitt gitt en verdi i programmet?

Svar 4a (1) Se på en TA-instruksjon i en blokk B som er tilordning til en variabel v. Denne kan fjernes

dersom (a) det ikke er noe bruk av v senere i blokka B, og (b) v ikke forekommer i outLive(B)

(2) Om det er variable i inLive(B0), der B0 er startblokka, så vil disse variablene (for en alle annen utførelse av programmet) kunne bli brukt før de får verdi.

4b Vi ser på følgende flytgraf:

Knut mener at det i denne flytgrafen er følgende løkker (slik løkker defineres i forbindelse med kodegenerering): B1, B2, B4, B5 B1, B3, B4, B5 B1, B2, B3, B4, B5 Astrid er ikke enig. Hvem har rett? Forklar! Om Astrid har rett, angi de riktige løkkene i flyt-grafen over.

B0

B1

B3 B5

B4

B2

Page 50: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

13

Svar 4b Det er Astrid som har rett. Hverken {B1, B2, B4, B5} eller {B1, B3, B4, B5} er løkker i bokas forstand, siden man kan komme utenfra og inn i dem til to forskjellige blokker, nemlig slik: Man kan komme utenfra og inn i {B1, B2, B4, B5} til B1 (fra B0) og til B5 (fra B3) Man kan komme utenfra og inn i {B1, B3, B4, B5} til B1 (fra B0) og til B5 (fra B2). Dessuten har Knut ikke fått med seg at blokken B3 alene utgjør en løkke. De riktige løkkene er altså: B1, B2, B3, B4, B5 B3

4c I blokk B2 i flytgrafen i 4.b står TA-instruksjonene … k = j + x k = k* k … Vi lurer på om denne beregningen kan flyttes ut av den minste løkka L som B2 er med i (for å spare eksekveringstid).

(1) Hva må du da sjekke i de forskjellige basale blokkene før du eventuelt kan gjøre en slik flytting, og i nøyaktig hvilke blokker må slik sjekk gjøres?

Konkret vil en slik flytting innebære at vi legger til følgende et sted utenfor løkka L: k’ = j + x k’ er en ny variabel k’ = k’* k’ Dessuten erstatter vi den første sekvensen (i B2) med k = k’.

(2) Hvor, utenfor løkka L, er det rimelig å legge den TA-sekvensen over som gir verdi til k’? Svar 4c (1) Man må sjekke at k, j og x ikke får en ny verdi noen steder i den minste omsluttende

løkka L, og det er altså i: {B1, B2, B3, B4, B5}.

(2) Man må legge disse TA-instruksjonene i en ny ”kunstig” basal blokk som har etterfølger B1, og som har som forgjengere alle blokker utenfor løkka L som har (eller hadde) B1 som etterfølger. Dette gir her en ny blokk mellom B0 og B1. Merk at kanten fra B5 til B1 ikke skal ”gå innom” denne blokka, siden B5 er med i løkka.

Page 51: UNIVERSITETET I OSLO · f) Lag parseringstabellen for G2 ut fra den typen grammatikk den er. g) Vis hvordan setningen: ”- - 9” vil bli parsert ved å skrive opp, som i boka, stakk-innholdet

14

4d Vi vil bruke den kodegenererings-metoden (inklusive metoden getreg) som står i notatet tatt fra kap. 9. i ASU-boken (og i foilene) til å generere maskinkode (av samme type som i notatet) for følgende basale blokk av TA-instruksjoner: e = a – b f = a – c d = f – e Her er alle variable vanlige programvariable, og de antas alle å være i live etter blokka. Til forskjell fra i notatet skal vi nå anta at maskinen bare har ett register R0. Du kan anta at analysen som gir informasjon om next-use etc. for den aktuelle blokka er utført før kodegenereringen starter. Hva blir den genererte sekvensen av maskin-instruksjoner? Vis hvilke maskin-instruksjoner som stammer fra hvilken TA-instruksjon. Du behøver ikke angi de formelle deskriptorene, men du skal skrive noen kommentarer med tilsvarende innhold til høyre for programmet. Svar 4c Dette blir litt fiklete kode, fordi det bare er ett register. Vi får: e = a – b MOV a R0 SUB b R0 // Som i notatet, med e nå i R0. Nå er alle registre opptatt f = a – c MOV R0 e // f har en neste-bruk. Frigjør det eneste registeret som finnes MOV a R0 SUB c R0 // f er nå i R0 d = f – e MOV R0 f // f er i live etter blokken og må derfor saves. SUB e R0 // f er allerede i riktig posisjon for operasjonen, altså i R0. // Etterpå er d i R0 Avslutning MOV R0 d //Alle de andre er i sine ”hjemmeposisjoner”