Larry Wall gibt den Rakudo-Perl-6-Compiler auf MoarVM für den produktiven Einsatz frei

Seite 5: Regex & Fazit

Inhaltsverzeichnis

Perl half den POSIX-Standard der Regex (reguläre Ausdrücke) zu popularisieren, bis seine Erweiterungen selbst zum Standard wurden. Wer sich davon nicht trennen kann, setzt am Anfang einer Perl-6-Regex das Adverb :Perl5 (oder :P5), gibt aber damit Möglichkeiten und Klarheit auf.

Allein die erste Regel vermeidet viele Fragen: alphanumerische Zeichen (A-z,0-9) nimmt das System wörtlich. Alle übrigen Zeichen haben potenziell eine Sonderbedeutung und benötigen ein vorrangestelltes \, damit der Interpreter sie wörtlich versteht.

Zweitens wurden Sonderschreibweisen an die Hauptsprache angepasst. Zum Beispiel wurde aus dem Quantoren {m,n} jetzt ** m..n und statt der Backreferences greifen Entwickler zu den gleichen Sondervariablen wie außerhalb der regulären Ausdrücke ($0 oder $/[0] statt \1). $/ enthält ein Objekt, dass alle Information über die letzte Anwendung einer Regex enthält.

Die dritte große Maßnahme hat den meisten Erfassungsgruppen englische Namen gegeben. So gilt statt (?<=...) für einen Lookbehind die Schreibweise <?after ...>, denn nach ihm kommt der Teil des Suchbegriffs, auf den er sich bezieht.

Was für Perl 5 die Option s war, wurde Standard, um übersichtlichere und dokumentierte Regex zu begünstigen. Entwickler können ihn explizit durch :s aufheben.

Die vielleicht wichtigste Änderung ist, dass Perl 6 die Funde der speichernden Gruppen (capturing groups) verschachtelt ablegt:

    /((\w)(..)).../

Das mit dem sichtbaren \w gefundene Wortzeichen wäre mit Perl 5 in $2, mit Perl 6 in $/[0][0]. Das macht Code unempfindlicher bei Änderungen, ist aber vor allem die Grundlage für den Aufbau hierarchischer Datenstrukturen. Sie sind wesentlich angenehmer, wenn jede Gruppe sprechende Namen hat, und ihr Ergebnis unter einem gleichnamigen Hash-Schlüssel gespeichert wird:

    # sucht 2 bis 5 von Kommas getrennte Ziffern
.. $<koordinaten>=[ \d ** 2 .. 5 % ',' ] ..
# eckige Klammern umfassen nicht speichernde Gruppen

Der Fund aus obigem Beispiel landet in $/<koordinaten> oder $<koordinaten>. Im nächsten Schritt wird das Suchmuster in eine Routine ausgelagert, die es auf ihren ersten Parameter anwendet und das Ergebnis in Form eines Suchobjektes (wie in $/) zurückliefert.

    regex koor { \d ** 2 .. 5 % ',' }

Damit wird das Muster als /..<koor>../ wiederverwendbar. Auf diese Weise speichern sich Entwickler nützliche Muster in eigenen Modulen. Da Perl 6 genauso vorgeht, bietet es eine große Anzahl vordefinierter Muster an, die übrigens keine besonderen Privilegien gegenüber denen des Nutzers besitzen.

Diese Module beziehungsweise Pakete beginnen mit dem Schlüsselwort grammar und entfalten ihre volle Stärke, wenn sich die Muster gegenseitig verwenden. Da grammar eine besondere Art von Klassen sind, können sie sich beerben und Methoden überladen. Um Rechenzeit zu sparen, nehmen Entwickler dazu meist keine regex-Routinen, sondern token und rule.

    # für Zeitstempel wie [11:43:22]
grammar Zeitstempel {
rule TOP {\[<Stunden><.Trenner><Minuten>[<.Trenner><Sekunden>]?\]}
token Trenner { <[: ,]> } # eigene Zeichenklasse
token Stunden {[ <[0 1]> \d ] | [2 <[0 4]>] } # 00-19 | 20-24
token Minuten {[ <[0..5]> \d ] | 6 0} # 00-59 | 60
token Sekunden {[ <[0..5]> \d ] | 6 0}
}

Wird eine Grammatik wie in Zeitstempel.parse($text); gebeten etwas einzulesen, bemüht sie die TOP-Regel. Der Rest folgt, bis die gesuchten Werte in $<Stunden> und $<Minuten> liegen. Da hier die Trenner nicht interessierten, kam das Muster <.Trenner> zum Einsatz, das zwar sucht, aber nichts in $<Trenner> speichert. Bereits an diesem einfachen Beispiel wurde deutlich: das Perl-5-Äquivalent – vor allem ohne die in 5.10 eingeführten benannten Gruppen – wäre deutlich unübersichtlicher.

Bekommt die .parse-Methode als zweiten Parameter eine sogenannte Action-Klasse, entsteht bereits ein vollständiger Parser. Wird zum Beispiel das token Minuten fündig, so bekommt die Methode Minuten der Action-Klasse das entstandene Match-Objekt als Parameter und verstaut dort auch ihr Resultat. Die Action-Methode TOP kann später darauf zugreifen und einen Gesamtwert berechnen.

Perl 6 ist sehr reichhaltig und adressiert fast alle aktuellen Felder der Programmierung. Dabei entwickelt es sogar eigene Visionen. Liebhaber von Perl 5 und Programmierer mit Parsing-Aufgaben sollten es sich zumindest ansehen. Auch Softwarearchitekten mit der Ambition zur eigenen Sprache können Perl 6 als Fertigbaukasten verwenden.

Trotz vorhandener Mechanismen zur Einschränkung von Freiheiten werden wohl die merklich großen Spielräume und die mittlerweile sparsamere Verwendung sämtlicher Sonderzeichen die Aspekte sein, an denen sich die Ansichten über Perl weiterhin scheiden.

Herbert Breunung
schreibt regelmäßig Artikel über Perl 5, Perl 6 und GUI-Programmierung und spricht darüber auch auf Konferenzen im In- und Ausland. Außerdem führt er ein freies Softwareprojekt und ist Autor von diversen Dokumentationen.

(rme)