Compilerbauhome Compilerbau: Ableitung regulärer Ausdrücke Prof. Dr. Uwe Schmidt FH Wedel

Ableitung regulärer Ausdrücke

weiter

weiter

Ableitungen Regulärer Mengen

Idee
uralt
Janusz A. Brzozowski, Princeton Univ.
1964
weiter
Ziel
Operationalisierung der Auswertung von regulären Ausdrücken (regulären Mengen)
weiter
Reguläre Ausdrücke direkt verarbeiten
ohne eine Transformation in DFAs.
weiter
Weitere Mengenoperationen: Durchschnitt, Komplement, Differenz, exklusives Oder
möglich: Alle Booleschen Funktionen
weiter
Vorgehen
1.Schritt
Definition einer Funktion δ zum Testen,
ob das leere Wort ε in einer regulären Menge r enthalten ist
und konstruktive Berechungsvorschrift für δ
2.Schritt
Definition einer Funktion Δ zur Ableitung einer regulären Menge nach einem Wort
und konstruktive Berechungsvorschrift für Δ
3.Schritt
Entwicklung einer Funktion, die berechnet ob ein Wort w in einer regulären Menge r enthalten ist.
weiter
Definition von δ
Für alle r ∈ R (dem Bereich der regulären Mengen über einem Alphabet A) gilt
δ(r) = {ε}, falls ε ∈ r
δ(r) = {}, falls ε ∉ r
äquivalente Definition
δ(r) = r ∩ {ε}
weiter
Berechnung von δ
1.
δ({}) = {}
2.
δ({ε}) = {ε}
3.
δ({a}) = {} für alle a ∈ A
4.
δ(r*) = {ε}
5.
δ(r1 ⋅ r2) = δ(r1) ∩ δ(r2)
6.
δ(r1 ∪ r2) = δ(r1) ∪ δ(r2)
weiter
Definition von Δ
Für alle r ∈ R und alle a ∈ A gilt:
Δa(r) = {t | a ⋅t ∈ r}
weiter
Erweiterung von Δ
auf Wörter
 
Für alle r ∈ R und alle w ∈ A* gilt:
Δw(r) = {t | w ⋅t ∈ r}
weiter
weiter
Berechnung von Δ
1.
Δa({}) = {}
2.
Δa({ε}) = {}
3.
Δa({a}) = {ε}
4.
Δa({b}) = {} für alle b ∈ A mit b ≠ a
5.
Δa(r*) = Δa(r) ⋅ r*
6.
Δa(r1 ⋅ r2) = Δa(r1) ⋅ r2 ∪ δ(r1) ⋅ Δa(r2)
7.
Δa(r1 ∪ r2) = Δa(r1) ∪ Δa(r2)
weiter
Folgerung
Die Ableitung einer regulären Menge ist wieder eine reguläre Menge
Folgerung
Der Algorithmus ist auf natürliche Weise erweiterbar von Zeichen a ∈ A auf Wörter w ∈ A*
Δε(r) = r
Δaw(r) = Δwa(r)) für a ∈ A, w ∈ A*
weiter

weiter

Implementierung

Repräsentation
der regulären Mengen durch Ausdrücke
 
data RE a = Zero                -- {}
          | Unit                -- {ε}
          | Sym   a             -- {a}
          | Star  (RE a)        -- r*
          | Seq   (RE a) (RE a) -- r1 . r2
          | Union (RE a) (RE a) -- r1 | r2
weiter
Beispiele
A = {0,1}
type BinRE = RE Bool
weiter
A = Char
type RegEx = RE Char
weiter
Implementierung von δ
mit Hilfe eines Prädikates nullable
 
nullable              :: RE a -> Bool
 
nullable Zero          = False
nullable Unit          = True
nullable (Sym x)       = False
nullable (Star r)      = True
nullable (Seq r1 r2)   = nullable r1
                         && nullable r2
nullable (Union r1 r2) = nullable r1
                         || nullable r2
weiter
Implementierung von Δ
delta :: Eq a => RE a -> a -> RE a
 
delta Zero x    = Zero
 
delta Unit x    = Zero
 
delta (Sym y) x
  | x == y      = Unit
  | otherwise   = Zero
 
delta (Star r) x
                = Seq
                  (delta r x)
                  (Star r)
delta (Seq r1 r2) x
  | nullable r1 = Union dr1 dr2
  | otherwise   = dr1
    where
    dr1 = Seq (delta r1 x) r2
    dr2 = delta r2 x
 
delta (Union r1 r2) x
                = Union
                  (delta r1 x)
                  (delta r2 x)
weiter
Erweiterung von Δ
auf Wörter
 
delta' :: Eq a => RE a -> [a]-> RE a
 
delta' re []    = re
delta' re (x:w) = delta' (delta re x) w
Worttest
match :: Eq a => RE a -> [a]-> Bool
 
match re w = nullable (delta' re w)

weiter

Erweiterungen

Offene Fragen
?
Praxisrelevanz, Anwendungen?
?
Laufzeit- und Speicherplatzeffizienz?
?
Erweiterbarkeit
weiter
Effizienz
schlecht
Sequenz und * vergrößern die Ausdrücke
schlecht
Im schlimmsten Fall exponentielles Wachstum in Abhängigkeit von der Wortlänge, der Anzahl der Ableitungen
schlecht
Unpraktikabel
weiter
Ausweg, Verbesserung
beim Konstruieren der Ausdrücke in Δ partiell auswerten und vereinfachen
Gesetzte
zur Vereinfachung
r ∪ {} = r
{} ∪ r = r
r ∪ r = r
r1 ∪ r2 = r2 ∪ r1
(r1 ∪ r2) ∪ r3 = r1 ∪ (r2 ∪ r3)
r ⋅ {} = {}
{} ⋅ r = {}
r ⋅ {ε} = r
{ε} ⋅ r = r
weiter
Umsetzung
durch "intelligente" Konstruktoren
Beispiel: r1 ∪ r2
union :: Eq a => RE a -> RE a -> RE a
 
union r1 Zero = r1
 
union Zero r2 = r2
 
union r1 r2
  | r1 == r2  = r1
  | otherwise = Union r1 r2
Beispiel: r1 ⋅ r2
analog
gut
Platzbedarf bleibt (fast immer) beschränkt, hängt nicht mehr von der Eingabe ab
gut
Laufzeit für δ und Δ bleibt (fast immer) beschränkt, hängt nicht mehr von der Eingabe ab
schlecht
Es gibt worst-case-Fälle, bei denen der abgeleitete reguläre Ausdruck extrem wächst.
Beispiel
r=a?{n}a{n}
Allgemein
Der Ausdruck besteht aus einer Sequenz von R.E.s, die alle das leere Wort enthalten.
weiter
Erweiterbarkeit
um Mengendurchschnitt, Differenz, Komplement, exklusives Oder
gut
Sehr einfach umzusetzen
Beispiel: r1 ∩ r2
Datenstruktur
data RE a = ...
          | Intersect (RE a) (RE a)
          | ...
δ
nullable (Intersec r1 r2) = nullable r1
                            && nullable r2
Δ
delta (Intersect r1 r2) a
                = Intersect
                  (delta r1 a)
                  (delta r2 a)
Vereinfachung
intersect :: Eq a => RE a -> RE a -> RE a
 
intersect r1 Zero = Zero
intersect Zero r2 = Zero
 
intersect r1 Unit = Unit
intersect Unit r2 = Unit
 
intersect r1 r2
  | r1 == r2  = r1
  | otherwise = Intersect r1 r2
gut
analog für Differenz, Komplement, ...
Praxisrelevanz, Anwendungen
?
für grep, sed, perl, lex, ...
shortest match
reguläre Ausdrücke aus Perl, z.B. für Kommentare (/*...*/), können auf einfache Weise in reguläre Ausdrücke mit Differenz-Operatoren transformiert werden.
XML, DTD, XML Schema, RelaxNG
Validierung des Inhalts eines Elements gegen das Inhaltsmodell

Letzte Änderung: 02.12.2014
© Prof. Dr. Uwe Schmidt
Prof. Dr. Uwe Schmidt FH Wedel