Automaten und formale Sprachen 14 Abschlusseigenschaften und

Werbung
Automaten und formale Sprachen
Notizen zu den Folien
14
Abschlusseigenschaften und Algorithmen kontextfreier
Sprachen
Kellerautomaten mit Endzuständen (Folie 272)
Satz. Eine Sprache wird genau dann von einem Kellerautomaten mit Endzuständen akzeptiert,
wenn sie von einem Kellerautomaten (ohne Endzustände) akzeptiert wird.
Hinweise warum dieser Satz gilt:
⇒ Wir wandeln einen Kellerautomaten mit Endzuständen in einen gewöhnlichen Kellerautomaten
um, indem wir einen neuen Akzeptanzzustand hinzufügen, in dem den Keller abgebaut wird. Der
Akzeptanzzustand kann über -Übergänge aus allen ursprünglichen Endzuständen erreicht werden.
⇐ Wir wandeln einen Kellerautomaten in einen Kellerautomaten mit Endzuständen um, indem
wir einen Endzustand zE hinzufügen und für jeden Übergang in dem das Kellerbodenzeichen
entfernt wird, stattdessen in den neuen Endzustand führen. (Dies funktioniert nur, wenn das
Kellerbodenzeichen immer als letztes entfernt wird und niemals auf den Keller gepusht wird. Wir
können immer einen solchen Kellerautomaten konstruieren.)
Abschluss unter Vereinigung (Folie 275)
Die kontextfreien Sprachen sind abgeschlossen unter Vereinigung.
Warum ist das der Fall?
Seien zwei Grammatiken G1 = (V1 , Σ, P1 , S1 ) und G2 = (V2 , Σ, P2 , S2 ) über demselben Alphabet
gegeben. Wir können davon ausgehen, dass die Variablen der zwei Grammatiken disjunkt sind
(das heißt, es gibt keine Variable, die sowohl Element von V1 als auch Element von V2 ist), denn
wenn dies nicht der Fall wäre, könnten wir die Variablen einer Grammatik einfach umbenennen.
Wir können nun eine Grammatik G mit L(G) = L(G1 ) ∪ L(G2 ) konstruieren, indem wir eine neue
Startvariable S (die nicht in einer der Grammatiken G1 oder G2 vorkommt) hinzufügen und die
folgenden zwei Produktionen aufnehmen:
S → S1
S → S2
Wenn wir ein Wort aus S ableiten wollen, können wir S durch S1 oder S2 ersetzen. Je nachdem
welche Wahl wir getroffen haben, können wir das Wort nun in G1 oder G2 ableiten. Es ist also
klar, dass L(G) = L(G1 ) ∪ L(G2 ).
Abschluss unter Produkt (Folie 276)
Die kontextfreien Sprachen sind abgeschlossen unter Produkt.
Warum is das der Fall?
Seien zwei Grammatiken G1 = (V1 , Σ, P1 , S1 ) und G2 = (V2 , Σ, P2 , S2 ) über demselben Alphabet
gegeben. Wir gehen wieder davon aus, dass die zwei Grammatiken keine Variablen gemein haben.
Wir können nun eine Grammatik G mit L(G) = L(G1 )L(G2 ) konstruieren, indem wir eine neue
Startvariable S (die nicht in einer der Grammatiken G1 oder G2 vorkommt) hinzufügen und die
folgende Produktion aufnehmen:
S → S1 S2
1
Wenn wir versuchen ein Wort aus S abzuleiten, müssen wir im ersten Schritt S1 S2 ableiten. Aus
S1 wird ein Wort w1 ∈ L(G1 ) abgeleitet und aus S2 ein Wort w2 ∈ L(G2 ). Die Sprache L(G)
besteht also aus der Konkatenation von Wörtern aus S1 und S2 .
Abschluss unter der Stern-Operation (Folie 277)
Die kontextfreien Sprachen sind abgeschlossen unter der Stern-Operation.
Warum is das der Fall?
Sei eine Grammatik G1 = (V1 , Σ, P1 , S1 ) gegeben.
Wir können nun eine Grammatik G mit L(G) = L(G1 )∗ konstruieren, indem wir eine neue Startvariable S (die nicht in der der Grammatik G1 vorkommt) hinzufügen und die folgenden Produktionen aufnehmen:
S → S1 S | Mit den neuen Produktionen können wir eine Folge von S1 belieber Länge ableiten. Jedes abgeleitete S1 kann jetzt durch einem Wort der Sprache L(G1 ) ersetzt werden. Es ist also klar, dass
L(G) = L(G1 )∗ .
Beispiel Kreuzproduktkonstruktion NFA/Kellerautomat (Folie 279,280)
Sei Σ = {<, >}.
Sei M der folgende Kellerautomat (mit Endzuständen): M = ({z0 , zE }, Σ, {A, #}, δM , z0 , {zE }),
wobei δM gegeben ist durch:
δM (z0 , <, #) 3 (z0 , A#)
δM (z0 , <, A) 3 (z0 , AA)
δM (z0 , >, A) 3 (z0 , )
δM (z0 , , #) 3 (zE , #)
M akzeptiert die Sprache korrekt geklammerter Ausdrücke.
Sei A der folgende (nichtdeterministische) endliche Automat: A = ({z1 , z2 }, Σ, δA , z1 , {z2 }), wobei
δA gegeben ist durch:
δ(z1 , <) = {z1 }
δ(z1 , >) = {z2 }
δ(z2 , <) = ∅
δ(z2 , >) = {z2 }
A kann folgendermaßen grafisch dargestellt werden:
>
z1
<
z2
>
A akzeptiert die Sprache L((<)∗ (>)∗ ).
Der folgende Kellerautomat akzeptiert die Sprache N (M ) ∩ T (A):
M 0 = (Z, Σ, Γ, δ, (z0 , z1 ), #, E)
wobei
2
• Z = {z0 , zE } × {z1 , z2 } = {(z0 , z1 ), (z0 , z2 ), (zE , z1 ), (zE , z2 )}
• E = {zE } × {z1 , z2 } = {(zE , z1 ), (zE , z2 )}
und δ wie folgt definiert ist:
δ((z0 , z1 ), <, #) 3 ((z0 , z1 ), A#)
δ((z0 , z1 ), <, A) 3 ((z0 , z1 ), AA)
δ((z0 , z1 ), >, A) 3 ((z0 , z2 ), )
δ((z0 , z1 ), , #) 3 ((zE , z1 ), #)
δ((z0 , z2 ), , #) 3 ((zE , z2 ), #)
Durch scharfes hingucken erkennen wir, dass M 0 die Sprache
N (M 0 ) = {<n >n | n ≥ 0} = N (M ) ∩ T (A)
akzeptiert.
Zu Folie 275
Ein Problem ist entscheidbar, falls es einen Algorithmus gibt, der es löst.
Wie bei den Algorithmen regulärer Sprachen, nehmen wir in allen Fällen an, dass (kontextfreie)
Sprachen in der Form einer Grammatik oder eines Kellerautomaten angegeben werden.
15
Erzeugen eines Parsers mit JavaCC
Zu Folien 299–300
In der Praxis wird einen anderen Syntax verwendet (Nichtterminale werden in Spitzenklammern
eingeschlossen, Terminale in Anführungszeichen und statt →“ wird ::=“ oder =“ geschrieben);
”
”
”
wir benutzen heute aber den Syntax, den wir im Rest der Vorlesung schon benutzt haben.
Zu Folie 301
Beispiele von Ausdrücke, die von der EBNF-Grammatik akzeptiert werden:
(2+5)/2
((2+5)/2)*34
Zu Folie 302
JavaCC erzeugt eine Klasse, die den Parser implementiert. Name ist der Name der zu erzeugenden
Klasse.
3
JavaCC anrufen
In UNIX-ähnliche Betriebssysteme (Linux, Mac OS X, . . . ):
$javacc Arith.jj
Java Compiler Compiler Version 5.0 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file Arith.jj . . .
File "TokenMgrError.java" does not exist. Will create one.
File "ParseException.java" does not exist. Will create one.
File "Token.java" does not exist. Will create one.
File "SimpleCharStream.java" does not exist. Will create one.
Parser generated successfully.
$javac Arith.java
$java Arith
(2+5)/2
(Eingabe-Ende wird angegeben mit Strg-D.)
In der Windows Kommandozeile:
F:\Parser\>javacc Arith.jj
Java Compiler Compiler Version 5.0 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file Arith.jj . . .
File "TokenMgrError.java" does not exist. Will create one.
File "ParseException.java" does not exist. Will create one.
File "Token.java" does not exist. Will create one.
File "SimpleCharStream.java" does not exist. Will create one.
Parser generated successfully.
F:\Parser\>javac Arith.java
F:\Parser\>java Arith
(2+5)/2
(Eingabe-Ende wird angegeben mit Strg-Z.)
4
Herunterladen