Örebro universitet
Institutionen för naturvetenskap och teknik
Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se)




Tentamen i

Kompilatorer och interpretatorer

onsdag 19 mars 2025

Gäller som tentamen för:
DT501A Kompilatorer och interpretatorer för civilingenjörer, provkod A001



Hjälpmedel: Ordbok för översättning.
Poängkrav: Maximal poäng är 40.
För godkänt betyg krävs totalt minst 24 poäng.
Resultat: Meddelas senast 15 arbetsdagar efter tentamensdatum.
Återlämning av tentor: Elektroniskt via webbportalen Studenttjänster.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070 - 73 47 013.





LYCKA TILL!

Formelsamling

1. Eliminering av vänsterrekursion

En vänsterrekursiv grammatik kan skrivas om så att den inte är vänsterrekursiv. Antag att en regel (eller, korrektare uttryckt, två produktioner) i grammatiken ser ut så här:
A -> A x | y
A är en icke-terminal, men x och y står för godtyckliga konstruktioner som består av terminaler och icke-terminaler.

Regeln ersätts av följande två regler (eller, korrektare uttryckt, tre produktioner), som beskriver samma språk men som inte är vänsterrekursiva:

A -> y R
R -> x R | empty

2. Vänsterfaktorisering

Antag att grammatiken innehåller denna regel (två produktioner):
A -> x y | x z
A är en icke-terminal, men x, y och z står för godtyckliga konstruktioner som består av terminaler och icke-terminaler.

Skriv om till dessa tre produktioner:

A -> x R
R -> y | z

Scenario till uppgift 1-4

Schack, skriver Wikipedia, är ett bräd- och strategispel för två deltagare som spelas på ett bräde med 8 gånger 8 omväxlande vita och svarta rutor. Vid spelets början har den ene spelaren ("vit") 16 vita pjäser och den andre spelaren ("svart") 16 svarta pjäser. Spelarna turas om att flytta sina pjäser. Här är ett schakbräde med pjäser:

Ett schackbräde

(Bilden är från användaren Karophyr på engelska Wikipedia, licensierad under Creative Commons Attribution-Share Alike 2.5 Generic, 2.0 Generic och 1.0 Generic.)

Schacknotation är ett system för att nedteckna schackpartier för senare genomgång och analys. Den vanligaste metoden är den algebraiska notationen, som bygger på schackbrädets koordinatsystem. Ett exempel med ett mycket kort parti:

1. e4 e5
2. Lc4 Sc6
3. Dh5 Sf6
4. Df7#

På varje rad anges först dragets ordningsnummer, därefter den vita spelarens drag, och sist den svarta spelarens drag. Ett drag anges med vilken sorts pjäs som flyttades och koordinaterna för den ruta som pjäsen flyttades till. Pjäsen anges med K för kung, D för dam, T för torn, L för löpare, S för springare, och ingenting för bonde. Koordinaterna består av en bokstav från a till h och en siffra från 1 till 8.

Om en av spelarna vinner och partiet tar slut anges det med tecknet #, som i exemplet ovan. Det kan komma efter den vita spelarens drag, som i exemplet, och då gör den svarta spelaren inget drag, och det kan också komma efter den svarta spelarens drag.

På riktigt är notationen krångligare, och det finns fler sorters drag, men här nöjer vi oss med beskrivningen ovan.

Uppgift 1 (4 p)

a) Vilka terminaler behövs för att man ska kunna skriva en grammatik för språket i scenariot?

b) En del av terminalerna har inte fixa lexem, utan kan se olika ut. Skriv, för varje sådan terminal, ett reguljärt uttryck som beskriver hur den får se ut!

Uppgift 2 (5 p)

Skriv en grammatik för språket. Startsymbolen ska vara inmatning, som representerar en komplett inmatning enligt scenariot ovan.

Uppgift 3 (4 p)

Ett parse-träd (ibland kallat "konkret syntaxträd") innehåller noder för alla icke-terminaler. Rita upp parse-trädet för den här inmatningen, enligt din grammatik i uppgiften ovan:

1. g4 e5
2. f3 Dh4#

Uppgift 4 (8 p)

Skriv en prediktiv recursive-descent-parser för språket i ett språk som åtminstone liknar C, C++, C# eller Java. 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, som returnerar typen på nästa token, och en funktion som heter error, som man kan anropa när något gått fel och som skriver ut ett felmeddelande och avslutar programmet.

Uppgift 5 (8 p)

Det här är ett programavsnitt i ett C-liknande språk:
x = 1;
y = 2;
while (z < t) {
    x = y * z + t / u / v + w;
}
while (x > y) {
    y = r + s + t * u * v;
    x = w;
}

Översätt ovanstående programavsnitt till två av följande tre representationer. (Skulle du svara på alla tre, räknas den med högst poäng bort.)

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

Observera: Två av typerna, inte alla tre!

Uppgift 6 (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?

Uppgift 7 (5 p)

Betrakta följande C-program:

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

int x, y, z;

void f(int a, int b) {
    int z;
    x = 1;
    y = 2;
    z = 3;
    int* p;
    p = malloc(sizeof(int));
    *p = a;
    if (a < 4)
        f(a + 5, b + 6);
    else
        printf("Här!\n");
}

int main(void) {
    int x, y;
    x = 7;
    y = 8;
    z = 9;
    f(0, y);
}

Funktionen main anropar funktionen f, som i sin tur kan anropa sig själv rekursivt. När programexekveringen i kommer fram till utskriften "Här!", 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".