Dezentrale Finanzen

Regex-Engine selbst bauen: Ein tiefgehender Leitfaden zur Mustererkennung in C++

Dezentrale Finanzen
Building a Regex Engine

Ein umfassender Leitfaden zum Verständnis und zur Umsetzung einer eigenen Regex-Engine in C++. Erfahre, wie reguläre Ausdrücke funktionieren, wie sie in endliche Automaten übersetzt werden und wie du eine leistungsfähige Regex-Engine von Grund auf entwickelst.

Reguläre Ausdrücke, kurz Regex genannt, sind aus der heutigen Softwareentwicklung kaum wegzudenken. Ob Textsuche, Datenvalidierung oder komplexe Mustererkennung – sie bieten eine flexible und mächtige Methode, um mit Text zu arbeiten. Doch obwohl viele Entwickler regelmäßig Regex einsetzen, bleibt das Verständnis, wie Regex-Engines im Inneren arbeiten, oft verborgen. Der Aufbau einer eigenen Regex-Engine bietet nicht nur Einblicke in fundamentale Konzepte der Informatik, sondern fördert auch ein tieferes Verständnis von Compiler-Techniken und Graphentheorie. In diesem Beitrag wird der Prozess erklärt, wie man von einem regulären Ausdruck zu einem lauffähigen Erkennungsautomat gelangt, und wie man diesen in C++ implementiert.

Dabei wird besonders der Schwerpunkt auf die theoretischen Grundlagen gelegt, die zur praktischen Realisierung nötig sind. Ein regulärer Ausdruck beschreibt eine Sprache – das heißt, er definiert eine Menge von Zeichenketten, die zu diesem Muster passen. Diese Sprache kann durch verschiedene Grundoperationen erzeugt werden: Vereinigung, Konkatenation und Kleene-Stern. Vereinigung entspricht dem logischen ODER, das bedeutet, entweder der Ausdruck links oder rechts vom Operator trifft zu. Konkatenation bedeutet, dass zwei Muster aneinandergehängt werden, sodass die Reihenfolge der Zeichen exakt erfüllt wird.

Der Kleene-Stern ermöglicht die Wiederholung eines Musters beliebig oft, einschließlich keiner Wiederholung. Um beispielsweise das Muster (a|b)*ab zu verstehen, stellt man sich vor, beliebig viele Zeichen a oder b, gefolgt von einem a und einem b, zu akzeptieren. Eine Reihe von Worten wie ab, bab, oder aaab würde zu einer solchen Sprache gehören. Um diese Muster nicht nur zu beschreiben, sondern auch auf Eingabedaten anwendbar zu machen, müssen reguläre Ausdrücke in erkennbare Automaten übersetzt werden. Hierzu werden sogenannte endliche Automaten verwendet.

Der nichtdeterministische endliche Automat (NFA) ist dabei ein grundlegendes Konzept. NFAs können sich aufgrund ihrer Nichtdeterminismus-Eigenschaft quasi an mehreren Orten gleichzeitig befinden. Dies bedeutet, dass das System für jeden eingehenden Buchstaben mehrere mögliche Übergänge hat, inklusive der Möglichkeit, Übergänge ohne Konsum von Eingaben (ε-Übergänge) zu nutzen. Ein solcher Automat wird formal durch Zustandsmengen, ein Eingabealphabet, eine Übergangsfunktion, einen Startzustand und eine Menge akzeptierender Zustände definiert. Der Bau eines NFAs aus einem regulären Ausdruck lässt sich elegant durch das McNaughton-Yamada-Thompson-Verfahren realisieren.

Dieses Verfahren baut rekursiv komplexe Ausdrücke aus einfacheren zusammen, wobei stets ein einzelner Start- und ein einzelner Endzustand für jede Teilausdrucks-NFA sichergestellt wird. Für den leeren String ε erzeugt man beispielsweise eine einfache Verbindung von Start- zu Endzustand über einen ε-Übergang. Für einzelne Zeichen wird eine unmittelbare Verbindung mit dem entsprechenden Buchstaben als Übergang erzeugt. Unionen werden durch einen neuen Start- und Endzustand mit ε-Übergängen zu den NFAs der Teilmengen realisiert. Konkatenation wird durch das Verbinden des akzeptierenden Zustands des ersten NFAs mit dem Startzustand des zweiten mittels eines ε-Übergangs modelliert.

Der Kleene-Stern schließlich erzeugt Zyklen, die Wiederholungen ermöglichen, indem er zusätzliche ε-Übergänge vom Start- zum akzeptierenden Zustand sowie vom akzeptierenden zurück zum Startzustand hinzufügt. Zur Implementation werden Zustände als Klassen mit Sammlungen von Übergängen modelliert. Jeder Zustand hält eine Liste von ε-Übergängen und eine Map von Eingabesymbolen auf Folgezustände. Die Verwaltung der Lebenszeit der Objekte erfolgt mittels modernem Speicher-Management wie smarten Zeigern, um Speicherlecks auszuschließen. Die Konstruktion des NFA beginnt mit einfachen Basiselementen, die dann schrittweise zu größeren Einheiten verschmolzen werden.

Ein wichtiger Teil der Engine ist die Funktion zur Berechnung der ε-Hülle, welche alle erreichbaren Zustände bei exklusiver Nutzung von ε-Übergängen bestimmt. Dieses Verfahren wird typischerweise mit Hilfe einer Tiefensuche realisiert und umfasst alle Zustände, die von einer gegebenen Menge aus ohne Eingabe anderer Zeichen erreichbar sind. Ebenso wird die Übergangsfunktion für ein gegebenes Eingabezeichen realisiert, die anhand der aktuell möglichen Zustände die Folgezustände ermittelt. Das Parsen des regulären Ausdrucks erfolgt mithilfe eines rekursiven Abstiegsparsers, der die Operatoren in der richtigen Priorität abarbeitet. Die Reihenfolge von Operatoren-Priorität ist Kleene-Stern, danach Konkatenation und zuletzt die Vereinigung.

Die Parser-Routinen verarbeiten jeweils den Teil des Ausdrucks, der einer Priorität entspricht, und rufen innerlich höher priorisierte Routinen auf, um Korrektheit und Struktur zu gewährleisten. Klammern werden dabei speziell behandelt, um verschachtelte Ausdrücke korrekt zu interpretieren. Das Ergebnis des Parsers ist ein kompletter NFA, der den gesamten regulären Ausdruck abbildet. Sobald der NFA generiert ist, können Eingabeworte gegen ihn geprüft werden. Die Simulation der Automata erfolgt, indem für jeden Buchstaben zunächst alle erreichbaren Folgezustände mittels der Übergangsfunktion gefunden und anschließend deren ε-Hüllen berechnet werden.

Wenn zu irgendeinem Zeitpunkt keine erreichbaren Zustände mehr vorliegen, bedeutet das, dass die Eingabe nicht akzeptiert wird. Nach Verarbeitung aller Eingaben erfolgt die Prüfung, ob einer der derzeit möglichen Zustände ein akzeptierender Zustand ist. Falls ja, gehört die Zeichenkette zur Sprache des regulären Ausdrucks. Die so realisierte Regex-Engine bietet eine solide Basis zum Verstehen und Experimentieren mit regulären Ausdrücken. Sie ist zwar einfach gehalten und noch nicht auf maximale Effizienz optimiert, liefert aber wesentliche Einblicke in den Aufbau und Betrieb solcher Pattern-Matching-Werkzeuge.

Automatischer Handel mit Krypto-Geldbörsen Kaufen Sie Ihre Kryptowährung zum besten Preis

Als Nächstes
Amazon to Invest $4B in Chile AWS Data Centers
Donnerstag, 12. Juni 2025. Amazon investiert 4 Milliarden Dollar in AWS-Rechenzentren in Chile: Ein Meilenstein für die digitale Infrastruktur Lateinamerikas

Amazon kündigt eine bedeutende Investition von 4 Milliarden US-Dollar in den Ausbau von AWS-Rechenzentren in Chile an, was die digitale Transformation der Region vorantreibt und neue Chancen für Wirtschaft und Technologie schafft.

Show HN: One-Line Installer for Cursor on Linux
Donnerstag, 12. Juni 2025. Effiziente Installation von Cursor auf Linux: Ein neuer Weg für Entwickler

Entdecken Sie, wie die One-Line-Installer-Skripte für Cursor unter Linux die Installation, Aktualisierung und Deinstallation eines innovativen AI-gestützten Code-Editors vereinfachen und Entwicklern eine nahtlose Integration und Nutzung ermöglichen.

Beautiful Concurrency (2007) [pdf]
Donnerstag, 12. Juni 2025. Schöne Parallelität: Wie Software Transactional Memory die Zukunft der nebenläufigen Programmierung prägt

Parallelität ist in der modernen Softwareentwicklung unerlässlich, um die Leistung auf Mehrkernprozessoren optimal zu nutzen. Software Transactional Memory (STM) bietet einen eleganten und modularen Ansatz für die nebenläufige Programmierung, der viele der bisherigen Herausforderungen überwindet.

Navy finds something the LCS is good at: Stopping drug smuggling
Donnerstag, 12. Juni 2025. Die Littoral Combat Ships der US Navy: Ein unverhoffter Erfolg im Kampf gegen Drogenschmuggel

Die Littoral Combat Ships (LCS) der US Navy, lange Zeit kritisch gesehen, finden zunehmend ihre Rolle im Kampf gegen den Drogenschmuggel. Ihre speziellen Eigenschaften machen sie zu effektiven Werkzeugen bei der Bekämpfung illegaler Drogenbewegungen in Küsten- und Karibikregionen.

OSS: Two Steps Forward, One Step Back
Donnerstag, 12. Juni 2025. Open Source Software im Wandel: Zwei Schritte vorwärts, ein Schritt zurück

Die Entwicklung von Open Source Software durchlebt eine dynamische Phase, in der sich neue Lizenzmodelle etablieren und gleichzeitig Herausforderungen für die Community und kommerzielle Anbieter entstehen. Der Wandel im Umgang mit Lizenzen wie AGPL und SSPL sowie die Rolle von Stiftungen prägen die Zukunft der Open Source Landschaft nachhaltig.

Cheap SSL Certificates
Donnerstag, 12. Juni 2025. Günstige SSL-Zertifikate: Sichere Website zum kleinen Preis

Erfahren Sie, wie günstige SSL-Zertifikate Ihre Website schützen, Vertrauen schaffen und gleichzeitig Kosten sparen können. Ein umfassender Leitfaden zu verschiedenen SSL-Typen, Anbietern und Einsatzgebieten für Webseiten jeder Größe und Branche.

Show HN: An AI-first visual editor using GPT-4o's GPT-image-1 model
Donnerstag, 12. Juni 2025. Revolutionäre KI-basierte Bildbearbeitung: Der AI-first Visual Editor mit GPT-4o's gpt-image-1 Modell

Ein tiefer Einblick in die Integration des GPT-4o Bildgenerierungsmodells in die CreativeEditor SDK und wie diese innovative KI-Lösung die kreative Bildbearbeitung und Designprozesse grundlegend transformiert.