Ein URL (Uniform Resource Locator) gibt die Adresse eines Objekts im
World Wide Web an. Er besteht aus der Zugriffsart (hp
,
ftp
, gopher
, mailto
, news
) gefolgt von
einem Doppelpunkt ":
" und einer genaueren Beschreibung des
Objekts, abhängig von der Zugriffsart.
Bei http
, ftp
und gopher
folgen zwei
Schrägstriche "//
", ein Hostname und ein Zugriffspfad.
Ein Hostname besteht entweder aus vier Zahlen mit maximal drei
Ziffern, getrennt durch einen Punkt (z.B. 128.130.173.8) oder
aus einer beliebigen Anzahl von Buchstabengruppen (Groß- und
Kleinbuchstaben und "-
") getrennt durch einen Punkt
(der Hostname muß in diesem Fall mit einem Buchstaben beginnen,
z.B. ftp.uni-paderborn.de
).
Ein Zugriffspfad ist vom Hostname durch einen Schrägstrich getrennt. Er besteht aus beliebig vielen (nicht leeren) Filenamen, die durch Schrägstriche getrennt sind und darf auch mit einem Schrägstrich enden.
Ein Filename besteht aus beliebig vielen Groß- und Kleinbuchstaben,
"-
" und ".
".
Bei der Zugriffsart news
folgt nach dem Doppelpunkt nur ein
Hostname. Bei mailto
folgt nach dem Doppelpunkt ein
Name, ein "@
" und ein Hostname. Ein Name besteht aus
beliebig vielen Groß- und Kleinbuchstaben.
ziff = [0-9]
zahl = ziff ziff? ziff?
bst = [a-z]|[A-Z]
ip = zahl "." zahl "." zahl "." zahl
hn = bst (bst|"-")* ("." (bst|"-")+)*
host = ip|hn
file = (bst|"-"|".")+
pfad = file ("/" file)* "/"?
art = "http"|"ftp"|"gopher"
URL = (art "://" host ("/" pfad)|("/"?)) | ("news:" host) | ("mailto:"
bst+ "@" host)
Bei einer regulären Definition ist es wichtig, innen anzufangen und sich langsam nach außen vorzuarbeiten. Die dabei entstehenden Bausteine werden dann für die weiteren Definitionen verwendet.
Die erste ins Auge fallenden Bausteine sind der Hostname der entweder aus Zahlen- oder aus Buchstabengruppen bestehen kann:
Ein Hostname besteht entweder aus vier Zahlen mit maximal drei Ziffern, getrennt durch einen Punkt (z.B. 128.130.173.8) oder aus einer beliebigen Anzahl von Buchstabengruppen (Groß- und Kleinbuchstaben und "
-
") getrennt durch einen Punkt (der Hostname muß in diesem Fall mit einem Buchstaben beginnen, z.B.ftp.uni-paderborn.de
).
Eine Zahl besteht also aus maximal drei Ziffern. Da die vier Zahlen
ihrerseits durch einen Punkt getrennt sind bedeutet das, daß eine
Zahl aus mindestens einer Ziffer bestehen muß. Eine
Trennung hätte ja sonst keinen Sinn. Daraus ergeben sich die
Definitionen ziff = [0-9]
und zahl = ziff ziff?
ziff?
. Eine Zahl besteht also aus einer Ziffer gefolgt von zwei
optionalen Ziffern. Über den Wertebereich einer Zahl wird keine
Aussage gemacht. Das "Metawissen", daß eine IP-Adresse (derzeit) nur
mit Zahlen im Bereich von 0 bis 255 arbeitet ist hier ohne Belang. Die
gesamte IP-Adresse ist eine Aneinanderreihung von Zahlen, getrennt durch
einen Punkt: ip = zahl "." zahl "." zahl "." zahl
Die zweite Alternative für den Hostname ist ein Name
bestehend aus Buchstabengruppen die durch Punkt getrennt sind. Die
Buchstabengruppen dürfen zwar auch einen Bindestrich enthalten, der
ganze Hostname muß jedoch mit einem
Buchstaben beginnen. Wir definieren daher zuerst einen Einzelbuchstaben
durch bst = [a-z]|[A-Z]
. Der ganze Name hn
beginnt
also mit einem bst
und erst dann dürfen Buchstaben und
Bindestriche in beliebiger Kombination vorkommen: (bst|"-")*
.
Weitere Buchstabengruppen sind durch Punkt getrennt: ("."
(bst|"-")+)*
Anmerkung: Die Aneinanderreihung von Termen und Trennzeichen kommt
sehr häfig vor. Eine übliche Konstruktion ist term (trenn
term)*
, also mindestens ein Term und beliebig viele Wiederholungen
von Trennzeichen und weiteren Termen.
Der ganze Hostname ist durch host = ip|hn
definiert.
Die Zugriffsarten news
und mailto
lassen sich
mit den vorangegangenen Bausteinen direkt aus der Textbeschreibung
ableiten:
Bei der Zugriffsart
news
folgt nach dem Doppelpunkt nur ein Hostname. Beimailto
folgt nach dem Doppelpunkt ein Name, ein "@
" und ein Hostname. Ein Name besteht aus beliebig vielen Groß- und Kleinbuchstaben.
Daraus ergeben sich "news:" host
bzw. "mailto:"
bst* "@" host
Anmerkung: Natürlich kann man auch argumentieren, daß
der Name in einer Mailadresse immer mindestens einen Buchstaben haben
muß, also bst+
statt bst*
. Beide Varianten
sind richtig, da keine weiteren Einschränkungen bezüglich des
Namens gemacht wurden.
Die Beschreibung des Zugriffspfades muß man sehr genau lesen, um sie richtig zu übersetzen:
Ein Zugriffspfad ist vom Hostname durch einen Schrägstrich getrennt. Er besteht aus beliebig vielen (nicht leeren) Filenamen, die durch Schrägstriche getrennt sind und darf auch mit einem Schrägstrich enden.
Die Filenamen sind noch das Einfachste. Sie bestehen aus beliebig
vielen Buchstaben, "-
" und ".
", sind aber
nicht leer also file = (bst|"-"|".")+
. Der ganze
Zugriffspfad besteht jedoch aus beliebig vielen, durch
"/
" getrennten Filenamen und darf mit einem
"/
" enden. D.h., der ganze Pfad kann auch leer sein. Daraus
ergibt sich pfad = file ("/" file)* "/"?
Beim Zusammensetzen der vollständigen Definition müssen wir noch eine Ungereimtheit beseitigen:
Ein Zugriffspfad ist vom Hostname durch einen Schrägstrich getrennt.
Wie wir gesehen haben, kann der Zugriffspfad auch leer sein. Eine Trennung
von etwas Leerem macht jedoch keinen Sinn. Gleichzeitig darf der Pfad nur
mit einem "/
" enden. Eine Definition die beide
Fälle berücksichtigt ist in der Lösung gegeben. Sie lautet:
host ("/" pfad)|("/"?)
und vermeidet damit zwei
Schrägstriche direkt nebeneinander.
Die Aneinanderreihung der alternativen Zugriffsarten ergibt schließlich die endgültige Lösung.
Von Wolfgang Faber kommt der Hinweis an alle, die nach diesem Beispiel laut aufstöhnen, einmal einen Blick in die Originalspezifikation zu werfen. :-)