Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Ordinarie tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

tisdag 18 mars 2003 kl 14:00 - 19:00








Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 48.
För betyget 3 krävs 24 poäng.
För betyget 4 krävs 32 poäng.
För betyget 5 krävs 40 poäng.
Resultat och lösningar: Meddelas på kursens hemsida senast tisdag 1 april 2003.
Visning: Onsdag 2 april 2003 kl 12:00-13:00 i T2220.
Därefter kan tentor hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!


Uppgift 1: Kontextfri grammatik (5 p)

Skriv en grammatik för sökfraser i en sökmotor på webben. En sökfras består av ett eller flera sökord, som kan bindas ihop med de binära operatorerna and och or, och med den unära operatorn not, och som dessutom kan grupperas med parenteser. Not har högst prioritet, och and har högre prioritet än or.

Exempel på sökfraser:

Grammatiken ska klara det angivna språket, och operatorernas prioritet ska bli rätt. Detta ska göras med hjälp av själva grammatiken, och inte med %prec-konstruktionen från Yacc. Såväl and som or är kommutativa, så deras associativitet är godtycklig.

Uppgift 2: Top-down-parsning (15 p)

I följande grammatik är S, X och Y icketerminaler. a, b, c och d är terminaler. S är startsymbol.
S -> a X | a Y
X -> X b | b
Y -> c Y | d

a) Ange tio olika strängar som ingår i det språk som beskrivs av grammatiken ovan.

b) Grammatiken lämpar sig inte för implementation av en prediktiv recursive-descent-parser (engelska: predictive recursive-descent parser). Ange vilka problem det är, vad i grammatiken som orsakar problemen, och vad som händer i parsern.

c) Använd de transformationer som tagits upp i kursen för att omvandla grammatiken till en grammatik som beskriver samma språk, men som enkelt kan implementeras i en prediktiv recursive-descent-parser. Ange de generella transformationsregler som du använder, och visa vad resultatet blir för den här grammatiken.

d) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 3: Lexikalisk analys (3 p)

Grammatiken i uppgift 2 kan, visar det sig, även beskrivas med ett reguljärt uttryck (engelska: regular expression).

a) Ange det uttrycket.

b) Ange en grammatik som inte kan ersättas med ett reguljärt uttryck, och förklara varför det inte går!

Uppgift 4: Mellankodsgenerering (9 p)

while (i < x + y) {
  if (x > 0) {
    y = y - 1;
  }
  else {
    a = b * c + d * e;
    d = e;
    f = h - i - j;
  }
}
Översätt ovanstående programavsnitt till

a) ett abstrakt syntaxträd

b) postfixnotation

c) treadresskod

Uppgift 5: Syntaxstyrd översättning (5 p)

Ge en grammatikregel för en while-sats i ett högnivåspråk.

Skapa ett syntaxstyrt översättningsschema, med produktioner och semantiska aktioner, för översättning av while-satsen till stackmaskinkod. Antag att översättningsschemat ska implementeras i bottom-up-parsningmiljö med en stack, som i Yacc och Bison. Utgå från din grammatikregel ovan, som dock kanske måste modifieras. Förklara införda attribut och eventuella funktioner och instruktioner som används. Ange alla dina antaganden.

Uppgift 6: Typkontroll (7 p)

Ett enkelt programmeringsspråk innehåller två datatyper: tal och strängar. Man kan deklarera variabler, och man kan addera två värden av samma typ.

Exempel:

variable s : string;
variable i : number;

i = 17;
i + i;		// Resultat: talet 34
i + 3;		// Resultat: talet 20

s = "foo";
s + s;		// Resultat: strängen "foofoo"
s + "hej";	// Resultat: strängen "foohej"

s = 17;		// typfel: s ska innehålla en sträng
s = i + 47;	// typfel: s ska innehålla en sträng
"foo" + 17;	// typfel: sträng + tal ej tillåtet
s + i;		// typfel: sträng + tal ej tillåtet
s + 47;		// typfel: sträng + tal ej tillåtet
Här är en grammatik för språket:
P -> Ds Ss
Ds -> Ds D | empty
Ss -> Ss S | empty
D -> "variable" id ":" T ";"
T -> "string" | "number"
S -> E ";" | id "=" E ";"
E -> id | string-constant | number-constant | E "+" E
Visa hur kompilatorn kan hantera typinformation, i en syntaxstyrd översättning och i symboltabellen, så att den upptäcker typfelen i exemplet ovan.

Uppgift 7: Aktiveringsposter (4 p)

Vad är en aktiveringspost?
Vad används den till?
Hur kan den se ut?
Var i minnet placeras den?


Kompilatorer och interpretatorer: Tentamen 2003-06-05 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Omtentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

torsdag 5 juni 2003 kl 14:00 - 19:00








Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 68.
För betyget 3 krävs 34 poäng.
För betyget 4 krävs 45 poäng.
För betyget 5 krävs 57 poäng.
Resultat: Meddelas på kursens hemsida senast torsdag 12 juni 2003.
Visning och frågestund: Torsdag 12 juni 2003 kl 12:00-13:00 i T2220.
Därefter kan tentorna hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!


Uppgift 1: Faser (6 p)

En kompilators arbete brukar delas in i sex faser. Ange vilka det är, och förklara kort vad varje fas gör. Vad är in- och utdata från respektive fas?

Uppgift 2: Kontextfri grammatik (10 p)

Skriv en grammatik för enkla beräkningar på mängder av heltal. Den ska kunna hantera mängdliteraler, variabler, och de tre operatorerna snitt (skrivs som intersection), union (skrivs som union) och differens (skrivs som -). Operatorerna union och differens har samma prioritet. Snitt har högst prioritet. Alla operatorerna är vänsterassociativa. Uttryck ska kunna grupperas med parenteser.

Exempel på uttryck som grammatiken ska klara:

Exempel på otillåtna uttryck: Grammatiken ska klara det angivna språket, och operatorernas prioritet och associativitet ska bli rätt. Detta ska göras med hjälp av själva grammatiken, och inte med specialkonstruktioner från Yacc. Det är inget krav att grammatiken ska lämpa sig för någon viss typ av parsning.

Följande terminaler kan användas i grammatikreglerna: integer, comma, left_bracket, right_bracket, identifier, intersection, union, minus, left_parenthesis, right_parenthesis.

Uppgift 3: Top-down-parsning (17 p)

I följande grammatik är S, X, Y och Z icketerminaler. a till f är terminaler. S är startsymbol.
S -> a X | a Y
X -> X b | c Z
Y -> a | d
Z -> e Z | f

a) Rita upp parse-trädet för strängen aceeef.

b) Ange tio andra strängar som ingår i det språk som beskrivs av grammatiken ovan.

c) Grammatiken lämpar sig inte för implementation av en prediktiv recursive-descent-parser (engelska: predictive recursive-descent parser). Ange vilka problem det är, vad i grammatiken som orsakar problemen, och vad som händer i parsern.

d) Använd de transformationer som tagits upp i kursen för att omvandla grammatiken till en grammatik som beskriver samma språk, men som enkelt kan implementeras i en prediktiv recursive-descent-parser. Ange de generella transformationsregler som du använder, och visa vad resultatet blir för den här grammatiken.

e) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 4: Tvetydighet (5 p)

a) Ge exempel på en tvetydig grammatik, dvs en som kan ge upphov till flera olika parse-träd för samma tokensekvens.

b) När är tvetydighet ett problem i en grammatik? När är det det inte? Visa med exempel!

Uppgift 5: Mellankodsgenerering (9 p)

x = 0;
while (x < 10) {
  y = y + 2;
  while (y < 3 + 2 * x) {
    z = z + x + y;
    y = y + 1;
  }
  x = x + 1;
}
Översätt ovanstående programavsnitt till

a) ett abstrakt syntaxträd (rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Uppgift 6: Syntaxstyrd översättning (5 p)

Ge en grammatikregel för en if-sats i ett högnivåspråk.

Skapa ett syntaxstyrt översättningsschema, med produktioner och semantiska aktioner, för översättning av if-satsen till stackmaskinkod. Antag att översättningsschemat ska implementeras i bottom-up-parsningmiljö med en stack, som i Yacc och Bison. Utgå från din grammatikregel ovan, som dock kanske måste modifieras. Förklara införda attribut och eventuella funktioner och instruktioner som används. Ange alla dina antaganden.

Uppgift 7: Optimering (8 p)

a) Vad är ett basic block?

b) Flera olika typer av optimeringar kan göras på koden inuti ett enskilt basic block. Vilka? Beskriv dem, och använd treadresskod för att ge exempel på hur de fungerar.

c) Ofta vill man felsöka program med en symbolisk debugger, som till exempel kan stega fram programmet en rad i taget och visa innehållet i variabler. Vilka problem kan det innebära att felsöka ett optimerat program i en symbolisk debugger? Förklara hur de problemen uppstår.

Uppgift 8: Skräpsamling (5 p)

Förklara hur skräpsamlingsmetoden mark and sweep fungerar. Visa med exempel.

Uppgift 9: Lexikalisk analys (3 p)

Skriv ett reguljärt uttryck (engelska: regular expression) som matchar ett amerikanskt personnamn. Sådana namn består av ett förnamn, en initial med en punkt, och ett efternamn, till exempel George W. Bush, Richard M. Nixon och John F. Kennedy. Andra tillåtna namn är Foo B. Fum, Zwz X. Wnnnn och A B. C. Exempel på namn som inte ska tillåtas är a b. c och Bill Clinton.


Kompilatorer och interpretatorer: Tentamen 2004-03-16 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Ordinarie tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

tisdag 16 mars 2004 kl 08:00 - 13:00 i L0001








Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 70.
För betyget 3 krävs 35 poäng.
För betyget 4 krävs 46 poäng.
För betyget 5 krävs 58 poäng.
Resultat: Meddelas på kursens hemsida senast tisdag 30 mars 2004.
Visning och frågestund: Tisdag 30 mars 2004 kl 12:00-13:30 i T2220.
Därefter kan tentorna hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!

Uppgift 1: Faser (7 p)

En kompilators arbete brukar delas in i sex faser.

a) Ange vilka det är, och förklara kort vad varje fas gör. Vad har varje fas för in- och utdata?

b) En viktig del av en kompilator är felhantering. Kompilatorn ska upptäcka, och rapportera, de fel som smugit sig in i källprogrammet. Vilka typer av fel kan upptäckas, och i vilken fas upptäcks varje typ av fel?

Uppgift 2: Kontextfri grammatik (10 p)

Skriv en grammatik för aritmetiska och trigonometriska beräkningar på reella tal. Förutom de fyra räknesätten (addition, subtraktion, multiplikation och division), som skrivs med de vanliga symbolerna, ska språket innehålla de trigonometriska funktionerna sinus (sin) och cosinus (cos). Man ska kunna använda parenteser för att ändra beräkningsordningen.

Exempel på uttryck som grammatiken ska klara:

Exempel på otillåtna uttryck: Grammatiken ska klara det angivna språket, och operatorernas prioritet och associativitet ska bli rätt. Detta ska göras med hjälp av själva grammatiken, och inte med specialkonstruktioner från Yacc. Det är inget krav att grammatiken ska lämpa sig för någon viss typ av parsning.

Följande terminaler kan användas i grammatikreglerna: +, -, *, /, (, ), sin, cos och number. En terminal av typen number är ett reellt tal.

Uppgift 3: Top-down-parsning (16 p)

I följande grammatik är S, X, Y och Z icketerminaler. a, b och c är terminaler. S är startsymbol.
S -> a X
X -> Y | Z
Y -> b Y b | a
Z -> Z c | c

a) Rita upp parse-trädet för strängen acc.

b) Rita upp parse-trädet för strängen abbbabbb.

c) Det finns minst ett problem med grammatiken som gör att den inte lämpar sig för implementation av en prediktiv recursive-descent-parser (engelska: predictive recursive-descent parser). Ange vilket eller vilka problem det är, vad i grammatiken som orsakar problemen, och vad som händer i parsern.

d) Använd de transformationer som tagits upp i kursen för att omvandla grammatiken till en grammatik som beskriver samma språk, men som enkelt kan implementeras i en prediktiv recursive-descent-parser. Ange de generella transformationsregler som du använder, och visa vad resultatet blir för den här grammatiken.

e) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 4: Lexikalisk analys (4 p)

Går grammatiken i uppgiften ovan att beskriva med ett reguljärt uttryck (engelska: regular expression)?

Om du svarar ja: Ange det reguljära uttrycket.
Om nej: Förklara varför det inte går.

Uppgift 5: Tvetydighet (5 p)

a) Vad innebär det att en grammatik är tvetydig?

b) Ge exempel på en tvetydig grammatik.

c) När är tvetydighet ett problem i en grammatik? När är det det inte? Visa med exempel!

Uppgift 6: Mellankodsgenerering (10 p)

if (x - 3 > y + z) {
  x = x - y - 1;
  y = 3 - 2 * z;
}
else {
  x = z;
}
Översätt ovanstående programavsnitt till

a) ett abstrakt syntaxträd (rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Uppgift 7: Syntaxstyrd översättning (6 p)

Det här är en grammatikregel för en for-loop i ett programmeringsspråk:

Statement -> for identifier = Expression to Expression do Statement

Statement och Expression är icke-terminaler. for, identifier, =, to och do är terminaler.

Exempel: Satsen

for i = 2 to 5 do Writeln(i)

ger utskriften

2
3
4
5

Skapa ett syntaxstyrt översättningsschema, med produktioner och semantiska aktioner, för översättning av for-satsen till treadresskod. Antag att översättningsschemat ska implementeras i bottom-up-parsningmiljö med en stack, som i Yacc och Bison. Utgå från grammatikregeln. Förklara införda attribut och eventuella funktioner och instruktioner som används. Ange alla dina antaganden.

Uppgift 8: Skräpsamling (5 p)

a) Förklara hur referensräkning (engelska: reference counting) fungerar. Visa med exempel.

b) Referensräkning har problem med en viss sorts datastrukturer. Förklara med ett exempel.

Uppgift 9: Några termer (7 p)

Förklara kort vad följande begrepp från kompilatortekniken innebär:


Kompilatorer och interpretatorer: Tentamen 2004-10-18 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

måndag 18 oktober 2004 kl 8:00 - 13:00 i L0001








Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 54.
För betyget 3 krävs 27 poäng.
För betyget 4 krävs 36 poäng.
För betyget 5 krävs 45 poäng.
Resultat: Meddelas på kursens hemsida senast måndag 8 november 2004.
Visning och frågestund: Meddelas senare.
Därefter kan tentorna hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!

Uppgift 1: Kontextfri grammatik (6 p)

En robot ska styras med enkla kommandon som talar om vart roboten ska åka. Målet anges med en x- och en y-koordinat separerade med ett komma. Man kan också ange flera olika mål, separerade med semikolon, för att få roboten att åka mellan flera olika punkter.

Skriv en grammatik för kommandospråket. Grammatiken ska hantera ett enda kommando, med ett eller flera mål. Det är inget krav att grammatiken ska lämpa sig för någon viss typ av parsning, men den ska vara entydig.

Exempel på kommandon som grammatiken ska klara:

Exempel på otillåtna kommandon:

Uppgift 2: Parse-träd (3 p)

Rita upp parse-träden för följande två kommandon:

Uppgift 3: Top-down-parsning (13 p)

Skriv en prediktiv recursive-descent-parser för grammatiken i uppgift 1. Använd ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Om den grammatik du gjorde i uppgift 1 inte lämpar sig för implementation av en prediktiv recursive-descent-parser, så gör först om den till en grammatik som beskriver samma språk, men som enkelt kan implementeras i en prediktiv recursive-descent-parser. Beskriv vad du gör, och varför.

Uppgift 4: Lexikalisk analys (3 p)

Går kommandospråket i uppgift 1 att beskriva med ett reguljärt uttryck (engelska: regular expression)?

Om du svarar ja: Ange det reguljära uttrycket.
Om nej: Förklara varför det inte går.

Uppgift 5: Mellankodsgenerering (10 p)

i = 1;
j = 0;
while (i > j) {
  if (i < 10)
    i = i + 1;
  else
    j = 10 - i - j;
}
Översätt ovanstående programavsnitt till

a) ett abstrakt syntaxträd (rita upp trädet!)
b) postfixkod för en stackmaskin
c) treadresskod

Uppgift 6: Semantik (3 p)

Om vi antar en normal semantik för språket som ska översättas i uppgiften ovan, så kommer loopen som ges som exempel inte att terminera, utan programmet kommer att fortsätta i oändlighet. Vilken inverkan har det på syntaxträdet i deluppgift a? Motivera svaret!

Uppgift 7: Kontextfri grammatik, igen (6 p)

Skriv en grammatikregel för switch-satsen i C. Den behöver inte stämma exakt med hur switch-satsen verkligen definieras i den riktiga C-grammatiken, för det är för hemskt, men den ska kunna hantera switch-satser som den här:
switch (i - j - k) {
  case 1: i = i + 2; break;
  case 2: i = i + 3; break;
  case 3: i = 19; break;
  case k + 7: i = 19; break;
  default: i = 19; break;
}
När du skriver regeln kan du anta att icke-terminalerna Statement och Expression finns, och terminalerna switch, case, break, default, (, ), {, }, : och ;.

Du kan använda dig av den här regeln för en case-gren:

Branch -> case Expression : Statement break ;

Uppgift 8: Exekvering av syntaxträd (10 p)

Vi tänker oss att switch-satsen i föregående uppgift översätts till ett syntaxträd med hjälp av ett syntaxstyrt översättningsschema. För switch-satsen i exemplet ser syntaxträdet ut så här:

Ett syntaxträd för switch-satsen i exemplet

Använd ett språk som åtminstone liknar C, Java eller Pascal, och skriv funktionen execute_switch, som exekverar switch-satsen. Den ska ta en pekare till en trädnod som argument.

Det finns redan en funktion, execute, som tar en pekare till en trädnod som argument. Den kan användas för att beräkna uttryck och utföra satser (utom, tyvärr, just switch-satsen).

Trädnoderna är av typen TreeNode. Du kan anta att trädnoderna har ett typfält som heter type, och som bland annat kan ha värdena SWITCH, CASE och DEFAULT. Noderna har pekare till de underliggande subträden i en array som heter args. Om pekaren p pekar på en trädnod, kan man nå det vänstra subträdet under den noden med uttrycket p->args[0].


Kompilatorer och interpretatorer: Tentamen 2005-10-17 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Ordinarie tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

måndag 17 oktober 2005 kl 08:00 - 13:00 i L0001








Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 60.
För betyget 3 krävs 30 poäng.
För betyget 4 krävs 40 poäng.
För betyget 5 krävs 50 poäng.
Resultat: Meddelas på kursens hemsida senast måndag 7 november 2005.
Visning och frågestund: Måndag 7 november 2005 kl 12:00-12:30 i T2220.
Därefter kan tentorna hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!

Uppgift 1: Faser (6 p)

Välj ett programmeringsspråk som du är van vid, till exempel C, C++ eller Java, och ge konkreta (dvs med utdrag ur programkoden) exempel på fel i ett källprogram som kan upptäckas i:

a) den lexikaliska analysen ("scannern")

b) den syntaktiska analysen ("parsern")

c) den semantiska analysen

Uppgift 2: Grammatiker och parse-träd (12 p)

I följande grammatik är S, X, Y och Z icketerminaler. a, b, c och d är terminaler. S är startsymbol.
S -> X Y Z
X -> a | b
Y -> Z | c
Z -> d

a) (2p) Rita upp parse-trädet för strängen bdd.

b) (3p) Vilka strängar, förutom bdd, kan genereras av denna grammatik?

c) (1p) Vad innebär det att en grammatik är tvetydig (engelska: "ambiguous")?

d) (2p) Är grammatiken ovan tvetydig? Motivera svaret!

e) (2p) Just den här grammatiken definierar ett språk som också kan beskrivas med ett reguljärt uttryck. Skriv ett reguljärt uttryck som beskriver språket!

f) (2p) Skulle man kunna beskriva samma språk med ett annat reguljärt uttryck?
Om ja: Ange ett sådant alternativt reguljärt uttryck.
Om nej: Förklara varför man inte kan det.

Uppgift 3: Grammatiktransformationer (8 p)

a) (1p) Vad innebär vänsterrekursion?

b) (2p) Visa med ett exempel hur man kan eliminera, dvs ta bort, vänsterrekursion från en grammatik.

c) (1p) Hur påverkas det språk som grammatiken beskriver av att man tar bort vänsterrekursionen från den grammatiken?

d) (2p) I vilka sammanhang behöver man ta bort vänsterrekursion? Varför behöver man göra det?

e) (2p) Man kan ha semantiska aktioner instoppade i grammatiken. Förklara, med exempel, hur man hanterar dessa vid eliminering av vänsterrekursion.

Uppgift 4: Parsning (10 p)

Vi har terminalerna a, b, c och d.

Det reguljära uttrycket a*b[cd] beskriver ett språk som består av strängar som:

a) (3p) Skriv en kontextfri grammatik som beskriver samma språk som det reguljära uttrycket ovan. Startsymbolen ska vara S. Grammatiken ska lämpa sig för implementation av en prediktiv recursive-descent-parser (engelska: predictive recursive-descent parser).

b) (7p) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 5: Mellankodsgenerering (10 p)

  if (x < 7 + y) {
    x = 9 - x - y;
  }
  else {
    while (x > 10) {
      z = x + 1;
      x = 2 * x * (y - 1);
    }
  }
Översätt ovanstående programavsnitt till

a) (3p) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) (3p) postfixkod för en stackmaskin

c) (4p) treadresskod

Uppgift 6: Aktiveringsposter (4 p)

Vad är en aktiveringspost?
Vad används den till?
Vad innehåller den?
Var i minnet brukar den placeras?

Uppgift 7: Typkontroll (10 p)

Ett enkelt programmeringsspråk innehåller tre datatyper: heltal, flyttal och strängar. Man kan deklarera variabler, och man kan addera två heltal eller två flyttal, men inte två strängar.

Ett exempel, där vi först deklarerar de tre variablerna f, i och s:

f : flyttal;
i : heltal;
s : sträng;

i = 17;
i + i;		// Resultat: heltalet 34
i + 3;		// Resultat: heltalet 20
2 + 5;		// Resultat: heltalet 7
14;		// Resultat: heltalet 14

f = 3.14;
f + f;		// Resultat: flyttalet 6.28
2.1 + f;	// Resultat: flyttalet 5.24

f = 17;		// typfel: f ska innehålla ett flyttal
f = "hej";	// typfel: f ska innehålla ett flyttal
3.5 + 12;	// typfel: flyttal + heltal ej tillåtet
i + 0.5;	// typfel: heltal + flyttal ej tillåtet
"hej" + "hopp"  // typfel: sträng + sträng ej tillåtet
Här är en grammatik för språket:
S -> Deklarationslista Satslista
Deklarationslista -> Deklarationslista Deklaration | empty
Satslista -> Satslista Sats | empty
Deklaration -> id ":" Typ ";"
Typ -> "flyttal" | "heltal" | "sträng"
Sats -> Uttryck ";" | id "=" Uttryck ";"
Uttryck -> Konstant | id | Uttryck "+" Uttryck
Konstant -> heltalskonstant | flytalskonstant | strängkonstant
Visa hur kompilatorn kan hantera typinformation, i en syntaxstyrd översättning och i symboltabellen, så att den upptäcker typfelen i exemplet ovan.


Kompilatorer och interpretatorer: Tentamen 2006-01-09 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

måndag 9 januari 2006 kl 08:00 - 13:00 i L0003








Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 58.
För betyget 3 krävs 29 poäng.
För betyget 4 krävs 40 poäng.
För betyget 5 krävs 50 poäng.
Resultat: Meddelas på kursens hemsida senast måndag 30 januari 2006.
Visning och frågestund: Onsdag 1 februari 2006 kl 12:00-12:30 i mitt rum (T2220)
Därefter kan tentorna hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!

Uppgift 1: Faser (3 p)

När följande C-program kompileras med en viss kompilator, får man de fem fel- och varningsmeddelanden som står med kursiv stil i högerspalten.

#include <stdio.h>

int main(void) {
  int i = 17;
  float f = 3.14;
  char c = 'x';
  char* s = "foo;         (1) missing terminating " character

  s = f;                  (2) error: incompatible types in assignment
  printf("f = %f\n", i);  (3) warning: double format, different type arg (arg 2)

  c s;                    (4) error: syntax error before "s"
  return;                 (5) warning: `return' with no value, in function returning non-void
}

Ange för vart och ett av de fem meddelandena i vilken fas i kompilatorn det felet upptäcktes!

Uppgift 2: Grammatiker och parse-träd (11 p)

I följande grammatik är S, A och B icketerminaler. x, y, z och t är terminaler. S är startsymbol.
S -> A | B | x
A -> x | y
B -> B z | t

a) (2p) Rita upp parse-trädet för strängen tzz.

b) (4p) Vilka strängar, förutom tzz, kan genereras av denna grammatik?

c) (1p) Vad innebär det att en grammatik är tvetydig (engelska: "ambiguous")?

d) (2p) Är grammatiken ovan tvetydig? Motivera svaret!

e) (2p) Just den här grammatiken definierar ett språk som också kan beskrivas med ett reguljärt uttryck. Skriv ett reguljärt uttryck som beskriver språket!

Uppgift 3: Språk, grammatiker och parsning (19 p)

Det finns ett spel som går ut på att man ger kommandon till en robot, som rör sig på en spelplan. Man kan beordra roboten att springa till en punkt på spelplanen, eller att hoppa till en punkt. Man kan också beordra den att antingen springa eller hoppa tillbaka till den föregående punkt där den befann sig. Dessutom finns ett startkommando för att starta roboten, och ett stopp-kommando för att stänga av den. Punkter anges med en x- och en y-koordinat, i form av heltal, och roboten startar i origo, dvs punkten med x=0 och y=0.

Som exempel kan följande sekvens av kommandon ge upphov till rörelserna i figuren nedan.

start;
spring till 5, 3;
spring till 9, 3;
hoppa tillbaka;
spring till 4, 6;
hoppa till 1, 6;
spring tillbaka;
spring till 10, 8;
stopp;

Ett diagram över rörelserna

a) (3p) Ange vilka terminaler, dvs typer av tokens, som behövs för att man ska kunna skriva en grammatik för kommandospråket.

b) (5p) Skriv grammatiken. Använd terminalerna från a-uppgiften. Startsymbolen ska heta S.

c) (3p) Om grammatiken från b-uppgiften inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, så transformera den så den passar. (Om den redan är lämplig, behöver du inte göra om den, utan du får 3 poäng på den här deluppgiften i alla fall.)

d) (8p) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 4: Run-time-omgivning, aktiveringsposter (7 p)

Betrakta följande C-program:

#include <stdlib.h>

int a;
int b;

void f(int c, int d) {
  int e;
  int* p = malloc(sizeof(int));
  e = 13;
  *p = 14;
  // Här!
}

void g(int h) {
  int i;
  int* p = malloc(sizeof(int));
  i = 15;
  *p = 16;
  f(h, 17);
}

int main(void) {
  int k;
  k = 18;
  a = 19;
  b = 20;
  g(k);
  return 0;
}

Funktionen main anropar funktionen g, som i sin tur anropar funktionen f. När programexekveringen i funktionen f kommer fram till raden med kommentaren "Här!", så antar vi att vi stoppar programmet och tittar på vilka olika variabler som finns i minnet.

I minnet kommer det då att finnas ett antal lagringsutrymmen för heltal, som innehåller talen 13-20. Rita upp en skiss över dessa variabler, och förklara vad som är vad. Din förklaring bör bland annat innehålla termerna "statiska data", "stack", "heap", "aktiveringspost" och "parametrar".

Uppgift 5: Mellankodsgenerering (12 p)

if (a + b > c) {
  d = 14;
  while (d < e - f - g) {
    d = d - 1;
  }
}
else {
  a = x + 2 * y - z + t;
  b = x + 3;
  c = x;
  d = 14;
}
Översätt ovanstående programavsnitt till

a) ett abstrakt syntaxträd (rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Uppgift 6: Skräpsamling (6 p)

a) Förklara hur referensräkning (engelska: reference counting) fungerar. Visa med exempel.

b) Referensräkning har problem med en viss sorts datastrukturer. Förklara med ett exempel.

c) Hur kan man lösa det problemet?


Kompilatorer och interpretatorer: Tentamen 2006-10-16 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)
Med vissa rättelser.







Ordinarie tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

måndag 16 oktober 2006 kl 08:00 - 13:00 i L001








Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 40.
För betyget 3 krävs 20 poäng.
För betyget 4 krävs 27 poäng.
För betyget 5 krävs 34 poäng.
Resultat: Meddelas på kursens hemsida senast måndag 6 november 2006.
Visning och frågestund: Måndag 13 november 2006 kl 12:00-12:30 i T2220.
Därefter kan tentorna hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!

Observera: Det finns nio uppgifter på tentan. Välj ut och besvara (högst) åtta av dessa. (Skulle du svara på alla nio, räknas den med högst poäng bort.)

Uppgift 1: Grammatiker (5p)

Ett språk innehåller terminalerna god, morgon, middag och kväll. Grammatiken för språket innehåller icke-terminalerna hälsning och tidsspecifikation, och följande produktioner:
hälsning -> god tidsspecifikation
tidsspecifikation -> morgon
tidsspecifikation -> middag
tidsspecifikation -> kväll
tidsspecifikation -> god
Startsymbolen är hälsning.

(a) (2p)

Ange vilket språk grammatiken beskriver, genom att räkna upp alla strängar (dvs sekvenser av terminaler) som kan uttryckas i språket.

Visa hur du fick fram svaret.

(b) (2p)

I ett annat språk ska man kunna skriva godtyckligt många hälsningar (som beskrivs av hälsning i grammatiken för det förra språket) efter varandra, åtskilda med semikolon. Med "godtyckligt många" menas noll, en eller flera.

Skriv en grammatik för detta språk. Glöm inte att ange vad som är startsymbol. Grammatiken ska vara entydig.

(c) (1p)

I deluppgiften ovan stod det att grammatiken skulle vara entydig. Det är motsatsen till att grammatiken är tvetydig. Förklara med exempel vad som menas med att en grammatik är entydig respektive tvetydig.

Uppgift 2: Kompilatorer (5 p)

En kompilator brukar byggas upp genom att delas in i sex faser: Indata till den första fasen består av källprogrammet i textform (alltså en sekvens av tecken), medan utdata från den sista fasen utgörs av ett målprogram uttryckt i maskinspråk eller assemblerspråk.

Men hur ser de data som skickas mellan faserna ut? Beskriv för var och en av de fem kopplingarna mellan faserna vilka data som överförs.

Uppgift 3: Scanning och reguljära uttryck (5 p)

En förenklad version av printf tar formatsträngar som kan innehålla vanlig text, %d-specificerare (som anger heltal), %f-specificerare (som anger flyttal), och %s-specificerare (som anger strängar).

%d-specificerare kan innehålla en fältbredd, som skrivs mellan procenttecknet och d:et. En negativ fältbredd betyder att talet ska vänsterjusteras i fältet.

%f-specificerare kan innehålla en fältbredd på samma sätt som för heltal, men också en punkt följd av en precision (antal decimaler som ska skrivas ut).

%s-specificerare kan innehålla en fältbredd på samma sätt som för heltal, men också en punkt följd av ett största antal tecken som får skrivas ut.

Här är några exempel på tillåtna formatsträngar:

Här är några exempel på formatsträngar som inte är tillåtna: Skriv ett reguljärt uttryck som beskriver hur en formatsträng får se ut. Använd gärna utvidgade reguljära uttryck av samma typ som finns i Lex. Bygg gärna upp uttrycket steg för steg, dvs med namn som står för ett reguljärt uttryck och som sen används i nästa uttryck.

Uppgift 4: Parsning (5 p)

I följande grammatik är S, T och U icke-terminaler. a, b, c och d är terminaler. S är startsymbol.
S -> a T | b T U
T -> T U | U
U -> c d | c d d

a)

Gör eventuella transformationer av grammatiken som krävs för att den ska lämpa sig för implementation av en prediktiv recursive-descent-parser (engelska: predictive recursive-descent parser).

b)

Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 5: Syntaxstyrd översättning (5 p)

Här är en grammatikregel för for-satsen i C:

sats -> for ( uttryck1 ; uttryck2 ; uttryck3 ) sats1

Skapa ett syntaxstyrt översättningsschema, med produktioner och semantiska aktioner, för översättning av for-satsen till mellankod. Välj själv om du vill generera ett abstrakt syntaxträd, postfixkod för en stackmaskin eller treadresskod.

Tips: Dessa två loopar kan betraktas som ekvivalenta:

for (i = 0; i < 10; ++i) {
  whatever();
}

i = 0;
while (i < 10) {
  whatever();
  ++i;
}

Uppgift 6: Mellankod (5 p)

r = 0;
s = 100;
while (r < s) {
  if (s > 0)
    s = s - (s - r) / 2;
  else
    s = 0;
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 7: Optimering (5 p)

a) Vad är ett basic block?

b) Flera olika typer av optimeringar kan göras på koden inuti ett enskilt basic block. Vilka? Beskriv dem, och använd treadresskod för att ge exempel på hur de fungerar.

Uppgift 8: Aktiveringsposter (5 p)

Betrakta följande C-program:

#include <stdlib.h>

int x;

void g(int x, int y) {
  int* p;
  p = malloc(sizeof(int));
  *p = x;
  // Här!
}

void f(int y, int z) {
  int t;
  t = x;
  x = y;
  g(x, x);
}

int main(void) {
  int y;
  x = 1;
  y = 2;
  f(3, y);
}

Funktionen main anropar funktionen f, som i sin tur anropar funktionen g. När programexekveringen i funktionen g kommer fram till raden med kommentaren "Här!", så antar vi att vi stoppar programmet och tittar på vilka olika variabler som finns i minnet.

I minnet kommer det då att finnas ett antal lagringsutrymmen för heltal, som innehåller några olika värden. Rita upp en skiss över dessa variabler, och förklara vad som är vad. Din förklaring bör bland annat innehålla termerna "statiska data", "stack", "heap", "aktiveringspost" och "parametrar".

Uppgift 9: Run-time-omgivningar (5 p)

Förklara hur skräpsamlingsmetoden mark and sweep fungerar. Visa med exempel.

Vilka fördelar och nackdelar har den, jämfört med referensräkning?

Observera: Det finns nio uppgifter på tentan. Välj ut och besvara (högst) åtta av dessa. (Skulle du svara på alla nio, räknas den med högst poäng bort.)


Kompilatorer och interpretatorer: Tentamen 2006-10-16 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Ordinarie tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

måndag 16 oktober 2006 kl 08:00 - 13:00 i L001








Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 40.
För betyget 3 krävs 20 poäng.
För betyget 4 krävs 27 poäng.
För betyget 5 krävs 34 poäng.
Resultat: Meddelas på kursens hemsida senast måndag 6 november 2006.
Visning och frågestund: Måndag 13 november 2006 kl 12:00-12:30 i T2220.
Därefter kan tentorna hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!

Observera: Det finns nio uppgifter på tentan. Välj ut och besvara (högst) åtta av dessa. (Skulle du svara på alla nio, räknas den med högst poäng bort.)

Uppgift 1: Grammatiker (5p)

Ett språk innehåller terminalerna god, morgon, middag och kväll. Grammatiken för språket innehåller icke-terminalerna hälsning och tidsspecifikation, och följande produktioner:
hälsning -> god tidsspecifikation
tidsspecifikation -> morgon
tidsspecifikation -> middag
tidsspecifikation -> kväll
tidsspecifikation -> god
Startsymbolen är hälsning.

(a) (2p)

Ange vilket språk grammatiken beskriver, genom att räkna upp alla strängar (dvs sekvenser av terminaler) som kan uttryckas i språket.

Visa hur du fick fram svaret.

(b) (2p)

I ett annat språk ska man kunna skriva godtyckligt många hälsningar (som beskrivs av hälsning i grammatiken för det förra språket) efter varandra, åtskilda med semikolon. Med "godtyckligt många" menas noll, en eller flera.

Skriv en grammatik för detta språk. Glöm inte att ange vad som är startsymbol. Grammatiken ska vara entydig.

(c) (1p)

I deluppgiften ovan stod det att grammatiken skulle vara entydig. Det är motsatsen till att grammatiken är tvetydig. Förklara med exempel vad som menas med att en grammatik är entydig respektive tvetydig.

Uppgift 2: Kompilatorer (5 p)

En kompilator brukar byggas upp genom att delas in i sex faser: Indata till den första fasen består av källprogrammet i textform (alltså en sekvens av tecken), medan utdata från den sista fasen utgörs av ett målprogram uttryckt i maskinspråk eller assemblerspråk.

Men hur ser de data som skickas mellan faserna ut? Beskriv för var och en av de fem kopplingarna mellan faserna vilka data som överförs.

Uppgift 3: Scanning och reguljära uttryck (5 p)

En förenklad version av printf tar formatsträngar som kan innehålla vanlig text, %d-specificerare (som anger heltal), %f-specificerare (som anger flyttal), och %s-specificerare (som anger strängar).

%d-specificerare kan innehålla en fältbredd, som skrivs mellan procenttecknet och d:et. En negativ fältbredd betyder att talet ska vänsterjusteras i fältet.

%f-specificerare kan innehålla en fältbredd på samma sätt som för heltal, men också en punkt följd av en precision (antal decimaler som ska skrivas ut).

%s-specificerare kan innehålla en fältbredd på samma sätt som för heltal, men också en punkt följd av ett största antal tecken som får skrivas ut.

Här är några exempel på tillåtna formatsträngar:

Här är några exempel på formatsträngar som inte är tillåtna: Skriv ett reguljärt uttryck som beskriver hur en formatsträng får se ut. Använd gärna utvidgade reguljära uttryck av samma typ som finns i Lex. Bygg gärna upp uttrycket steg för steg, dvs med namn som står för ett reguljärt uttryck och som sen används i nästa uttryck.

Uppgift 4: Parsning (5 p)

I följande grammatik är S, T, U och V icke-terminaler. a, b, c och d är terminaler. S är startsymbol.
S -> a T | b T U
T -> T U | U
U -> c d | c d d

a)

Gör eventuella transformationer av grammatiken som krävs för att den ska lämpa sig för implementation av en prediktiv recursive-descent-parser (engelska: predictive recursive-descent parser).

b)

Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 5: Syntaxstyrd översättning (5 p)

Här är en grammatikregel för for-satsen i C:

sats -> for ( uttryck1 ; uttryck2 ; uttryck3 ) sats1

Skapa ett syntaxstyrt översättningsschema, med produktioner och semantiska aktioner, för översättning av for-satsen till mellankod. Välj själv om du vill generera ett abstrakt syntaxträd, postfixkod för en stackmaskin eller treadresskod.

Tips: Dessa två loopar kan betraktas som ekvivalenta:

Kom ihåg att dessa

for (i = 0; i < 10; ++i) {
  whatever();
}

i = 0;
while (i < 10) {
  whatever();
  ++i;
}

Uppgift 6: Mellankod (5 p)

r = 0;
s = 100;
while (r < s) {
  if (s > 0)
    s = s - (s - r) / 2;
  else
    s = 0;
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 7: Optimering (5 p)

a) Vad är ett basic block?

b) Flera olika typer av optimeringar kan göras på koden inuti ett enskilt basic block. Vilka? Beskriv dem, och använd treadresskod för att ge exempel på hur de fungerar.

Uppgift 8: Aktiveringsposter (5 p)

Betrakta följande C-program:

#include <stdlib.h>

int x;

void g(int x, int y) {
  int* p;
  p = malloc(sizeof(int));
  *p = x;
  // Här!
}

void f(int y, int z) {
  int t;
  t = x;
  x = y;
  g(x, x);
}

int main(void) {
  int y;
  x = 1;
  y = 2;
  f(3, y);
}

Funktionen main anropar funktionen f, som i sin tur anropar funktionen g. När programexekveringen i funktionen g kommer fram till raden med kommentaren "Här!", så antar vi att vi stoppar programmet och tittar på vilka olika variabler som finns i minnet.

I minnet kommer det då att finnas ett antal lagringsutrymmen för heltal, som innehåller några olika värden. Rita upp en skiss över dessa variabler, och förklara vad som är vad. Din förklaring bör bland annat innehålla termerna "statiska data", "stack", "heap", "aktiveringspost" och "parametrar".

Uppgift 9: Run-time-omgivningar (5 p)

Förklara hur skräpsamlingsmetoden mark and sweep fungerar. Visa med exempel.

Vilka fördelar och nackdelar har den, jämfört med referensräkning?

Observera: Det finns nio uppgifter på tentan. Välj ut och besvara (högst) åtta av dessa. (Skulle du svara på alla nio, räknas den med högst poäng bort.)


Kompilatorer och interpretatorer: Tentamen 2007-01-08 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet m fl

måndag 8 januari 2007 kl 08:00 - 13:00 i L001











Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 30.
För betyget 3 krävs 15 poäng.
Resultat: Meddelas på kursens hemsida senast måndag 29 januari 2007.
Visning och frågestund: Tisdag 30 januari 2007 kl 15:00-15:30 i T2220.
Därefter kan tentorna hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, tel: Mellankod (5 p)efon 070-7347013.




LYCKA TILL!

Uppgift 1: Grammatiker (5p)

Ett språk innehåller terminalerna a, b, c, d, e och f. Grammatiken för språket innehåller icke-terminalerna S, T och U, och följande produktioner:
S -> a T | a U
T -> b c
U -> c d
Startsymbolen är S.

(a) (2p)

Ange vilket språk grammatiken beskriver, genom att räkna upp alla strängar (dvs sekvenser av terminaler) som kan uttryckas i språket.

Visa hur du fick fram svaret.

(b) (1p)

I ett annat språk ska man kunna skriva godtyckligt många förekomster av strängen a b c. Med "godtyckligt många" menas noll, en eller flera. Exempel på strängar som ska accepteras:

Skriv en grammatik för detta språk. Glöm inte att ange vad som är startsymbol. Grammatiken ska vara entydig.

(c) (1p)

I deluppgiften ovan stod det att grammatiken skulle vara entydig. Det är motsatsen till att grammatiken är tvetydig. Förklara med exempel vad som menas med att en grammatik är entydig respektive tvetydig.

(d) (1p)

Skriv ett reguljärt uttryck som beskriver språket i deluppgift a.

Uppgift 2: Kompilatorer (5 p)

Vilka faser brukar en kompilator delas in i, och vad gör varje fas?

Uppgift 3: Parsning (5 p)

a)

Gör eventuella transformationer av grammatiken i deluppgift 1 a som krävs för att den ska lämpa sig för implementation av en prediktiv recursive-descent-parser (engelska: predictive recursive-descent parser).

b)

Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 4: Syntaxstyrd översättning (5 p)

a)

Skriv en grammatikregel för while-satsen i C.

b)

Skapa ett syntaxstyrt översättningsschema, med produktioner och semantiska aktioner, för översättning av while-satsen till mellankod. Välj själv om du vill generera ett abstrakt syntaxträd, postfixkod för en stackmaskin eller treadresskod.

Uppgift 5: Mellankod (5 p)

if (a - b - c > d + e + f) {
  g = 100;
  h = 200;
}
else {
  while (i < 20) {
    i = i + 1;
  }
  j = 300;
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 6: Run-time-omgivningar (5 p)

Antag att minnet innehåller dessa sju dataobjekt:

Några objekt som garben ska köras på

a) Antag att vi använder skräpsamlingsmetoden "mark and sweep". Vilka av objekten kommer att markeras i markeringsfasen?

b) Vilka av objekten kommer att tas bort i sopfasen?

c) Antag att vi i stället använder referensräkning. Kan situationen som visas på bilden uppstå? (Vi antar att vi inte är mitt i en uppstädning.)

d) Vi använder fortfarande referensräkning. Ange värdet på referensräknaren för vart och ett av dataobjekten.

e) Vi använder fortfarande referensräkning. Vi sätter de båda pekarna som pekar ut ur rotmängden (dvs i dataobjekt 2 och 3) till NULL. Beskriv vad som händer.


Kompilatorer och interpretatorer: Tentamen 2007-08-24 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet m fl

fredag 24 augusti 2007 kl 08:00 - 12:00 i L001

Gäller som tentamen för:
TDK104 Kompilatorer och interpretatorer, provkod 0100











Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 30.
För betyget 3 krävs 15 poäng.
Resultat: Meddelas på kursens hemsida senast måndag 10 september 2007.
Visning och frågestund: Tisdag 11 september 2007 kl 12:00-12:30 i mitt rum (T2220).
Därefter kan tentorna hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.




LYCKA TILL!

Uppgift 1: Grammatiker (5p)

Ett språk innehåller terminalerna a, b, c, d och e. Grammatiken för språket innehåller icke-terminalerna S, T och U, och följande produktioner:
S -> a T | b U
T -> b c U e
U -> c d
Startsymbolen är S.

(a) (2p)

Ange vilket språk grammatiken beskriver, genom att räkna upp alla strängar (dvs sekvenser av terminaler) som kan uttryckas i språket.

Visa hur du fick fram svaret.

(b) (1p)

I ett annat språk ska man kunna skriva godtyckligt många förekomster av strängen a a, följt av strängen bc. Med "godtyckligt många" menas noll, en eller flera. Exempel på strängar som ska accepteras:

Skriv en grammatik för detta språk. Glöm inte att ange vad som är startsymbol. Grammatiken ska vara entydig.

(c) (1p)

I deluppgiften ovan stod det att grammatiken skulle vara entydig. Det är motsatsen till att grammatiken är tvetydig. Förklara med exempel vad som menas med att en grammatik är entydig respektive tvetydig.

(d) (1p)

Skriv ett reguljärt uttryck som beskriver språket i deluppgift a.

Uppgift 2: Kompilatorer (5 p)

En av faserna som en kompilator brukar delas in i är optimering.

a) Vilka andra faser finns det, och i vilken ordning kommer de?

b) I en nyare upplaga av "drakboken" har man delat in optimeringsfasen i två olika faser: maskinoberoende optimering och maskinberoende optimering. Varför har man gjort den uppdelningen?

Uppgift 3: Parsning (5 p)

a)

Gör eventuella transformationer av grammatiken i deluppgift 1 a som krävs för att den ska lämpa sig för implementation av en prediktiv recursive-descent-parser (engelska: predictive recursive-descent parser).

b)

Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 4: Syntaxstyrd översättning (5 p)

a)

Skriv en grammatikregel för if-satsen i C.

b)

Skapa ett syntaxstyrt översättningsschema, med produktioner och semantiska aktioner, för översättning av while-satsen till mellankod. Välj själv om du vill generera ett abstrakt syntaxträd, postfixkod för en stackmaskin eller treadresskod.

Uppgift 5: Mellankod (5 p)

while (a + (b + c) < a + b + c) {
  if (i > j) {
    a = 200;
  }
  else {
    c = b * c + a * j;
    j = j + 1;
  }
  a = j + 1;
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 6: Run-time-omgivningar (5 p)

Antag att minnet innehåller dessa sju dataobjekt:

a) Antag att vi använder skräpsamlingsmetoden "mark and sweep". Vilka av objekten kommer att markeras i markeringsfasen?

b) Vilka av objekten kommer att tas bort i sopfasen?

c) Antag att vi i stället använder referensräkning. Kan situationen som visas på bilden uppstå? (Vi antar att vi inte är mitt i en uppstädning.) Motivera svaret.

d) Vi använder fortfarande referensräkning. Ange värdet på referensräknaren för vart och ett av dataobjekten.

e) Nu använder vi mark and sweep. Vi sätter de tre pekarna som pekar ut ur rotmängden från dataobjekt 1 och 2 till NULL. Beskriv vad som händer vid nästa skräpsamling.


Kompilatorer och interpretatorer: Tentamen 2007-11-06 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)





Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

tisdag 6 november 2007 kl 08:00 - 12:00

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100
TDK104 Kompilatorer och interpretatorer, provkod 0100







Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 40.
För godkänt betyg (3 respektive G) krävs 20 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast måndag 19 november 2007.
Visning och frågestund: Måndag 19 november 2007 kl 12:00-12:30 i mitt rum (T2220).
Efter visningen kan tentorna hämtas på institutionen. Man kan också få sin rättade tenta hemskickad.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!

Observera: Det finns sju uppgifter på tentan, men alla ska inte lösas. Svara på uppgift 1 och (högst) fem av de övriga sex uppgifterna. (Skulle du svara på alla sex, räknas den med högst poäng bort.)

Uppgift 1: Språk, grammatiker och parsning (15 p)

En Wumpus
Fig. 1. Wumpus.

I spelet Hunt the Wumpus går man runt mellan olika rum i en grotta och jagar ett farligt monster. I den variant som beskrivs här kan man ge kommandon för att gå mellan olika rum (kommandot ), för att skjuta på wumpusen (kommandot skjut), för att ge upp (kommandot ge upp), och för att börja om (kommandot börja om). Till skjut-kommandot anger man en lista med rum, som man skjuter mot. Man kan ge flera kommandon på en gång genom att skriva semikolon mellan dem.

Här är några exempel på kommandorader som man kan ge:

Några felaktiga kommandorader:

a) (2p) Ange vilka terminaler, dvs typer av tokens, som behövs för att man ska kunna skriva en grammatik för kommandospråket.

b) (5p) Skriv grammatiken. Använd terminalerna från a-uppgiften. Startsymbolen ska beskriva en kommandorad, som alltså kan innehålla flera kommandon.

c) (2p) Om grammatiken från b-uppgiften inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, så transformera den så den passar. (Om den redan är lämplig, behöver du inte göra om den, utan du får 2 poäng på den här deluppgiften i alla fall.)

d) (6p) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Observera: Det finns sju uppgifter på tentan, men alla ska inte lösas. Svara på uppgift 1 och (högst) fem av de övriga sex uppgifterna. (Skulle du svara på alla sex, räknas den med högst poäng bort.)

Uppgift 2: Faser (5 p)

En kompilators arbete brukar delas in i sex eller sju faser. Ange vilka det är, och förklara kort vad varje fas gör. Vad är in- och utdata från respektive fas?

Uppgift 3: Scanning och reguljära uttryck (5 p)

a) (3p) Skriv reguljära uttryck för de olika tokentyperna i uppgiften ovan.

b) (2p) Vad är det för skillnad på ett lexem och ett lexikaliskt värde, och vad har dessa med scanning att göra?

Uppgift 4: Run-time-omgivning, aktiveringsposter (5 p)

Betrakta följande C-program:

#include <stdlib.h>
#include <stdio.h>

int x = 1;
int y = 2;

void f(int a) {
    int b;
    b = x;
    a = 3;
    // Här!
}

void g(int a, int b) {
    int c;
    c = a;
    x = 4;
    int* p = malloc(sizeof(int));
    *p = b;
    f(x);
}

int main(void) {
    int x;
    x = 5;
    y = 6;
    g(7, x);
    return 0;
}

Funktionen main anropar funktionen g, som i sin tur anropar funktionen f. När programexekveringen i funktionen f kommer fram till raden med kommentaren "Här!", så antar vi att vi stoppar programmet och tittar på vilka olika variabler som finns i minnet.

I minnet kommer det då att finnas ett antal lagringsutrymmen för heltal, som innehåller olika heltalsvärden. Rita upp en skiss över dessa variabler, och förklara vad som är vad. Din förklaring bör bland annat innehålla termerna "statiska data", "stack", "heap", "aktiveringspost" och "parametrar".

Uppgift 5: Mellankod (5 p)

Det här är ett programavsnitt i C:
x = 1;
y = 2;
while (x > y) {
    if (x < a) {
        x = x − a − 2;
        y = y + a * 3;
    }
    else
        x = x − 1;
    y = y + 1;
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 6: Syntaxstyrd översättning (5 p)

Här är en grammatikregel för if-satsen i ett språk:

sats -> if ( uttryck ) then sats1 else sats2 endif

Skapa en syntaxstyrd definition, med produktioner och semantiska regler, för översättning av for-satsen till mellankod. Välj själv om du vill generera ett abstrakt syntaxträd, postfixkod för en stackmaskin eller treadresskod.

Uppgift 7: Optimering (5 p)

a) Vad är treadresskod? Visa med exempel.

b) Vad är ett basic block? Visa med exempel.

c) Flera olika typer av optimeringar kan göras på koden inuti ett enskilt basic block. Vilka? Beskriv dem, och använd treadresskod för att ge exempel på hur de fungerar.

Observera: Det finns sju uppgifter på tentan, men alla ska inte lösas. Svara på uppgift 1 och (högst) fem av de övriga sex uppgifterna. (Skulle du svara på alla sex, räknas den med högst poäng bort.)


Kompilatorer och interpretatorer: Tentamen 2007-12-08 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)





Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

lördag 8 december 2007 kl 08:00 - 12:00

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100
TDK104 Kompilatorer och interpretatorer, provkod 0100







Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 43.
För godkänt betyg (3 respektive G) krävs 21 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast lördag 29 december 2007.
Visning och frågestund: Tisdag 8 januari 2008 kl 15:00-15:30 i mitt rum (T2220).
Efter visningen kan tentorna hämtas på institutionen. Man kan också få sin rättade tenta hemskickad.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!

Uppgift 1: Språk, grammatiker och parsning (12 p)

En Wumpus
Fig. 1. Wumpus.
                  
En liten Wumpus
Fig. 2. Wumpusens son.

I spelet Son of Wumpus går man runt mellan olika rum i en grotta och jagar ett litet och ganska ofarligt monster. Eftersom monstret är så litet och ofarligt, behöver man inte se sig för så noga i grottan, utan man anger i förväg vilka rum man ska besöka, och i vilka rum man vill skjuta på monstret. (Man hoppas alltså att monstret råkar vara i något av de rummen.) Det man gör är att man skriver ett litet program, som börjar med begin och slutat med end, och som räknar upp vilka rum man ska besöka och var man vill skjuta. Ett exempel:

Programmet innebär att man i tur och ordning går till rum nummer 2, 3, 4 och 5, sen stannar man i rum nummer 5 och skjuter, och sen går man tillbaka till först rum nummer 4 och sen nummer 3.

Här är några andra exempel på program som man kan ange:

a) (1p) Ange vilka terminaler, dvs typer av tokens, som behövs för att man ska kunna skriva en grammatik för kommandospråket.

b) (4p) Skriv grammatiken. Använd terminalerna från a-uppgiften. Ange vad som är startsymbol. Startsymbolen ska beskriva ett program, enligt ovan.

c) (2p) Om grammatiken från b-uppgiften inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, så transformera den så den passar. (Om den redan är lämplig, behöver du inte göra om den, utan du får 2 poäng på den här deluppgiften i alla fall.)

d) (5p) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 2: Faser (6 p)

a) (2p) I uppgiften ovan kan man bara gå mellan rum som ligger intill varandra, så följande program är felaktiga: Bör den kontrollen ligga i kompilatorn? I så fall, i vilken fas? Motivera svaret!

b) (2p) Man kan dela upp den kodoptimering som kompilatorn gör i två olika faser: maskinoberoende respektive maskinberoende optimering. Ge ett exempel på en optimering som bäst görs i den maskinoberoende optimeringsfasen, och förklara varför den skulle vara svårare att göra i den andra, maskinberoende optimeringsfasen.

c) (2p) Ge ett exempel på en optimering som bäst görs i den maskinberoende optimeringsfasen, och förklara varför den skulle vara svårare att göra i den andra, maskinoberoende optimeringsfasen.

Uppgift 3: Mellankod (5 p)

Det här är ett programavsnitt i C:
if (x > y)
    x = y;
else
    y = x;
while (x > y − z − t) {
    x = x * y - z;
    y = x - y - z;
    z = x - y * z;
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 4: Syntaxstyrd översättning (5 p)

a) Skriv en grammatikregel för while-satsen i C.

b) Skapa ett syntaxstyrt översättningsschema, med produktioner och semantiska aktioner, för översättning av while-satsen till mellankod. Välj själv om du vill generera ett abstrakt syntaxträd, postfixkod för en stackmaskin eller treadresskod.

Uppgift 5: Typkontroll (5 p)

Ett enkelt programmeringsspråk innehåller två datatyper: heltal och flyttal. Man kan deklarera variabler, och man kan addera två värden av samma typ, men man får inte blanda tal av olika typ.

Exempel på ett program i språket:

int i;
float f;

i = 17;
i + i;		// Resultat: heltalet 34
i + 3;		// Resultat: heltalet 20

f = 7.0;
f + f;		// Resultat: flyttalet 14.0
f + 3.0;	// Resultat: flyttalet 10.0

f = 17;		// typfel: f ska innehålla ett flyttal
f = i + 47;	// typfel: f ska innehålla ett flyttal
3.0 + 17;	// typfel: flyttal + heltal ej tillåtet
f + i;		// typfel: flyttal + heltal ej tillåtet
f + 47;		// typfel: flyttal + heltal ej tillåtet
Här är en grammatik för språket:
program -> deklarationer satser
deklarationer -> deklarationer deklaration | empty
satser -> satser sats | empty
deklaration -> typ id ";"
typ -> "int" | "float"
sats -> uttryck ";" | id "=" uttryck ";"
uttryck -> id | heltalskonstant | flyttalskonstant | uttryck "+" uttryck
Visa hur kompilatorn kan hantera typinformation, i en syntaxstyrd översättning och i symboltabellen, så att den upptäcker typfelen i exemplet ovan.

Uppgift 6: Några termer (10 p)

Förklara kort vad följande begrepp från kompilatortekniken innebär. Ge gärna exempel.
  1. call by value
  2. DAG
  3. heap
  4. konservativ skräpsamling
  5. parseträd (ibland kallad "konkret syntaxträd")
  6. registerallokering
  7. reguljärt uttryck
  8. syntaxträd (ibland kallad "abstrakt syntaxträd")
  9. tvetydig grammatik
  10. Yacc


Kompilatorer och interpretatorer: Tentamen 2008-11-03 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)





Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

måndag 3 november 2008 kl 08:00 - 12:00

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100
TDK104 Kompilatorer och interpretatorer, provkod 0100







Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 40.
För godkänt betyg (3 respektive G) krävs 20 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast måndag 24 november 2008.
Visning och frågestund: Tisdag 25 november 2008 kl 15:00-15:30 i mitt rum (T2220).
Efter visningen kan tentorna hämtas på institutionen. Man kan också få sin rättade tenta hemskickad.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-73 47 013.



LYCKA TILL!

Uppgift 1: Språk, grammatiker och parsning (15 p)

I en enkel databashanterare kan man skapa tabeller med kolumner, som kan innehålla heltal och strängar. Man kan skapar och ta bort tabellerna med kommandona create table och drop table. Man kan också stoppa in data i tabellerna med kommandot insert into.

Här är några exempel på SQL-kommandon som den här databashanteraren förstår:

create table Blaha
(foo integer unique,
fum string primary key,
blaj string unique);

drop table Blaha;

create table Apa
(nummer integer,
namn string,
svampkod integer);

insert into Apa values (1, 'Hej', 17);
Databashanteraren implementerar alltså en ganska liten delmängd av det vanliga databasspråket SQL. Mer om SQL-dialekten: Här är några exempel på SQL-kommandon som databashanteraren inte förstår:
create table Apa
(nummer integer default 10 not null,
namn char(10),
svampkod integer references Svamp(id));

insert into Apa (nummer, namn) values (17, 'Hej');

select * from Apa;

a) (2p) Ange vilka terminaler, dvs typer av tokens, som behövs för att man ska kunna skriva en grammatik för SQL-dialekten.

b) (5p) Skriv grammatiken. Använd terminalerna från a-uppgiften. Ange vad som är startsymbol. Startsymbolen ska beskriva ett SQL-kommando, enligt ovan.

c) (2p) Om grammatiken från b-uppgiften inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, så transformera den så den passar. (Om den redan är lämplig, behöver du inte göra om den, utan du får 2 poäng på den här deluppgiften i alla fall.)

d) (6p) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 2: Faser (4 p)

Här är ett C-program. (Radnumren ingår inte i programmet, utan är bara med som referens.)
    1   #include <math.h>
    2
    3   int main(void) {
    4       char* s = "hej!;
    5       int i = 18;
    6       double = 7.3;
    7       double e = arcsin(1.13);
    8       e = s;
    9       return 0;
   10   }
När man försöker kompilera och köra programmet, får man följande fyra felmeddelanden:
faser.c:4: error: missing terminating " character
faser.c:6: error: expected identifier or '(' before '=' token
faser.c:8: error: incompatible types in assignment
faser.c:7: undefined reference to `arcsin'
En kompilator indelas i flera faser. I vilken fas (eller någonannanstans) har vart och ett av de fyra felen upptäckts?

Uppgift 3: Mellankod (10 p)

Det här är ett programavsnitt i C:
i = 1;
j = 17;
while (i < j) {
    m = (i + j - 1) / 2;
    i = i + j;
    j = i + j;
    if (i > x)
        x = j;
}
Översätt ovanstående programavsnitt till var och en av följande tre typer av mellankod:

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod, i form av en flödesgraf ("flow graph") med treadresskoden indelad i basic blocks

Uppgift 4: Optimering (5 p)

Visa vilka optimeringar som en kodoptimerare gör på flödesgrafen i uppgiften ovan. Förklara också vad som händer. Tala gärna om vad de olika optimeringarna heter.

Uppgift 5: Några termer (6 p)

Förklara kort vad följande begrepp från kompilatortekniken innebär. Ge gärna exempel.

Tala också om i vilken av kompilatorns faser (eller någonannanstans) som man använder sig av dessa saker.

  1. Nyckelhålsoptimering ("peep-hole optimization")
  2. Typsystem
  3. Strukturekvivalens ("structural equivalence")
  4. Aktiveringspost ("activation record")
  5. Döda data ("dead data")
  6. Onåbara data ("unreachable data")


Kompilatorer och interpretatorer: Tentamen 2008-12-20 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@oru.se)




Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet

lördag 20 december 2008

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100
TDK104 Kompilatorer och interpretatorer, provkod 0100







Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 36.
För godkänt betyg (3 respektive G) krävs 18 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast lördag 10 januari 2009.
Återlämning av tentor: Efter att resultatet meddelats kan tentorna hämtas på institutionen. Man kan också få sin rättade tenta hemskickad.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-73 47 013.



LYCKA TILL!

Uppgift 1 (6 p)

Betrakta nedanstående C-program:
#include <stdlib.h>
#include <stdio.h>

int a = 1;
int b = 2;
int c = 3;

void smurf(int x, int y);
void drutt(int x, int y, int z);

void smurf(int x, int y) {
    int c;
    c = a;
    x = 4;
    // Här!
    drutt(x, y - 5, 6);
}

void drutt(int x, int y, int z) {
    int c;
    int* p = malloc(sizeof(int));
    *p = 7;
    b = 8;
    c = 9;
    x = 10;
    y = 11;
    z = 12;
    smurf(a, x);
}

int main(void) {
    int b;
    a = 13;
    b = 14;
    drutt(a, b, c);
    c = 15;
    return 0;
}
a) Ett programs adressrymd kan delas upp i fyra delar: programkod och konstanter, statiska data, heap och stack. Rita upp hur stacken, heapen och statiska data ser ut första gången programkörningen kommer till kommentaren "Här!".

b) Vad kommer att hända när programmet fortsatt att köra en stund? Varför?

Uppgift 2: Språk, grammatiker och parsning (12 p)

I ett bilspel kan man dels definiera punkter, som punkterna a, d, b och tjohej i exemplet nedan, och dels ge kommandon för att köra bilen till de olika punkterna. Kommandona avslutas med semikolon. En följd av noll, ett eller flera kommandon bildar ett program. Här är ett exempel på hur ett program kan se ut:
punkt a = 6, 7;
punkt d = 6, 9;
punkt b = 8, 14;
kör till a;
kör till b;
punkt tjohej = 3, 3;
kör till d;
kör till tjohej;

a) (1p) Ange vilka terminaler, dvs typer av tokens, som behövs för att man ska kunna skriva en grammatik för det här lilla programmeringsspråket.

b) (4p) Skriv grammatiken. Använd terminalerna från a-uppgiften. Ange vad som är startsymbol. Startsymbolen ska beskriva ett program, enligt ovan.

c) (2p) Om grammatiken från b-uppgiften inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, så transformera den så den passar. (Om den redan är lämplig, behöver du inte göra om den, utan du får 2 poäng på den här deluppgiften i alla fall.)

d) (5p) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 3: Faser (6 p)

Vilka faser innehåller en typisk kompilator? Vad gör de? Visa också hur in- och utdata från varje fas kan se ut!

Uppgift 4: Mellankod (7 p)

Det här är ett programavsnitt i ett C-liknande språk:
while (true) {
    y = y - z - w * 2;
    if (z > w)
        z = y;
    else {
        z = -y;
        a = a * b - c * d;
    }
}
Översätt ovanstående programavsnitt till var och en (inte två av dem!) av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Uppgift 5: Syntaxstyrd översättning (5 p)

a) Skriv en grammatikregel för for-satsen i C.

b) Skapa ett syntaxstyrt översättningsschema, med produktioner och semantiska aktioner, för översättning av while-satsen till mellankod. Välj själv om du vill generera ett abstrakt syntaxträd, postfixkod för en stackmaskin eller treadresskod. (Tala också om vilket du valde.)


Kompilatorer och interpretatorer: Tentamen 2009-11-07 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@oru.se)




Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet m fl

lördag 7 november 2009

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100
TDK104 Kompilatorer och interpretatorer, provkod 0100



Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 40.
För godkänt betyg (3 respektive G) krävs 20 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast lördag 28 november 2009.
Återlämning av tentor: Efter att resultatet meddelats kan tentorna hämtas på institutionen. Man kan också få sin rättade tenta hemskickad.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-73 47 013.




LYCKA TILL!

Scenario till (en del av) uppgifterna

En träningsdagbok är en dagbok där man antecknar sina träningspass, som till exempel löpning och styrketräning. Vi vill att man ska kunna skriva sin träningsdagbok som en fil, och så ska ett program läsa filen och göra olika typer av bearbetning.

Här är ett exempel på hur en fil med en sådan träningsdagbok ska kunna se ut:

typ löpning;
typ motionscykling;
2009-10-19 löpning;
       typ  styrketräning ;
2009-10-19 styrketräning;

2009-10-20 löpning 43:12.2;
       2009-10-21 löpning 1:44:00.62    ;
2009-10-21
styrketräning 1:00:00
;
2009-10-22 motionscykling 1:09:22.1;
slut;

Som synes ska filen kunna skrivas på fritt format, vilket betyder att blanktecken och radslut inte spelar någon roll, annat än för att skilja orden från varandra.

Man kan skriva in vilka sporter man ägnar sig åt med "satser" som börjar med nyckelordet typ. Man kan skriva in träningspass med "satser" som börjar med ett datum, följt av namnet på en sport (som tidigare måste ha deklarerats med en typ-sats), eventuellt följt av en tid. Dessutom finns en slut-sats som markerar slutet på träningsdagboken. Alla satser avslutas med semikolon.

Det finns alltså ett "träningsdagboks-språk" som beskriver hur träningsdagboken ser ut, och ett program som ska kunna läsa och förstå träningsdagboken måste kunna läsa och förstå det språket.

Uppgift 1 (5 p)

Vi antar att datum och tid är två egna tokentyper (även kallade terminaler).

a) (2p) Vilka övriga tokentyper ingår i träningsdagboks-språket?

b) (1p) Ett exempel på hur ett datum kan se ut är 2009-10-19. Datum ska bestå av årtal med fyra siffror, ett bindestreck, månad med två siffror, ännu ett bindestreck, och till sist datum med två siffror. Skriv ett reguljärt uttryck som beskriver tokentypen datum.

c) (2p) Den träningstid som man kan ange för en träning kan bestå av timmar, minuter, sekunder och decimaldelar av en sekund, som till exempel 1:09:22.1 och 117:00:09.6293845. Minuterna och sekunderna måste vara med, men timmarna och sekunddecimalerna kan uteslutas, som till exempel 09:22.17, 1:09:22 och 0:09. Skriv ett reguljärt uttryck som beskriver tokentypen tid.

Uppgift 2 (5 p)

a) (3p) Skriv en grammatik för träningsdagboks-språket. Använd terminalerna från uppgift 1. Startsymbolen ska heta dagbok, och ska beskriva hela innehållet på filen, enligt scenariot.

b) (2p) Om grammatiken från a-uppgiften inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, så transformera den så den passar. (Om den redan är lämplig, behöver du inte göra om den, utan du får 2 poäng på den här deluppgiften i alla fall.)

Uppgift 3 (3 p)

Ett parse-träd (ibland kallat "konkret syntaxträd") innehåller noder för alla icke-terminaler. I ett syntax-träd (ibland kallat "abstrakt syntaxträd") har man tagit bort alla "onödiga" inre noder, och flyttat upp operatorerna.

Här är en kort träningsdagbok:

typ vila;
2009-10-19 vila 24:00:00;
2009-10-20 fika 1:00:00;
slut;

Rita upp ett parse-träd för denna träningsdagbok, med din grammatik från (b-)uppgiften ovan.

Uppgift 4 (5 p)

Skriv en prediktiv recursive-descent-parser för träningsdagboks-språket. Gör detta i ett språk som åtminstone liknar något vanligt känt programmeringsspråk, till exempel C. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Förklara gärna sådant som kan antas vara oklart för läraren.

Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 5 (4 p)

Här är ett C-program:
#include <stdlib.h>
#include <stdio.h>

int x = 1;

int apa(int a, int b) {
    int* p = malloc(sizeof(int));
    *p = a;
    x = a;
    if (a <= 2) {
        /* Här! */
        return 3;
    }
    else {
        return apa(a - 4, b);
    }
}

void svamp(int a, int y) {
    int z;
    z = 5;
    z = apa(6, x);
}

int main(void) {
    int a;
    int y;
    a = 7;
    y = 8;
    svamp(a, y);
    a = 9;
    return 0;
}
Ett programs adressrymd kan delas upp i fyra delar: programkod och konstanter, statiska data, heap och stack. Rita upp hur stacken, heapen och statiska data ser ut när programkörningen kommer till kommentaren "Här!".

Uppgift 6 (7 p)

Det här är ett programavsnitt i ett C-liknande språk:
i = 0;
j = 10;
n = 0;
while (i < j) {
    if (i % 2 == 0)
         i = i + 2;
    else
         j = j - 1;
    n = (j - i - 1) / 2;
}
Översätt ovanstående programavsnitt till var och en av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Uppgift 7 (5 p)

I en syntaxstyrd översättning (på engelska: "syntax-directed translation") associerar man grammatikregler med vad som ska hända. Den finns i två varianter: syntax-styrd definition (på engelska: "syntax-directed definition"), där produktionerna associeras med semantiska regler, som anger hur attribut ska få värden, och syntax-styrt översättningsschema (på engelska: "syntax-directed translation scheme"), där man stoppar in semantiska aktioner.

a) Skriv en grammatikregel för while-satsen i C.

b) Välj en form av mellankod (bland dem från uppgift 6 ovan), och tala om vilken du valde. Skriv sedan en syntax-styrd definition eller ett syntaxstyrt översättningsschema (och tala om vilken du valde) för översättning av while-satsen till mellankod.

Uppgift 8 (6 p)

En intresserad (men ibland kanske något förvirrad) person ställer frågor om kompilatorer. Svara på frågorna! Det kan kanske behövas en del förklaringar för att reda ut missuppfattningar som personen har.

a) Kompilatorn har ju faser som "scanning", "parsning" och så vidare. Varför finns det ingen fas i kompilatorn som heter "skräpsamling"? Skräpsamling är ju ett ändå ganska viktigt begrepp i modern programmering, och man vill slippa krångla med manuella free och delete.

b) Jag tycker att man borde sluta med kompilatorer och bara använda interpretatorer, för interpretatorer måste ju vara mycket snabbare. En kompilator översätter ju först källkoden, innan den kan köras, medan en interpretator börjar köra programmet direkt!

c) Bison säger att jag har en massa "shift/reduce-konflikter" här i min grammatik. Vad är det för nåt? Vad beror det på? Är det farligt?


Kompilatorer och interpretatorer: Tentamen 2009-11-07 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@oru.se)




Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet m fl

lördag 7 november 2009

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100
TDK104 Kompilatorer och interpretatorer, provkod 0100



Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 40.
För godkänt betyg (3 respektive G) krävs 20 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast lördag 28 november 2009.
Återlämning av tentor: Efter att resultatet meddelats kan tentorna hämtas på institutionen. Man kan också få sin rättade tenta hemskickad.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-73 47 013.




LYCKA TILL!

Scenario till (en del av) uppgifterna

En träningsdagbok är en dagbok där man antecknar sina träningspass, som till exempel löpning och styrketräning. Vi vill att man ska kunna skriva sin träningsdagbok som en fil, och så ska ett program läsa filen och göra olika typer av bearbetning.

Här är ett exempel på hur en fil med en sådan träningsdagbok ska kunna se ut:

typ löpning;
typ motionscykling;
2009-10-19 löpning;
       typ  styrketräning ;
2009-10-19 styrketräning;

2009-10-20 löpning 43:12.2;
       2009-10-21 löpning 1:44:00.62    ;
2009-10-21
styrketräning 1:00:00
;
2009-10-22 motionscykling 1:09:22.1;
slut;

Som synes ska filen kunna skrivas på fritt format, vilket betyder att blanktecken och radslut inte spelar någon roll, annat än för att skilja orden från varandra.

Man kan skriva in vilka sporter man ägnar sig åt med "satser" som börjar med nyckelordet typ. Man kan skriva in träningspass med "satser" som börjar med ett datum, följt av namnet på en sport (som tidigare måste ha deklarerats med en typ-sats), eventuellt följt av en tid. Dessutom finns en slut-sats som markerar slutet på träningsdagboken. Alla satser avslutas med semikolon.

Det finns alltså ett "träningsdagboks-språk" som beskriver hur träningsdagboken ser ut, och ett program som ska kunna läsa och förstå träningsdagboken måste kunna läsa och förstå det språket.

Uppgift 1 (5 p)

Vi antar att datum och tid är två egna tokentyper (även kallade terminaler).

a) (2p) Vilka övriga tokentyper ingår i träningsdagboks-språket?

b) (1p) Ett exempel på hur ett datum kan se ut är 2009-10-19. Datum ska bestå av årtal med fyra siffror, ett bindestreck, månad med två siffror, ännu ett bindestreck, och till sist datum med två siffror. Skriv ett reguljärt uttryck som beskriver tokentypen datum.

c) (2p) Den träningstid som man kan ange för en träning kan bestå av timmar, minuter, sekunder och decimaldelar av en sekund, som till exempel 1:09:22.1 och 117:00:09.6293845. Minuterna och sekunderna måste vara med, men timmarna och sekunddecimalerna kan uteslutas, som till exempel 09:22.17, 1:09:22 och 0:09. Skriv ett reguljärt uttryck som beskriver tokentypen tid.

Uppgift 2 (5 p)

a) (3p) Skriv en grammatik för träningsdagboks-språket. Använd terminalerna från uppgift 1. Startsymbolen ska heta dagbok, och ska beskriva hela innehållet på filen, enligt scenariot.

b) (2p) Om grammatiken från a-uppgiften inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, så transformera den så den passar. (Om den redan är lämplig, behöver du inte göra om den, utan du får 2 poäng på den här deluppgiften i alla fall.)

Uppgift 3 (3 p)

Ett parse-träd (ibland kallat "konkret syntaxträd") innehåller noder för alla icke-terminaler. I ett syntax-träd (ibland kallat "abstrakt syntaxträd") har man tagit bort alla "onödiga" inre noder, och flyttat upp operatorerna.

Här är en kort träningsdagbok:

typ vila;
2009-10-19 vila 24:00:00;
2009-10-20 fika 1:00:00;
slut;

Rita upp ett parse-träd för denna träningsdagbok, med din grammatik från (b-)uppgiften ovan.

Uppgift 4 (5 p)

Skriv en prediktiv recursive-descent-parser för träningsdagboks-språket. Gör detta i ett språk som åtminstone liknar något vanligt känt programmeringsspråk, till exempel C. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Förklara gärna sådant som kan antas vara oklart för läraren.

Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 5 (4 p)

Här är ett C-program:
#include <stdlib.h>
#include <stdio.h>

int x = 1;

int apa(int a, int b) {
    int* p = malloc(sizeof(int));
    *p = a;
    x = a;
    if (a <= 2) {
        /* Här! */
        return 3;
    }
    else {
        return apa(a - 4, b);
    }
}

void svamp(int a, int y) {
    int z;
    z = 5;
    z = apa(6, x);
}

int main(void) {
    int a;
    int y;
    a = 7;
    y = 8;
    svamp(a, y);
    a = 9;
    return 0;
}
Ett programs adressrymd kan delas upp i fyra delar: programkod och konstanter, statiska data, heap och stack. Rita upp hur stacken, heapen och statiska data ser ut när programkörningen kommer till kommentaren "Här!".

Uppgift 6 (7 p)

Det här är ett programavsnitt i ett C-liknande språk:
i = 0;
j = 10;
n = 0;
while (i < j) {
    if (i % 2 == 0)
         i = i + 2;
    else
         j = j - 1;
    n = (j - i - 1) / 2;
}
Översätt ovanstående programavsnitt till var och en av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Uppgift 7 (5 p)

I en syntaxstyrd översättning (på engelska: "syntax-directed translation") associerar man grammatikregler med vad som ska hända. Den finns i två varianter: syntax-styrd definition (på engelska: "syntax-directed definition"), där produktionerna associeras med semantiska regler, som anger hur attribut ska få värden, och syntax-styrt översättningsschema (på engelska: "syntax-directed translation scheme"), där man stoppar in semantiska aktioner.

a) Skriv en grammatikregel för while-satsen i C.

b) Välj en form av mellankod (bland dem från uppgift 6 ovan), och tala om vilken du valde. Skriv sedan en syntax-styrd definition eller ett syntaxstyrt översättningsschema (och tala om vilken du valde) för översättning av while-satsen till mellankod.

Uppgift 8 (6 p)

En intresserad (men ibland kanske något förvirrad) person ställer frågor om kompilatorer. Svara på frågorna! Det kan kanske behövas en del förklaringar för att reda ut missuppfattningar som personen har.

a) Kompilatorn har ju faser som "scanning", "parsning" och så vidare. Varför finns det ingen fas i kompilatorn som heter "skräpsamling"? Skräpsamling är ju ett ändå ganska viktigt begrepp i modern programmering, och man vill slippa krångla med manuella free och delete.

b) Jag tycker att man borde sluta med kompilatorer och bara använda interpretatorer, för interpretatorer måste ju vara mycket snabbare. En kompilator översätter ju först källkoden, innan den kan köras, medan en interpretator börjar köra programmet direkt!

c) Bison säger att jag har en massa "shift/reduce-konflikter" här i min grammatik. Vad är det för nåt? Vad beror det på? Är det farligt?


Kompilatorer och interpretatorer: Tentamen 2009-12-19 Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@oru.se)




Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet m fl

lördag 19 december 2009

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100
TDK104 Kompilatorer och interpretatorer, provkod 0100



Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 37.
För godkänt betyg (3 respektive G) krävs 18 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast lördag 9 januari 2010.
Återlämning av tentor: Efter att resultatet meddelats kan tentorna hämtas på institutionen. Man kan också få sin rättade tenta hemskickad.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-73 47 013.




LYCKA TILL!

Uppgift 1: Faser (5 p)

En kompilators arbete brukar delas in i flera faser. Ange vilka det är, och förklara kort vad varje fas gör. Vad är in- och utdata från respektive fas?

Uppgift 2: Scanning och reguljära uttryck (5 p)

a) (3p) Skriv reguljära uttryck för följande olika typer av tokens som förekommer i vanliga programmeringsspråk:

b) (2p) Vad är det för skillnad på ett lexem och ett lexikaliskt värde, och vad har dessa med scanning att göra?

Uppgift 3: Grammatiker och top-down-parsning (15 p)

I följande grammatik är S, X och Y icketerminaler. a, b, c, d och e är terminaler. S är startsymbol.
S -> a X | b | X Y
X -> X c | e
Y -> d Y | d

a) Ange tio olika strängar som ingår i det språk som beskrivs av grammatiken ovan.

b) Grammatiken lämpar sig inte för implementation av en prediktiv recursive-descent-parser (engelska: predictive recursive-descent parser). Ange vilka problem det är, vad i grammatiken som orsakar problemen, och vad som händer i parsern.

c) Använd de transformationer som tagits upp i kursen för att omvandla grammatiken till en grammatik som beskriver samma språk, men som enkelt kan implementeras i en prediktiv recursive-descent-parser. Ange de generella transformationsregler som du använder, och visa vad resultatet blir för den här grammatiken.

d) Skriv den prediktiva recursive-descent-parsern i ett språk som åtminstone liknar C, Java eller Pascal. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Du kan anta att det finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 4: Mellankod (5 p)

x = 1;
while (y < 2) {
    if (z > 3) {
        t = t - x - y / (1 - z - y);
    }
    else {
        x = 1;
        y = 2;
        z = 3;
    }
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 5: Några termer (7 p)

Förklara kort vad följande begrepp från kompilatortekniken innebär:

a) aktiveringspost
b) basic block
c) copy propagation
d) fas (engelska: phase)
e) pass (engelska: pass)
f) registerallokering
g) rotmängd (engelska: root set)


Kompilatorer och interpretatorer: Tentamen 2010-10-30 Örebro University
School of Science and Technology
Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se)









Exam

Compilers and Interpreters

for Dataingenjörsprogrammet, and others

Saturday October 30, 2010

Exam for:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100








→ This exam is also available in a Swedish version.

Aids: No aids.
Score requirements: Maximum score is 32.
To pass (3 or G), at least 16 points are required.
Results: Announced on the course website or by e-mail by Saturday November 20, 2010.
Return of the exams: After the result has been announced, exams can be collected from the university's central "tentamensutlämning".
Examiner: Thomas Padron-McCarthy




GOOD LUCK!!

Task 1: Phases (3 p)

When we compile the following C program, the compiler gives the italicized error and warning messages:
#include <stdio.h>

int main(void) {
    int a;

    printf("Hi!\n );            error: missing terminating " character
    printf("Give a number: ");
    scanf("%d", &a ;            error: expected ')' before ';' token
    printf("The number was: %d\n", a);

    return "Charles";           warning: return makes integer from pointer without a cast
}
A compiler's work is usually divided into several phases. In which phases are these errors and warnings detected?

Task 2: Scanning and Regular Expression (5 p)

a) (2p) Write regular expressions for the following:

b) (2p) Write a regular expression for the Swedish personal identity number (for example 631211-1658). Your expression should match all valid such numbers. It is difficult to write a regular expression that does not also match certain incorrect numbers, so your solution is allowed to do that. But state at least one check that is not made by your regular expression.

c) (1p) What is the difference between a token and a lexeme?

Task 3: Grammars (10 p)

Here are three things that are problematic in a grammar:

a) left recursion
b) FIRST() conflicts
c) ambiguity

For each of these problems, provide an example of a grammar that exhibits the problem. Also explain, for each of the grammars, how the problem manifests itself in practice. (That is: what is it that does not work, because of the problem?) Also explain how to solve the problem.

Task 4: Intermediate Code (5 p)

x = 1;
y = 2;
z = 3;
while (y == 2) {
    if (z > 4) {
        y = y - 1 - 1;
    }
    else {
        z = z + y * z + z;
        t = t + 2;
    }
}
Translate the above program section to two of the following three types of intermediate code:

a) an abstract syntax tree (by drawing the tree!)

b) postfix code for a stack machine

c) three-address code

Note: There are three sub-tasks in the task above. Select and answer (at most) two of them. (If you answer all three, the one with the most points will be discarded.)

Task 5: Some Terms(9 p)

Briefly explain what the following terms from compiler technology mean:

a) target language
b) target program
c) front end
d) Yacc
e) symbol table
f) shift-reduce conflict
g) deterministic finite state machine
h) reserved word (or "keyword")
i) call sequence


Kompilatorer och interpretatorer: Tentamen 2010-10-30 Örebro universitet
Akademin för naturvetenskap och teknik
Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se)







Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet m fl

lördag 30 oktober 2010

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100






→ This exam is also available in an English version.

Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 32.
För godkänt betyg (3 respektive G) krävs 16 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast lördag 20 november 2010.
Återlämning av tentor: Efter att resultatet meddelats kan tentorna hämtas på universitetets centrala tentamensutlämning.
Examinator: Thomas Padron-McCarthy




LYCKA TILL!

Uppgift 1: Faser (3 p)

När vi kompilerar följande försök till C-program, ger kompilatorn de kursiverade fel- och varningsmeddelandena:
#include <stdio.h>

int main(void) {
    int a;

    printf("Hej!\n );         error: missing terminating " character
    printf("Ange ett tal: ");
    scanf("%d", &a ;          error: expected ')' before ';' token
    printf("Talet var: %d\n", a);

    return "Kalle";           warning: return makes integer from pointer without a cast
}
En kompilators arbete brukar delas in i flera faser. I vilka faser upptäcks de olika felen och varningarna?

Uppgift 2: Scanning och reguljära uttryck (5 p)

a) (2p) Skriv reguljära uttryck ("regexpar") för följande:

b) (2p) Skriv ett reguljärt uttryck för svenska personnummer (som till exempel 631211-1658). Uttrycket ska matcha alla giltiga personnummer. Det är besvärligt att skriva ett reguljärt uttryck som inte också matchar vissa otillåtna personnummer, så det gör inget om ditt svar gör det. Men förklara minst en kontroll som inte görs av ditt reguljära uttryck.

c) (1p) Vad är det för skillnad på en token och ett lexem?

Uppgift 3: Grammatiker (10 p)

Här är tre saker som kan vara problematiska i en grammatik:

a) vänsterrekursion
b) FIRST()-konflikter
c) tvetydighet

Ge för var och en av dessa saker exempel på en grammatik som uppvisar problemet. Förklara också för var och en av dessa grammatiker hur problemet visar sig i praktiken. (Dvs: vad är det som inte fungerar, på grund av det problemet?) Visa också hur man löser problemet.

Uppgift 4: Mellankod (5 p)

x = 1;
y = 2;
z = 3;
while (y == 2) {
    if (z > 4) {
        y = y - 1 - 1;
    }
    else {
        z = z + y * z + z;
        t = t + 2;
    }
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 5: Några termer (9 p)

Förklara kort vad följande begrepp från kompilatortekniken innebär:

a) målspråk
b) målprogram
c) front end
d) Yacc
e) symboltabell
f) shift-reduce-konflikt
g) deterministisk ändlig tillståndsmaskin
h) reserverat ord
i) anropskonventioner (på engelska: call sequence)


Kompilatorer och interpretatorer: Tentamen 2011-08-15 Örebro universitet
Akademin för naturvetenskap och teknik
Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se)



Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet m fl

måndag 15 augusti 2011

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100


Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 30.
För godkänt betyg (3 respektive G) krävs 15 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast måndag 5 september 2011.
Återlämning av tentor: Efter att resultatet meddelats kan tentorna hämtas på universitetets centrala tentamensutlämning.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070 - 73 47 013.




LYCKA TILL!

Uppgift 1: Pass och faser (6 p)

a) Vad är det, i kompilatorsammanhang, för skillnad på en fas och ett pass?

b) Vilka faser brukar man tala om? Skriv inte bara vad de heter, utan beskriv (mycket) kort vad de gör.

c) När vi "bygger" (dvs kompilerar och länkar) följande försök till C-program, får vi de tre kursiverade fel- och varningsmeddelandena. I vilka faser upptäcks dessa fel och varningar?

#include <stdio.h>

int main(void) {
    int a;
    int 2a;                     error: invalid suffix "a" on integer constant

    printf("Hej!\n");
    printg("Ange ett tal: ");   warning: implicit declaration of function 'printg'
                                error: undefined reference to `printg'
    scanf("%d", &a);
    printf("Talet = %d\n", a);

    return 0;
}

Uppgift 2: Mellankod (6 p)

Det här är ett programavsnitt i ett C-liknande språk:
a = 1;
b = a - b - c * d;
while (i * 2 > j * 3) {
    if (i % 2 == 0)
         i = i + 2;
    b = i;
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Scenario till (en del av) uppgifterna

I en kartdatabas vill vi kunna lägga in tätorter och vägar mellan dem. Vi vill också kunna lägga in rutter, som leder från en tätort till en annan och som består av en eller flera vägar. För att mata in detta konstruerar vi ett enkelt språk.

Man använder nyckelordet ort för att lägga in en tätort, till exempel så här: ort Örebro

Man använder nyckelordet väg för att lägga in en väg, till exempel så här för att ange att det finns en väg mellan Örebro och Karlskoga: väg Örebro Karlskoga

Man använder nyckelordet rutt (och nyckelordet framme) för att lägga in en rutt, till exempel så här för att lägga in en rutt från Örebro till Karlstad: rutt Örebro Karlskoga Kristinehamn Karlstad framme

Man använder nyckelordet slut för att ange slutet på hela inmatningen.

Här är ett komplett exempel:

ort Örebro
ort Karlstad
ort Karlskoga
ort Kristinehamn
ort Arboga
ort Kungsör
ort Oslo
väg Örebro Karlskoga
väg Karlskoga Kristinehamn
väg Kristinehamn Karlstad
rutt Örebro Karlskoga Kristinehamn Karlstad framme
väg Örebro Arboga
väg Arboga Kungsör
rutt Örebro Arboga Kungsör framme
slut

Kommandona ska kunna skrivas på fritt format, vilket betyder att blanktecken och radslut inte spelar någon roll, annat än för att skilja orden från varandra.

Vi antar att ortnamn alltid består av ett enda ord.

Uppgift 3: Grammatiker (5 p)

a) (1p) Vilka tokentyper ingår i språket?

b) (4p) Skriv en grammatik för språket. Använd terminalerna från deluppgift a. Om grammatiken inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, ska du också transformera den så den passar.

Uppgift 4: Träd (3 p)

Ett parse-träd (ibland kallat "konkret syntaxträd") innehåller noder för alla icke-terminaler. I ett syntax-träd (ibland kallat "abstrakt syntaxträd") har man tagit bort alla "onödiga" inre noder, och flyttat upp operatorerna.

Här är ett kortare exempel på inmatning till kartdatabasen:

ort Örebro
ort Karlstad
väg Örebro Karlskoga
slut

Rita upp ett parse-träd för denna inmatning, med din grammatik från uppgiften ovan.

Uppgift 5: Parsning (6 p)

Skriv en prediktiv recursive-descent-parser för inmatningsspråket. Gör detta i ett språk som åtminstone liknar något vanligt känt programmeringsspråk, till exempel C. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Förklara gärna sådant som kan antas vara oklart för läraren.

Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 6: Några termer (4 p)

Förklara kort vad följande begrepp från kompilatortekniken innebär. Ge gärna exempel.

  1. Aktiveringspost ("activation record")
  2. Döda data ("dead data")
  3. Död kod ("dead code")
  4. Referensräkning ("reference counting")


Kompilatorer och interpretatorer: Tentamen 2011-10-31 Örebro universitet
Akademin för naturvetenskap och teknik
Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se)
Med vissa korrigeringar 2011-10-31.


Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet m fl

måndag 31 oktober 2011

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100


Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 30.
För godkänt betyg (3 respektive G) krävs 15 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast måndag 21 november 2011.
Återlämning av tentor: Efter att resultatet meddelats kan tentorna hämtas på universitetets centrala tentamensutlämning.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070 - 73 47 013.




LYCKA TILL!

Uppgift 1: Grunder om kompilatorer (6 p)

När man skriver ett någorlunda stort program är det bra att dela upp det i moduler. Det gäller även kompilatorer. Vi gör ett försök att dela upp kompilatorn i moduler, och åstadkommer den här listan:
  1. debugger
  2. editor
  3. kodgenerering
  4. lexikalisk analys ("scanner")
  5. länkning
  6. maskinberoende optimering
  7. maskinoberoende optimering
  8. mellankodsgenerering
  9. semantisk analys
  10. symboltabellen
  11. syntaktisk analys ("parser")

a) (1 p) Det blev fel i listan ovan. Vilka av de uppräknade modulerna ingår inte i kompilatorn?

b) (1p) En del av de uppräknade modulerna brukar kallas "faser". Vad menas med en fas?

c) (0.5 p) En av modulerna ingår i kompilatorn, men är inte en fas. Vilken?

d) (0.5p) I listan ovan är modulerna ordnade i bokstavsordning. Lista faserna i rätt ordning.

e) (3p) Indata till den första fasen består av källprogrammet i textform (alltså en sekvens av tecken), medan utdata från den sista fasen utgörs av ett målprogram uttryckt i maskinspråk eller assemblerspråk. Beskriv alla fasernas indata och utdata.

Uppgift 2: Mellankod (6 p)

Det här är ett programavsnitt i ett C-liknande språk:
if (a < b) {
    c = d / e / f;
}
else {
    while (g > h) {
        i = j;
        k = l / (m / n);
    }
    o = 17;
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 3: En oändlig loop (2p)

while-loopen i uppgiften ovan ser ut att ha ett problem. Om villkoret g > h är sant (och i eller k inte på något oväntat sätt refererar till g eller h), kommer loopen aldrig att avslutas.

a) Vad innebär detta för mellankodsgenereringen i uppgiften ovan? Förklara också varför!

b) Vad innebär detta för kompileringen i övrigt? Dvs, beskriv om andra delar av kompilatorn på något sätt hanterar att loopen är oändlig.

Scenario till resten av uppgifterna

Vi åker runt och avlyssnar radiomeddelanden:

En mobil radiostation. Licens: Creative Commons Attribution-Share Alike 30.

Vi konstruerar ett enkelt språk för att ange var och när vi avlyssnat. Man använder nyckelordet avlyssnat för att ange en avlyssning, med tid och plats. Platser kan anges med koordinater, men man kan också namnge platser med nyckelordet plats. Man använder nyckelordet slut för att ange slutet på hela inmatningen.

Här är ett komplett exempel:

avlyssnat 9:10:22.103 59.274120 15.2066
plats Örebro = 59.274120 15.2066
avlyssnat 15:07:28.210 Örebro
plats Örebro-universitet = 59.254320 15.24625
plats Brickeberg = 59.2465 15.2415
plats Tripoli = 32.902222 13.185833
avlyssnat 16:01:01 Tripoli
slut

Kommandona ska kunna skrivas på fritt format, vilket betyder att blanktecken och radslut inte spelar någon roll, annat än för att skilja orden från varandra.

Vi antar att platsnamn alltid består av ett enda ord.

Uppgift 4: Grammatiker (4 p)

a) (1p) Vilka tokentyper ingår i inmatningsspråket från uppgiften ovan?

b) (3p) Skriv en grammatik för språket. Använd terminalerna från deluppgift a. Om grammatiken inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, ska du också transformera den så den passar.

Uppgift 5: Parsning (6 p)

Skriv en prediktiv recursive-descent-parser för inmatningsspråket ovan. Gör detta i ett språk som åtminstone liknar något vanligt känt programmeringsspråk, till exempel C. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Förklara gärna sådant som kan antas vara oklart för läraren.

Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 6: Scanning och reguljära uttryck (1 p)

Skriv reguljärt uttryck ("regexp") för tidsangivelserna i inmatningsspråket ovan. De består av timmar, minuter och sekunder, med kolon emellan. Sekunddelen kan innehålla decimaler.

Uppgift 7: Optimering (5 p)

Här är lite treadresskod:
(1) temp1 = b * 17
(2) temp2 = c * 18
(3) a = temp1 + temp2
(4) temp3 = c * 18
(5) if (a > temp3) goto 14
(6) temp4 = c - 1
(7) if (a > temp4) goto 13
(8) temp5 = 1 * d
(9) c = c - temp5
(10) temp6 = b * 17
(11) a = a + temp6
(12) goto 6
(13) goto 16
(14) e = b * 17
(15) f = c * 18
(16) temp7 = b * 17
(17) g = a + temp7

a) Dela in koden i basic blocks.

b) Optimera koden med hjälp av de vanliga metoderna för optimering, såväl inom ett enskilt basic block som i flera block. Beskriv inte bara resultatet, utan de olika stegen, gärna med namn.


Kompilatorer och interpretatorer: Tentamen 2011-10-31 Örebro universitet
Akademin för naturvetenskap och teknik
Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se)



Tentamen i

Kompilatorer och interpretatorer

för Dataingenjörsprogrammet m fl

måndag 31 oktober 2011

Gäller som tentamen för:
DT3004 Datateknik C, Kompilatorer och interpretatorer, provkod 0100


Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 30.
För godkänt betyg (3 respektive G) krävs 15 poäng.
Resultat: Meddelas på kursens hemsida eller via e-post senast måndag 21 november 2011.
Återlämning av tentor: Efter att resultatet meddelats kan tentorna hämtas på universitetets centrala tentamensutlämning.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070 - 73 47 013.




LYCKA TILL!

Uppgift 1: Grunder om kompilatorer (6 p)

När man skriver ett någorlunda stort program är det bra att dela upp det i moduler. Det gäller även kompilatorer. Vi gör ett försök att dela upp kompilatorn i moduler, och åstadkommer den här listan:
  1. debugger
  2. editor
  3. kodgenerering
  4. lexikalisk analys ("scanner")
  5. länkning
  6. maskinberoende optimering
  7. maskinoberoende optimering
  8. mellankodsgenerering
  9. semantisk analys
  10. symboltabellen
  11. syntaktisk analys ("parser")

a) (1 p) Det blev fel i listan ovan. Vilka av de uppräknade modulerna ingår inte i kompilatorn?

a) (1p) En del av de uppräknade modulerna brukar kallas "faser". Vad menas med en fas?

a) (0.5 p) En av modulerna ingår i kompilatorn, men är inte en fas. Vilken?

c) (0.5p) I listan ovan är modulerna ordnade i bokstavsordning. Lista faserna i rätt ordning.

d) (3p) Indata till den första fasen består av källprogrammet i textform (alltså en sekvens av tecken), medan utdata från den sista fasen utgörs av ett målprogram uttryckt i maskinspråk eller assemblerspråk. Beskriv alla fasernas indata och utdata.

Uppgift 2: Mellankod (6 p)

Det här är ett programavsnitt i ett C-liknande språk:
if (a < b) {
    c = d / e / f;
}
else {
    while (g > h) {
        i = j;
        k = l / (m / n);
    }
    o = 17;
}
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod.

a) ett abstrakt syntaxträd (genom att rita upp trädet!)

b) postfixkod för en stackmaskin

c) treadresskod

Observera: Det finns tre deluppgifter i uppgiften ovan. Välj ut och besvara (högst) två av dessa. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

Uppgift 3: En oändlig loop (2p)

while-loopen i uppgiften ovan ser ut att ha ett problem. Om villkoret g > h är sant (och i eller k inte på något oväntat sätt refererar till g eller h), kommer loopen aldrig att avslutas.

a) Vad innebär detta för mellankodsgenereringen i uppgiften ovan? Förklara också varför!

b) Vad innebär detta för kompileringen i övrigt? Dvs, beskriv om andra delar av kompilatorn på något sätt hanterar att loopen är oändlig.

Scenario till resten av uppgifterna

Vi åker runt och avlyssnar radiomeddelanden:

En mobil radiostation. Licens: Creative Commons Attribution-Share Alike 30.

Vi konstruerar ett enkelt språk för att ange var och när vi avlyssnat. Man använder nyckelordet avlyssnat för att ange en avlyssning, med tid och plats. Platser kan anges med koordinater, men man kan också namnge platser med nyckelordet plats. Man använder nyckelordet slut för att ange slutet på hela inmatningen.

Här är ett komplett exempel:

avlyssnat 9:10:22.103 59.274120 15.2066
plats Örebro = 59.274120 15.2066
avlyssnat 15:07:28.210 Örebro
plats Örebro-universitet = 59.254320 15.24625
plats Brickeberg = 59.2465 15.2415
plats Tripoli = 32.902222 13.185833
avlyssnat 16:01:01 Tripoli
slut

Kommandona ska kunna skrivas på fritt format, vilket betyder att blanktecken och radslut inte spelar någon roll, annat än för att skilja orden från varandra.

Vi antar att platsnamn alltid består av ett enda ord.

Uppgift 4: Grammatiker (4 p)

a) (1p) Vilka tokentyper ingår i inmatningsspråket från uppgiften ovan?

b) (3p) Skriv en grammatik för språket. Använd terminalerna från deluppgift a. Om grammatiken inte lämpar sig för implementation i form av en prediktiv recursive-descent-parser, ska du också transformera den så den passar.

Uppgift 5: Parsning (6 p)

Skriv en prediktiv recursive-descent-parser för inmatningsspråket ovan. Gör detta i ett språk som åtminstone liknar något vanligt känt programmeringsspråk, till exempel C. Du behöver inte skriva exakt korrekt programkod, men det ska framgå vilka procedurer som finns, hur de anropar varandra, och vilka jämförelser med tokentyper som görs. Förklara gärna sådant som kan antas vara oklart för läraren.

Du kan anta att det redan finns en funktion som heter scan, och att den returnerar typen på nästa token.

Uppgift 6: Scanning och reguljära uttryck (1 p)

Skriv reguljärt uttryck ("regexp") för tidsangivelserna i inmatningsspråket ovan. De består av timmar, minuter och sekunder, med kolon emellan. Sekunddelen kan innehålla decimaler.

Uppgift 7: Optimering (5 p)

Här är lite treadresskod:
(1) temp1 = b * 17
(2) temp2 = c * 18
(3) a = temp1 + temp2
(4) temp3 = c * 18
(5) if (a > temp3) goto 14
(6) temp4 = c - 1
(7) if (a > temp4) goto 13
(8) temp5 = 1 * d
(9) c = c - temp5
(10) temp6 = b * 17
(11) a = a + temp6
(12) goto 6
(13) goto 16
(14) e = b * 17
(15) f = c * 18
(16) temp7 = b * 17
(17) g = a + temp7

a) Dela in koden i basic blocks.

b) Optimera koden med hjälp av de vanliga metoderna för optimering, såväl inom ett enskilt basic block som i flera block. Beskriv inte bara resultatet, utan de olika stegen, gärna med namn.