• Keine Ergebnisse gefunden

Testaufgaben zu Compilerbau −−−− Lösungen

N/A
N/A
Protected

Academic year: 2021

Aktie "Testaufgaben zu Compilerbau −−−− Lösungen"

Copied!
9
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Testaufgaben zu Compilerbau −−−− Lösungen

1. Aufgabe: Lex-Programmierung

Gegeben ist ein ASCII-Text, in den E-Mail-Adressen eingestreut sind. Daraus sind alle E- Mail-Adressen herauszufiltern, die einer der Top Level Domains it, ch, de zugeordnet sind und zeilenweise am Bildschirm aufzulisten.

E-Mail-Adressen genügen der folgenden Formatspezifikation:

<name>@<domain>

<name> ::= <vorname>.<nachname>

<domain> ::= [<hostname>.[<subdomain>.[<subdomain>.[ .... ]]]].<domain>.<topleveldomain>

Dabei sind <hostname>, <subdomain>, <domain>, <topleveldomain> Zeichenfolgen aus kleinen oder großen Buchstaben, Ziffern und dem Minuszeichen.

Für <topleveldomain> kommen in unserem Fall nur die Werte it, IT, ch, CH, de, DE in Frage. Ein Beispiel für eine solche Adresse ist somit:

julius.caesar@capitol.rom.it

Ein Lex-Programm, das die angegebenen eMuil-Adressen herausfiltert ist:

%{

/* Filtern von eMail-Adresen der Top Level Domains de, ch, it */

/* ========================================================== */

%}

digit [0-9]

letter [a-zA-Z]

ch [0-9a-zA-Z-]

name ({ch}+[\.])?{ch}+

hostname {ch}+

domain {ch}+

subdomain {ch}+

topleveldomain (at|ch|de|AT|CH|DE)

email {na-

me}@({hostname}\.)?({subdomain}\.)*{domain}\.(it|ch|de|IT|CH|DE)

%%

{email} { printf ("\n%s", yytext); }

\n { ; }

. { ; }

%%

main () {

yylex();

}

(2)

2. Aufgabe: Endliche Automaten

a) Geben Sie einen Endlichen Automaten an, der alle 0,1-Folgen akzeptiert, die mindestens die Länge 1 haben und unter je drei aufeinanderfolgenden Zeichen mindestens eine 1 enthalten. (Zustandsgraph, Start-/Endzustände)

b) Geben Sie eine reguläre Grammatik an, welche die in a) beschriebene Sprache erzeugt.

Begründen Sie kurz, daß Ihre Grammatik dies leistet.

zu a: Zustandsdiagramm

Zustand B ⇔ Es war zuletzt eine 1 da.

Zustand C ⇔ Es war zuletzt eine 0 da und unmittelbar davor eine 1.

Zustand D ⇔ Es war zuletzt zwei Nullen da.

Zustand E ⇔ Fehlerzustand

Startzustand = A, Endzustände = B, C, D

zu b: Grammatik:

{ }

{ }

X

0 | 1

X 1X | 0A | 1| 0 A 1X | 0B | 1| 0 B 1X | 1

| A | B

=

=

= →

ì ü

ï ï

í ý

ï ï

î þ

4

4

N T

P

Begründung, daß die Grammatik die in a) beschriebene Sprache erzeugt:

− Die Grammatik erzeugt Folgen von Nullen und Einsen

− Eine 1 kann vom aktuellen Nonterminal aus jederzeit als nächstes Zeichen entstehen

− Eine 0 kann immer entstehen, wenn gerade eine 1 erzeugt wurde, weil dann X das Non- termianl ist.

− Die einzige Möglichkeit zwei Nullen zu erzeugen ist X → ....0A → 00B

− Danach muß erst wieder eine 1 erzeugt werden mit B → ....

(3)

3. Aufgabe: Speicherverwaltung

Gegeben ist der folgende Ausschnitt aus einem Pascal-Programm:

program HP;

var a, b, c: integer; ....

procedure P1;

VAR a, b; c: integer; ...

begin { P1 } ... end; { P1 } procedure P2;

VAR a, u, v: integer; ...

procedure P3;

VAR a, x, y: integer; ...

procedure P4;

VAR a, b: integer; ...

begin { P4 } ... end; { P4}

begin { P3 } ... end; { P3 } begin { P2 } ... end; { P2 } begin { HP } ... end. { HP }

Skizzieren Sie den Aufbau der Symboltabelle einschließlich der dort eingetragenen Variablen zum Zeitpunkt der Übersetzung des Rumpfes der Prozedur P4 und schildern Sie, wie der Compiler zu diesem Zeitpunkt den Symboltabelleneintrag der Variablen c sucht.

Lösung:

Name Typ

0

1 a varobj

2 b varobj

3 c varobj

4 p1 procobj

5 p2 procobj

6 a varobj

7 u varobj

8 v varobj

9 p3 procobj

10 a varobj

11 x varobj

12 y varobj

13 p4 procobj

14 a varobj

15 b varobj

Die Variable c wird zum Zeitpunkt der Übersetzung des Rumpfes der Prozedur P4 vom unte- re Ende der Symboltabelle her gesucht und auf Position 3 gefunden.

lev=3 lev=0

lev=1

lev=2 HP

P1

P2

P3

P4

(4)

Zur Laufzeit kann die folgende Aufruf-Reihenfolge der Prozeduren vorkommen:

HP → P1 → P2 → P3 → P3 → P4 → P2

Die Datenbereiche der Prozeduren Pi sind i∗∗∗∗150 Bytes lang (I=1,2,3,4). Der Datenbereich des Hauptprogramms ist 200 Bytes lang und beginnt auf Adresse 1000. Die Datenbereiche werden in der Aufrufreihenfolge im Laufzeitkeller angelegt. Damit beginnt z.B. der Datenbe- reich von P1 an der Adresse 1200.

G Tragen Sie die Anfangsadressen der Datenräume in die unten stehende Skizze ein, entsprechend der obigen Aufrufreihenfolge. tragen Sie außerdem die Adreßwerte der Static Link-Kette (1.Feld im Datenraum) und der Dynamic Link-Kette (2. Feld im Daten- raum) ein.

SL:

DL

SL:

DL

SL:

DL

SL:

DL

SL:

DL

SL:

DL

1000

1200

G Eine Variable V1 werde aus dem Aufruf von P4 heraus mit der Adresse (2,50) = (leveldistanz,offset) angesprochen.

Eine Variable V2 wird von der letzten Aktivierung von P2 aus mit (0,10) angesprochen.

Berechnen Sie die absoluten Adressen der Variablen:

Adresse (V1) = 1400

Adresse (V2) = 3160

1350

DSA(HP)

DSA(P1)

DSA(P2)

DSA(P3)

DSA(P3)

DSA(P4)

DSA(P2)

1000 1000

1000 1200

1350 1350

1350 1650

2100 2100

1000 2550

1650

2100

2550

3150

(5)

G Die folgende Skizze stellt die Display-Vektoren der Datenräume in der selben Situation wie oben dar. tragen Sie die Adreßwerte der Zeiger ein.

0 1 2 3

P1 1000 1200

P2 1000 1350

P3 1000 1350 1650

P3 1000 1350 2100

P4 1000 1350 2100 2550

P2 1000 3150

(6)

4. Aufgabe LR-Analyse

Gegeben ist die folgende, bereits um ein nur einmalig auftretendes Axiom S erweiterte Grammatik :

G = áN,T,P,Sñ mit:

N = { X, A, V } T = { a | b }

ì X → V ü

P = í V → A A ý î A → a A | b þ

a) Die erste LR(0)-Information hat die Form é X → . V ù I0 = ê V → . A A ú

ê A → . a A ú ë A → . b û

Vervollständigen Sie die kanonische Kollektion der LR(0)-Informationen.

Es genügt dazu, die folgenden LR(0)-Informationen zu berechnen:

I1 = GOTO(I0,V), I2 = GOTO(I0,A), I3 = GOTO(I0,a), I4 = GOTO(I0,b), I5 = GOTO(I2,A), I6 = GOTO(I3,A)

b) Geben Sie die Aktions- und GOTO-Tabelle für den zugehörigen SLR(1)-Parser an.

Lösung:

1. Followmengen der Nonterminals bestimmen:

FOLLOW(X) = { $ } FOLLOW(A) = { a, b, $ } FOLLOW(V) = { $ }

2. Kanonische Kollektion bestimmen:

Gegeben ist:

é X → . V ù I0 = ê V → . A A ú ê A → . a A ú ë A → . b û

Die weiteren LR(0)-Infos bestimmt man ausgehend von I0 wie folgt:

I1 = GOTO( I0 , V) = HÜLLE[ X → V. ] = [ X → V. ]

é V → A . A ù I2 = GOTO( I0 , A) = HÜLLE[ V → A.A ] = ê A → . a A ú ë A → . b û é A → a . A ù I3 = GOTO( I0 , a) = HÜLLE[ A → a.A ] = ê A → . a A ú ë A → . b û

(7)

I4 = GOTO( I0 , b) = HÜLLE[ A → b. ] = [ A → b. ] I5 = GOTO( I2 , A) = HÜLLE[ V → AA. ] = [ V → AA. ] I6 = GOTO( I3 , A) = HÜLLE[ A → aA. ] = [ A → aA. ]

Weitere erlaubte Übergänge, die aber keine neuen Zustände liefern sind auch noch:

GOTO( I2 , a) = HÜLLE[ A → a.A ] = I3 GOTO( I2 , b) = HÜLLE[ A → b. ] = I4

GOTO( I3 , a) = HÜLLE[ A → a.A ] = I3 GOTO( I3 , b) = HÜLLE[ A → b. ] = I4

Das Zustandsdiagramm des zugehörigen LR(0)-Automaten ist damit:

Aktionstabelle Sprungtabelle

a b $ X A V

I0 I3 I4 I0 I2 I1

I1 accept I1

I2 I3 I4 I2 I5

I3 I3 I4 I3 I6

I4 A→→→→b A→→→→b A→→→→b I4

I5 V→→→→AA I5

I6 A→→→→aA A→→→→aA A→→→→aA I6

(8)

NewLine Anweisung

5. Aufgabe

Gegeben: Die do-loop-Schleife in Visual-Basic:

do-Anweisung:

Anweisungen:

Anweisung:

Programm-Beispiel

EndeTest = True : Zähler = 0 ' Variablen initialisieren.

do ' Äußere Schleife.

do while Zähler < 20 ' Innere Schleife.

Zähler = Zähler + 1 ' Zähler hochzählen.

if Zähler = 10 then ' Wenn Bedingung erfüllt,

EndeTest = False ' Statusvariable auf False setzen.

exit do ' Innere Schleife verlassen.

end if ' Innere Schleife verlassen.

loop

loop until EndeTest = False ' Äußere Schleife sofort verlassen.

do

while condition

Anweisungen

loop

condition until

exit do

Zuweisung

If-Anweisung

.... <andere Anweisungen> ....

(9)

Aufgabe: Erweitern Sie den PL0-Parser um die Analyse von do-Anweisungen dieses Typs:

Lösung: siehe Dateien scanner.h, pl0Parser.cpp im Unterverzeichnis .\Aufgabe5

Die Funktion Statment(...) ist wie folgt zu erweitern:

case doSym: // now we have while-statement

getSym(); // get next symbol after "while"

if (sym == whileSym) {

getSym();

condition( followSymSet ); // parse the condition }

statement(STAT_START | IDENT | SEMICOLON_END);

// loop over the rest of the statements while ( (sym == semicolon) || (sym==ident)

|| (symType[sym] & STAT_START)) {

if (sym == semicolon) getSym();

else error(10);

statement( followSymSet | SEMICOLON_END );

}

if (sym != loopSym) error(36);

else {

getSym();

if (sym==untilSym) {

getSym();

condition( followSymSet );

} } break;

Referenzen

ÄHNLICHE DOKUMENTE

(1) Sie haben eine E-Mail geöffnet. Nun wollen Sie diese in einem Ordner ablegen. Dazu ist der Button hilfreich. Klicken Sie darauf, öffnet sich ein Fenster mit einer Auswahl

Buzzword-Bingo, in der sp¨ateren Verbreitung auch Bullshit- oder Besprechungs-Bingo genannt, ist eine humoristische Variante des Bingo- Spiels, die die oft inhaltslose Verwendung

Um sicherzustellen, dass die über den E-Mail-Dienst des Landesbildungsservers ver- sandten Informationen zukünftig von allen Schulen eingesehen werden können, ist wie folgt