home Funktionale Programmierung: Ableitung von regulären Ausdrücken Prof. Dr. Uwe Schmidt FH Wedel

Ableitung von regulären Ausdrücken

weiter

weiter

Aufgabe

Ableitungen von Regulären Ausdrücken
als Trainingslager für die Verarbeitung und Transformation von Ausdrücken
weiter
Reguläre Ausdücken
können direkt operationalisiert werden. Traditionell werden R.E.s in deterministische endliche Automaten transformiert, um ein operationales Modell für die Worterkennung mit regulären Sprachen zu realisiern.
 
Dieses geht aber auch direkt. Das Verfahren ist in den Unterlagen zur Vorlesung Compilerbau beschrieben.
 
Die Idee dabei ist die, dass aus einem R.E. und dem ersten Zeichen einer Eingabe ein R.E. für den Rest der Eingabe berechnet wird.
 
In den Compilerbau-Unterlagen ist auch schon eine Datenstruktur skizziert, mit der man reguläre Ausdrücke als Repräsentanten für reguläre Mengen aufbauen kann.
 
Für die Operationalisierung benötigt man folgende Funktionen:
 
nullable        :: RE a -> Bool
delta           :: RE a -> a -> RE a
delta'          :: RE a -> [a] -> RE a
match           :: RE a -> [a] -> Bool
1. Aufgabe
Vervollständigen Sie die Codefragmente aus den Unterlagen, entwickeln Sie auf möglichst systematische Weise Testfälle (mit Char als Eingabealphabet) und entwickeln Sie eine trace-Funktion, mit der man beobachten kann, wie die Ableitungen schrittweise aufgebaut werden und sich beim Parsen verändern. Hierfür ist die Funktion deltaTest vorgesehen.
 
deltaTest       :: RE a -> [a] -> [RE a]
 
Für die Untersuchung des Wachsens von Ausdrücken sind insbesondere die Wiederholungen in Kombination mit Sequenz und Auswahl interessant, Beispiele a*, (a|b)*, (a|b*)*
Die Typdefinitionen und erste einfache kleine Funktionen für die Lösung.
Download
2. Aufgabe
Erweitern Sie die Datenstruktur und die Funktionen so, dass folgende Operatoren in R.E.s möglich sind:
.
für ein beliebiges Zeichen aus dem Alphabet
r+
für eine mindestens einmalige Wiederholung
r & r
für einen Mengendurchschnitt
r - r
für einen Mengensubtraktion
Tests
Sinnvolle Beispiele für diese Erweiterung sind reguläre Ausdrücke für Kommentare aus C (/****/ aber nicht /**/*/) oder alle Bezeichner einer Sprache außer Schlüsselwörter.
Verfeinerung
der Datenstruktur: Dieses kann für die Performanz wichtig sein. Eine Ineffizienz besteht darin, nur mit einzelnen Symbolen als Blätter zu arbeiten. Symbolmengen werden dann zu sehr großen Ausdrücken. Hier kann es günstiger sein, mit Symbol-Mengen zu arbeiten, die entweder als explizite Listen oder als Funktionen repräsentiert werden.
weiter
3. Aufgabe
Ersetzen Sie die expliziten Konstruktoraufrufe durch Aufrufe von so genannten intelligenten Konstruktorfunktionen. Diese sollen dafür sorgen, dass die durch das Ableiten entstehenen Ausdrücke in ihrer Größe nicht wachsen, d.h. in dieses Funktionen werden die Gesetzte der Booleschen Algebra zur partiellen Auswertung und Vereinfachung ausgenutzt. Ziel dabei ist, dass die Größe des abgeleiteten Ausdrucks nicht von der Länge der Eingabe abhängt.
 
Wählen Sie dafür eine hinreichende Menge von Transformationsregeln.
4. Aufgabe
Entwickeln Sie einen Parser für die Syntaxanalyse von regulären Ausdrücken und den Aufbau des Ausdrucksbaums.
Noch mit fehlenden Konstruktor-Funktionen.
Download
5. Aufgabe
Schreiben Sie eine Anwendung, die ähnliche Funktionalität besitzt wie das grep-Kommando.
6. Aufgabe
Schreiben Sie eine Anwendung, die ähnliche Funktionalität besitzt wie das scan-Kommando aus Ruby. Mit diesem kann man über einen regulären Ausdruck einen Text in Wörter zerlegen. Alle diese Wörter passen auf den R.E., alle anderen Zeichen werden als Worttrenner interpretiert und gelöscht.

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