Skriptums

Werbung
1 Spezifikation formaler Sprachen
1.1 Formale Sprachen
Ein Alphabet ist eine endliche, nicht-leere Menge von atomaren Symbolen, d.h. von Symbolen, die weder eine innere Struktur besitzen noch eine andere Eigenschaften haben als
jene, voneinander unterscheidbar zu sein. Als mathematische Variablen für Alphabete
verwenden wir Σ oder T . Um eindeutig zu kennzeichnen, dass ein Zeichen als Symbol
und nicht als meta-sprachlicher Begriff zu verstehen ist, unterstreichen wir Symbole.
1.1 Beispiel Das Zeichen 0 ist ein Symbol, das wie die Ziffer 0 aussieht, tatsächlich aber
von vorneherein keine Bedeutung besitzt (es sei denn, wir ordnen sie ihm explizit zu).
Ist Σ ein Alphabet, dann entspricht der Ausdruck 0 ∈ Σ der Aussage Das Symbol 0
”
kommt im Alphabet Σ vor“. Die Aussage 0 ∈ Σ ergibt hingegen nur Sinn, wenn Σ kein
Alphabet, sondern etwa eine Menge von Zahlen ist.
Analog ist + ein Symbol, das wie ein Kreuz aussieht, während + in einem mathematischen Kontext die Addition, also eine zweistellige Funktion, bezeichnet. 2+3 ist eine
Abfolge von 3 Symbolen, die nichts mit 5 zu tun hat, während 2 + 3 äquivalent zu 5
ist. Der Ausdruck 2 + 3 wird üblicherweise wenig Sinn haben, da die Addition nicht auf
Zeichen definiert ist.
Wichtig ist auch, zwischen Symbolen und mathematischen Variablen zu unterscheiden.
Der Ausdruck a ∈ Σ entspricht der Aussage Das Symbol a kommt in Σ vor“, während
”
a ∈ Σ der Typdefinition Sei a irgendein Symbol aus Σ“ entspricht.
t
u
”
Ein Wort über einem Alphabet Σ ist eine Folge von Symbolen aus Σ. Das Wort, das
aus gar keinen Zeichen besteht, wird Leerwort genannt. Um dieses unsichtbare“ Wort
”
niederschreiben zu können, verwenden wir das metasprachliche Zeichen ε.
Die Menge aller Wörter über Σ wird mit Σ+ oder, wenn auch das Leerwort ε in der
Menge enthalten ist, mit Σ∗ bezeichnet:
Σ+ = {s1 · · · sn | si ∈ Σ, 1 ≤ i ≤ n}
Σ∗ = Σ+ ∪ {ε}
Wörter können durch den Verkettungsoperator verknüpft werden: w1 · w2 = w1 w2 , d.h.,
das Wort w1 verkettet mit dem Wort w2 ergibt das Wort w1 w2 . Das Leerwort spielt
dabei die Rolle eines neutralen Elementes, d.h., mit einem beliebigen Wort verkettet
ergibt sich wieder dieses Wort: w · ε = ε · w = w. Algebraisch gesehen bildet hΣ∗ , ·, εi
somit ein Monoid (=Halbgruppe mit Einselement), da Σ∗ abgeschlossen bezüglich des
assoziativen Verkettungsoperators ist und ε als neutrales Element fungiert.
1
Zusätzlich definieren wir Potenzen von Worten:
w0 = ε,
wn+1 = w · wn für n ≥ 0 .
Die Länge eines Wortes w, geschrieben als |w|, ist die Anzahl der Symbolvorkommnisse
in w:
|ε| = 0,
|aw| = 1 + |w| für a ∈ Σ, w ∈ Σ∗ .
1.2 Beispiel Sei Σ das Alphabet {a, b}. Dann ist Σ∗ die Menge
{ε, a, b, aa, ab, ba, bb, aaa, aab, aba, . . .}
.
Σ+ ist identisch mit Σ∗ bis auf den Umstand, dass Σ+ das Leerwort ε nicht enthält.
Beispiele zur Verkettung:
ab · ba = abba , ba · ab = baab , ab · ε = ε · ab = ab ,
(ab)0 = ε ,
(ab)1 = ab ,
(ab)2 = abab , (ab)3 = ababab
Die ersten beiden Beispiele zeigen, dass die Verkettung nicht kommutativ ist.
t
u
Unter einer formalen Sprache L über einem Alphabet Σ versteht man eine beliebige
Menge von Wörtern über Σ, d.h., L ⊆ Σ∗ . Die Menge aller Sprachen ist die Menge aller
Teilmengen von Σ∗ , also die Potenzmenge P(Σ∗ ) von Σ∗ .
1.3 Beispiel Beispiele für Sprachen:
– Über den Buchstaben A–Z inklusive Umlauten und Satzzeichen: die Menge aller
grammatikalisch richtigen deutschen Sätze.
– Über dem Ascii-Zeichensatz: die Menge aller C-Programme.
– Über einem beliebigen Alphabet: die Menge aller Palindrome (=Wörter, die von
vorne nach hinten und hinten nach vorne gelesen gleich lauten, wie omo, anna,
otto, reliefpfeiler, . . . ). Längere, aber nicht unbedingt sinnvollere Palindrome sind Vitaler Nebel mit Sinn ist im Leben relativ“ und Satan, oscillate my
”
”
metallic sonatas“.
– Über einem beliebigen Alphabet: die leere Menge; die Menge aller Wörter; die
Menge aller Wörter der Länge 4.
t
u
Der Verkettungsoperator kann von Wörtern auf Sprachen erweitert werden. Seien L1
und L2 zwei Sprachen über Σ, d.h. L1 , L2 ⊆ Σ∗ bzw. L1 , L2 ∈ P(Σ∗ ). Dann definieren
wir die Verkettung von Sprachen als
L1 · L2 = {w1 · w2 | w1 ∈ L1 , w2 ∈ L2 } .
Bei dieser Operation übernimmt {ε} die Funktion des Einheitselementes. Somit bildet
hP(Σ∗ ), ·, {ε}i wieder ein Monoid.
2
Rechengesetz
A∪B = B∪A
A ∪ (B ∪ C) = (A ∪ B) ∪ C
A · (B · C) = (A · B) · C
A · (B ∪ C) = A · B ∪ A · C
(A ∪ B) · C = A · C ∪ B · C
{ε} · A = A
A · {ε} = A
(A ∪ {ε})∗ = A∗
(A∗ )∗ = A∗
A · A∗ = A+
A∗ · A = A+
A+ ∪ {ε} = A∗
Kommentar
Vereinigung ist kommutativ.
Vereinigung ist assoziativ.
Verkettung ist assoziativ.
Verkettung distribuiert über Vereinigung
{ε} ist das Einheitselement bzgl. Verkettung
∗
ist idempotent
Tabelle 1.1: Algebraische Eigenschaften der Sprachoperatoren
Auch die Potenzenbildung lässt sich auf Sprachen erweitern. Ist L eine Sprache, dann
sind ihre Potenzen definiert durch
L0 = {ε},
Ln+1 = L · Ln für n ≥ 0 .
S
Vereinigt man alle Potenzen,
erhält man den Stern-Operator1 L∗ = n≥0 Ln , und analog
S
den Plus-Operator L+ = n≥1 Ln . Ist L ein Alphabet, d.h., bestehen alle Wörter in L
aus nur einem Zeichen, dann ist Ln genau die Menge aller Wörter der Länge n, die mit
den Symbolen in L gebildet werden können. L∗ ist dann die Vereinigung der Wörter aller
Längen, somit die Menge aller Wörter über dem Alphabet L. Wegen L0 = {ε} enthält
L∗ auch das Leerwort. Die Vereinigung in der Definition von L+ hingegen beginnt erst
bei n = 1, somit ist das Leerwort nur dann in L+ , falls es bereits in L war. Tabelle 1.1
gibt einen Überblick über wichtige Rechenregeln für Sprachoperatoren.
1.4 Beispiel Sei Σ = {a, b}. Wir erhalten Σ0 = {ε}, Σ1 = Σ, Σ2 = {aa, ab, ba, bb} und
Σ3 = {aaa, aab, aba, abb, baa, bab, . . .}. Die Menge Σ∗ ist die Vereinigung all dieser
Mengen, somit die Menge aller Wörter über den Symbolen a und b.
t
u
1.2 Induktive Definitionen
Die in der Informatik auftretenden Mengen enthalten zum Teil Elemente komplizierterer Bauart; man denke etwa an die Menge aller syntaktisch korrekten C-Programme.
Eine übliche mathematische Methode zur Definition unendlicher Mengen ist die stufenweise Konstruktion: unter Verwendung einer gegebenen Grundmenge A0 sowie der
1
Nach seinem Erfinder auch Kleene-Stern genannt, gesprochen [’kli:ni].
3
bisher konstruierten Mengen A1 , . . . , Ak baut man nach bestimmten Vorschriften die
nächste Menge Ak+1 auf, die üblicherweise komplizierter als die Vorgängermengen ist.
Die dadurch
insgesamt definierte Menge ist dann die Vereinigung all dieser Mengen:
S
A = i∈ω Ai .
1.5 Beispiel Sei A0 die Menge der Ziffern, also A0 = {0, . . ., 9}. Additive Ausdrücke über
dieser Menge lassen sich stufenweise konstruieren durch:
A1 = A0 ∪ {u+v | u, v ∈ A0 } = {0, . . ., 9, 0+0, 0+1, . . ., 9+9}
A2 = A1 ∪ {u+v | u, v ∈ A1 }
= {0, . . ., 0+0, . . ., 0+0+0, 0+0+1, . . ., 0+0+0+0, . . ., 9+9+9+9}
..
.
Die Menge aller additiven Ausdrücke ergibt sich als
S
i≥0 Ai .
t
u
Stufenweise konstruierte Mengen sind in folgendem Sinn abgeschlossen bezüglich der
Konstruktionsvorschriften.
1.6 Definition Sei B eine Menge und f : B n → B eine Funktion. Eine Menge A ⊆ B heißt
abgeschlossen unter f , wenn gilt: aus x1 , . . . , xn ∈ A folgt f (x1 , . . . , xn ) ∈ A.
1.7 Satz Sei B eine Menge, A0 ⊆ B und f : B n → B. Weiters sei
Ak+1 = Ak ∪ {f (x1 , . . . , xn ) | x1 , . . . , xn ∈ Ak }
und A =
S
k≥0 Ak .
Dann gilt:
(a) A ist abgeschlossen unter f .
(b) Ist A0 irgendeine Teilmenge von B, die A0 enthält und abgeschlossen ist unter f ,
dann ist A Teilmenge von A0 (A ⊆ A0 ).
Beweis
(a) Laut Definition der Abgeschlossenheit müssen wir zeigen, dass f (x1 , . . . , xn ) für
beliebige x1 , . . . , xn ∈ A in A liegt. Auf Grund der Konstruktion der Mengen Ai gilt
Ai ⊆ Ai+1 für alle i ≥ 0. Daher muss es ein k geben, sodass x1 , . . . , xn allesamt in
Ak liegen. Daraus folgt aber f (x1 , . . . , xn ) ∈ Ak+1 . Die Menge A ist die Vereinigung
aller Ak , enthält also auch die Elemente von Ak+1 , insbesondere f (x1 , . . . , xn ).
(b) Um zu zeigen, dass A Teilmenge von A0 ist, beweisen wir mittels vollständiger
Induktion, dass Ak Teilmenge von A0 ist für alle k ≥ 0. Offenbar gilt dann auch
A ⊆ A0 , da A die Vereinigung aller Ak ist.
Induktionsanfang: A0 ist laut Voraussetzung des Satzes in A0 .
Induktionshypothese: Ak ist Teilmenge von A0 .
4
Induktionsschritt: Wir müssen zeigen, dass auch Ak+1 ⊆ A0 gilt. Laut Definition
gilt Ak+1 = Ak ∪ {f (x1 , . . . , xn ) | x1 , . . . , xn ∈ Ak }. Wegen der Induktionshypothese können wir Ak ⊆ A0 annehmen, es bleibt zu beweisen, dass {f (x1 , . . . , xn ) |
x1 , . . . , xn ∈ Ak } ⊆ A0 gilt. Dies folgt aber aus der Induktionshypothese und der
Abgeschlossenheit von A0 bezüglich f : da x1 , . . . , xn in Ak und damit in A0 liegen,
muss auch f (x1 , . . . , xn ) in A0 liegen.
t
u
In anderen Worten: A ist die kleinste Menge, die A0 enthält und abgeschlossen ist unter f .
Um A kompakt und eindeutig zu definieren, kann daher folgendes Schema verwendet
werden.
Schema der induktiven Definition A ist die kleinste Menge, für die gilt:
(a) A0 ⊆ A
(b) Wenn x1 , . . . , xn ∈ A, dann f (x1 , . . . , xn ) ∈ A.
Induktive Definitionen bestehen somit aus drei wesentlichen Komponenten: einer Grundmenge, einer Abschlusseigenschaft und einer Minimalitätsbedingung ( . . . ist kleinste
”
Menge, für die gilt . . .“).
1.8 Beispiel Die in Beispiel 1.5 stufenweise konstruierte Menge lässt sich induktiv definieren
als die kleinste Menge A, für die gilt:
(a) {0, 1, . . ., 9} ⊆ A
(b) Wenn x, y ∈ A, dann auch x+y ∈ A.
t
u
1.9 Beispiel Die geraden Zahlen können induktiv definiert werden als die kleinste Menge,
für die gilt:
(a) Grundelement: 0 ist eine gerade Zahl.
(b) Abschlusseigenschaft: Ist n eine gerade Zahl, dann ist auch n + 2 eine solche.
Jede der drei Bedingungen ist notwendig, um die geraden Zahlen eindeutig festzulegen.
Ohne der Minimalitätsbedingung etwa käme auch die Menge aller natürlichen Zahlen in
Frage, da 0 eine natürliche Zahl ist und die natürlichen Zahlen abgeschlossen unter der
Funktion +2“ sind. Allerdings ist sie nicht die kleinste Menge mit diesen Eigenschaften,
”
da die geraden Zahlen eine echte Teilmenge bilden. Die erste Bedingung hingegen scheidet
die ungeraden Zahlen als Kandidat aus.
Die induktive Definition kann gemäß Satz 1.7 auch benützt werden, um die geraden
Zahlen stufenweise zu konstruieren:
A0 = {0}
A1 = A0 ∪ {n + 2 | n ∈ A0 } = {0} ∪ {2} = {0, 2}
A2 = A1 ∪ {n + 2 | n ∈ A1 } = {0, 2} ∪ {2, 4} = {0, 2, 4}
A3 = A2 ∪ {n + 2 | n ∈ A2 } = {0, 2, 4} ∪ {2, 4, 6} = {0, 2, 4, 6}
..
.
5
t
u
1.3 Reguläre Sprachen
Eine der einfachsten Sprachklassen ist die Menge der regulären Sprachen. Reguläre Sprachen können auf mehrere gleichwertige Arten definiert werden: als reguläre Mengen, als
die von endlichen Automaten akzeptierte Sprachfamilie, als die Menge der von regulären
Grammatiken erzeugten Sprachen usw. Wegen ihrer Einfachheit und der damit verbundenen guten Eigenschaften treten reguläre Sprachen in der Informatik häufig auf.
In der ersten Phase eines Compilerlaufes, der sogenannten lexikalischen Analyse, wird
das Benutzerprogramm in eine Folge von Token umgewandelt; der entsprechende Programmteil des Compilers wird als Scanner oder Lexer bezeichnet. Der Lexer fasst alle
Zeichen, die zu einem Schlüsselwort, einem Bezeichner, einem Operator oder einer Zahl
gehören, zusammen und wandelt sie in eine interne Darstellung um. Die Menge aller
Wörter, die jeweils ein Token bilden – alle Schlüsselwörter, Bezeichner, Zahlendarstellungen – bilden eine reguläre Sprache. Diese reguläre Sprache lässt sich mittels regulärer
Ausdrücke (siehe unten) beschreiben. Es gibt Programme, sogenannte Scannergeneratoren, die aus dieser Beschreibung automatisch einen passenden Scanner erzeugen können,
der dann als Teil eines Compilers genau diese reguläre Sprache in Token umwandelt;
bekannte Scannergeneratoren unter Unix sind etwa lex und flex.
Ein anderes Anwendungsgebiet sind Texteditoren. Fortgeschrittene Editoren erlauben
nicht nur das Suchen fester Zeichenketten in einem Text, sondern ermöglichen die Angabe
von Mustern, mit denen alle Zeichenketten gesucht werden können, die in der durch das
Muster spezifizierten Sprache liegen. Beispiele für solche Editoren sind vi und emacs
unter Unix oder auch der Norton Desktop-Editor. Etwa kann man im vi mit dem
Muster [0-9][0-9]* alle ganzen Zahlen im Text auffinden.
Weiters gibt es zahlreiche Programme, insbesondere unter Unix, die die Spezifikation
von (Teilmengen von) regulären Sprachen zulassen. Dies beginnt bei Kommandointerpretern wie Dos oder Unix-Shells, die bei der Selektion von Dateien Ausdrücke mit
Wildcards“ zulassen, und geht bis zu Programmen wie egrep oder awk, die beliebige
”
reguläre Ausdrücke akzeptieren. Darüber hinaus bilden reguläre Ausdrücke ein wesentliches Element von Programmiersprachen wie Perl, die zur Analyse und Erzeugung von
Textdateien (etwa von Html-Seiten) eingesetzt werden.
Sucht man auf dem Server des World Wide Web Consortiums (W3C) nach den Spezifikationen der Websprachen, stößt man auf einen Formalismus, der ausgiebig von regulären
Ausdrücken Gebrauch macht. In der Xml-Spezifikation treten reguläre Ausdrücke sogar
auf zwei Ebenen auf: einmal objektsprachlich als Teil von Document Type Definitions
(Dtds), und einmal metasprachlich zur Beschreibung der Syntax von Xml (und damit
auch jener von Dtds).
In den folgenden Abschnitten definieren wir die regulären Sprachen als reguläre Mengen und beschreiben verschiedene Formalismen und Notationen zur Festlegung regulärer
Mengen.
6
1.3.1 Reguläre Mengen
Reguläre Mengen sind nichts anderes als alle Sprachen, die aus einem Alphabet mittels
der in Abschnitt 1.1 definierten Operationen Vereinigung, Verkettung und Kleene-Stern
gebildet werden können.
1.10 Definition Die Menge Lreg (Σ) der regulären Sprachen über Σ ist die kleinste Menge,
für die gilt:
(a) {}, {ε} ∈ Lreg (Σ);
{s} ∈ Lreg (Σ) für alle s ∈ Σ;
(b) Wenn A, B ∈ Lreg (Σ), dann gilt auch A ∪ B, A · B, A∗ ∈ Lreg (Σ), d.h., Lreg (Σ) ist
abgeschlossen gegenüber Vereinigung, Verkettung und Kleene-Stern.
Offensichtlich ist Lreg auch gegenüber dem
X + kann ja durch X · X ∗ ersetzt werden.
+ -Operator
abgeschlossen: jeder Ausdruck
1.11 Beispiel Die Menge der Real-Zahlen in Modula ist eine reguläre Menge über dem Alphabet {0, . . ., 9, ., E, +, -}:
– Laut erstem Punkt von Definition 1.10 sind die Mengen {ε}, {0}, . . . , {9}, {.},
{E}, {+} und {-} regulär.
– Da die Vereinigung regulärer Mengen wieder regulär ist, ist auch digit = {0, . . ., 9}
regulär.
– Die Menge {E, E+, E-} ist regulär, da sie mittels Verkettung und Vereinigung aufgebaut werden kann: {E} ∪ {E} · {+} ∪ {E} · {-}.
– Aus der Abgeschlossenheit bzgl. Plus- und Sternoperator folgt, dass auch digit +
und digit ∗ regulär sind.
Daraus lässt sich nun die Menge der Real-Zahlen zusammensetzen:
real
= digit + · {.} · digit ∗ · ({ε} ∪ {E, E+, E-} · digit + ) .
Eine Realzahl beginnt demnach mit einer Folge von Ziffern (mindestens einer), gefolgt
von einem Punkt und weiteren optionalen Ziffern. Danach kann ein Exponentialteil folgen, der aus dem Symbol E, einem optionalen Vorzeichen und mindestens einer Ziffer
bestehen muss.
t
u
1.12 Beispiel Wir konstruieren einige der regulären Sprachen in Lreg ({a}) gemäß Satz 1.7.
Im ersten Schritt erhalten wir alle Sprachen, die laut Punkt 1 der induktiven Definition
von Lreg reguläre Mengen sind:
A0 = {{}, {ε}, {a}} .
7
Im nächsten Schritt kommen alle Sprachen hinzu, die aus A0 mittels Vereinigung, Verkettung und Stern-Operator gebildet werden können:
A1 = A0 ∪ {{ε, a}, {aa}, {an | n ≥ 0}} .
Durch Vereinigung von Elementen aus A1 ergeben sich drei neue Mengen: {ε, aa}, {a, aa}
und {ε, a, aa}. Durch Verkettung erhalten wir sechs neue Mengen, darunter etwa {ε, a} ·
{aa} = {aa, aaa} und {aa} · {an | n ≥ 0} = {an | n ≥ 2}. Der Stern-Operator liefert
nur auf {aa} angewendet eine neue Sprache: {aa}∗ = {a2n | n ≥ 0}. Insgesamt ergibt
sich:
A2 = A1 ∪ {
{ε, aa}, {a, aa}, {ε, a, aa}, {aa, a3 }, {a3 }, {a4 },
{an | n ≥ 1}, {an | n ≥ 2}, {a2n | n ≥ 0} } .
In A3 alleine durch die Vereinigung 19 neue Sprachen hinzu.
t
u
1.3.2 Reguläre Ausdrücke
Um reguläre Sprachen spezifizieren zu können, muss eine geeignete Notation festgelegt werden. Abhängig von den historischen Wurzeln und den Anforderungen – wie
der Verständlichkeit für Nicht-Formalisten, der Ausdrückbarkeit im Ascii-Zeichensatz
oder der einfachen algebraischen Handhabbarkeit – wurden verschiedene Varianten eingeführt, die sich direkt ineinander übersetzen lassen. Tabelle 1.2 gibt eine Übersicht,
wobei A für die Bezeichnung einer Untersprache, s für ein Symbol und X bzw. Y für
einen Teilausdruck im jeweiligen Formalismus steht.
Algebraische Notation
Aufgrund der Monoid-Eigenschaften der Sprachenverkettung orientiert sich die algebraische Notation an der Addition und verwendet + für die Mengenvereinigung und ∅ für
das neutrale Elemente {}. Die Elementarsprachen {ε} und {s} (für s ∈ Σ) werden ohne Mengenklammern geschrieben, und Verkettung wird durch Nebeneinanderschreiben
ausgedrückt. Um Klammern zu sparen, ordnet man ∗ die höchste und der Vereinigung
die niedrigste Priorität zu. Formal lässt sich die Sprache L(e), die durch einen regulären
Ausdruck e in algebraischer Notation spezifiziert wird, definieren als:
L(0) = {}
L(ε) = {ε}
L(s) = {s}
L(e1 e2 ) = L(e1 ) · L(e2 )
L(e1 + e2 ) = L(e1 ) ∪ L(e2 )
L(e∗ ) = L(e)∗
wobei s ∈ Σ ein Symbol und e, e1 , e2 reguläre Ausdrücke sind.
1.13 Beispiel Die Realzahlen aus Beispiel 1.11 lassen sich darstellen als
digit digit ∗ . digit ∗ (ε + (E + E + + E -) digit digit ∗ )
wobei digit eine Abkürzung für den Ausdruck (0 + 1 + · · · + 9) ist.
8
t
u
reg. Menge
Algebra
Ebnf
Syntaxdiagramm
Kommentar
A
A
A
A
Untersprache
{}
0
{ε}
ε
{s}
s
"s"
X ·Y
XY
XY
Leersprache
X ∪Y
X +Y
X |Y
{ε} ∪ X
ε+X
[X ]
X∗
X∗
{X }
X+
XX ∗
X {X }
(X)
(X)
(X )
s
-X -Y -
Leerwort-Sprache
Terminalsymbole
Aufeinanderfolge
-X
-Y
Alternativen
-X
X
Option
Wiederholung ≥ 0
-X
Wiederholung ≥ 1
Gruppierung
Tabelle 1.2: Verschiedene Notationen für reguläre Ausdrücke
EBNF
Die Syntax der Programmiersprache Modula-2 im Anhang des Buches Programming in
Modula-2 von N. Wirth wird durch Regeln in erweiterter Backus-Naur Form (EBNF)
beschrieben. Eine EBNF ist nichts anderes als eine kontextfreie Grammatik (siehe später
in der Vorlesung) erweitert um reguläre Ausdrücke.
1.14 Beispiel In dem erwähnten Buch wird die Syntax der Realzahlen spezifiziert durch
real = digit {digit} "." {digit} [ScaleFactor]
ScaleFactor = "E" ["+"|"-"] digit {digit}
digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
Diese Regeln lassen sich gemäß Tabelle 1.2 in reguläre Mengen übersetzen:
real
ScaleFactor
digit
= digit · digit ∗ · {.} · digit ∗ · ({ε} ∪ ScaleFactor )
= {E} · ({ε} ∪ {+} ∪ {-}) · digit · digit ∗
= {0} ∪ {1} ∪ · · · ∪ {9}
Vereinfacht man die rechten Seiten, erhält man den gleichen Ausdruck für real wie in
Beispiel 1.11.
u
t
9
real
- digit
digit - .
- ScaleFactor
ScaleFactor
- +
- E
- digit
- digit - 0
- 1
..
.
..
.
..
.
- 9
Abbildung 1.3: Syntaxdiagramme für die Realzahlen in Modula
Syntaxdiagramme
Zur Beschreibung der Syntax von Pascal und Modula führte N. Wirth Syntaxdiagramme ein, die nichts anderes als eine graphische Darstellung regulärer Ausdrücke in EBNF
sind. Die zu einem Syntaxdiagramm gehörende Sprache erhält man, indem man den Graphen in Richtung der Pfeile durchläuft und alle angetroffen Terminalsymbole aneinander
reiht. Ein Rechteck mit dem Namen eines anderen Syntaxdiagrammes entspricht dabei
einem Unterdiagrammaufruf“: an Stelle des Rechtecks wird das angegebene Syntaxdia”
gramm durchlaufen und anschließend im ursprünglichen Diagramm nach dem Rechteck
fortgesetzt.
1.15 Beispiel Die Syntaxdiagramme in Abb. 1.3 beschreiben (wieder einmal) die Syntax der
Realzahlen in Modula.
t
u
Reguläre Ausdrücke unter Unix
Viele Standardprogramme in Unix erlauben als Eingabe reguläre Ausdrücke. Beispiele
dafür sind Editoren wie emacs, vi, ex und sed, Kommandos wie awk oder egrep, und
Scannergeneratoren wie lex. Die Schreibweise der regulären Ausdrücke ist bei all diesen
Kommandos ähnlich (leider aber nicht identisch2 ). Stellvertretend betrachten wir die
regulären Ausdrücke, wie sie von egrep akzeptiert werden. Das Kommando
egrep ’hreg. Ausdruck i’ hTextdatei i
sucht aus hTextdatei i alle Zeilen heraus, die eine Zeichenkette enthalten, welche in der
durch hreg. Ausdruck i definierten regulären Sprache liegt. Tabelle 1.4 fasst die wichtigsten Ausdruckselemente zusammen.
2
Der Mathematiker und Informatiker D.E. Knuth – auch bekannt als Schöpfer des Textsystems TEX,
das zum Setzen dieses Skriptums verwendet wurde – definiert Unix als 30 definitions of regular
”
expressions living under one roof“.
10
Ausdruck
s
\s
.
^
selektiert
Einzelzeichen s, falls kein
Spezialsymbol
Einzelzeichen s (auch wenn
Spezialsymbol)
jedes beliebige Zeichen außer Zeilenende
Zeilenanfang
$
[s1 · · · sn ]
Zeilenende
alle Zeichen in {s1 , . . ., sn }
[^s1 · · · sn ]
alle Zeichen, die nicht in
{s1 , . . ., sn } vorkommen
null oder mehr Vorkommnisse von r
r*
r+
ein oder mehr Vorkommnisse von r
r?
ein oder kein Vorkommnis
von r
r{i}
i Vorkommnisse von r
r{i,}
r{i,j}
r1 r2
i oder mehr Vorkommnisse
von r
i bis j Vorkommnisse von r
r1 gefolgt von r2
r1 |r2
r1 oder r2
(r)
r
Beispiel
a selektiert alle Zeilen, die a enthalten
a\.b selektiert alle Zeilen mit der Zeichenfolge a.b
a.b selektiert alle Zeilen, die entweder
aab oder abb oder acb oder . . . enthalten
^a selektiert alle Zeilen, die mit a beginnen
a$ selektiert alle Zeilen, die mit a enden
[ab] selektiert alle Zeilen, die a oder b
enthalten
[^ab] selektiert alle Zeilen, die nicht
nur aus a’s und b’s bestehen
a.*a selektiert alle Zeilen, die zwei
durch beliebig viele (auch null) Zeichen
getrennte a’s enthalten
a.+a selektiert alle Zeilen, die zwei
durch beliebig viele (aber mind. ein)
Zeichen getrennte a’s enthalten
a.?a selektiert alle Zeilen, die zwei
durch null oder ein Zeichen getrennte
a’s enthalten
a.{4}a selektiert alle Zeilen, die zwei
durch genau vier Zeichen getrennte a’s
enthalten
a{0,} ist gleichbedeutend mit a* und
a{1,} mit a+
a{0,1} ist gleichbedeutend mit a?
ab selektiert alle Zeilen, die ein a unmittelbar gefolgt von b enthalten
a|b selektiert alle Zeilen, die a oder b
enthalten
(a|b) ist gleichbedeutend mit [ab]
Tabelle 1.4: Reguläre Ausdrücke des Kommandos egrep
11
1.16 Beispiel Um alle Zeilen zu erhalten, die genau eine Realzahl in Modula-Syntax (und
sonst nichts) enthalten, muss egrep mit dem regulären Ausdruck
^[0-9]+\.[0-9]*(E[+-]?[0-9]+)?$
t
u
aufgerufen werden.
Reguläre Definitionen
Hinter dem Begriff der regulären Definition verbirgt sich nichts anderes als die Verwendung von Abkürzungen für reguläre Teilausdrücke. In den vorangegangenen Beispielen
wurde bereits stillschweigend davon Gebrauch gemacht. So verwenden die meisten regulären Ausdrücke für die Realzahlen (inklusive der Syntaxdiagramme) neben real auch
noch ScaleFactor und digit. Reguläre Definitionen erhöhen nicht die Ausdruckskraft regulärer Ausdrücke: sie können ja durch Ersetzung der linken durch die rechten Seiten
jederzeit eliminiert werden. Ihr Nutzen liegt in der besseren Strukturierung und damit
der besseren Lesbarkeit der regulären Ausdrücke.
Die einzige Einschränkung bei der Verwendung regulärer Definitionen besteht darin,
dass keine (direkten oder indirekten) Rekursionen entstehen dürfen. eine Definition wie
digits = digit · digits ∪ {ε}
ist nicht zulässig, da digits in seiner eigenen Definition (der rechten Seite Der Gleichung)
vorkommt.
12
Herunterladen