Signatur
Beschreibung
Parle\Lexer ist Teil der Parle-Erweiterung und stellt einen tokenisierenden Lexer mit einem einzigen Zustand bereit. Er eignet sich, um Eingabe-Strings anhand regulärer Ausdrücke in Token-Sequenzen zu zerlegen, was typischerweise der erste Schritt beim Parsen einer kleinen Sprache, eines Konfigurationsformats oder einer Ausdruckssprache ist.
Im Gegensatz zu Parle\RLexer (der mehrere Zustände unterstützt) beschränkt sich Parle\Lexer auf einen einzigen Zustands-Automaten. Das reicht für einfache, kontextfreie Tokenisierungsaufgaben aus und ist dabei leichter zu konfigurieren und zu verwenden.
Der typische Arbeitsablauf ist: Token-Muster mit push() registrieren, den Lexer mit build() kompilieren, anschließend mit consume() Eingabedaten bereitstellen und per advance() Token für Token durchlaufen. Das aktuelle Token ist dann über die öffentliche Eigenschaft token (ein Parle\Token-Objekt) zugänglich.
Weil der Lexer intern auf einem deterministischen endlichen Automaten (DFA) basiert, ist die Tokenisierung sehr performant — auch für längere Eingaben. Der Einsatz empfiehlt sich überall dort, wo man preg_match-Schleifen oder manuelle Zeichenanalysen ersetzen möchte.
Beispiele
Einfache Arithmetik-Tokenisierung
<?php
$lexer = new Parle\Lexer();
// Whitespace ignorieren
$lexer->push('\s+', Parle\Lexer::SKIP);
// Integer-Zahl
$lexer->push('[0-9]+', 1);
// Operatoren
$lexer->push('[+\-*/]', 2);
// Lexer kompilieren (DFA erzeugen)
$lexer->build();
// Eingabe bereitstellen
$lexer->consume('12 + 34 * 5');
// Token für Token auslesen
while (Parle\Lexer::EOI !== $lexer->token->id) {
$token = $lexer->token;
echo 'ID=' . $token->id . ' Wert="' . $token->value . '"' . PHP_EOL;
$lexer->advance();
}
Identifier und Schlüsselwörter erkennen
<?php
define('TOK_KEYWORD', 1);
define('TOK_IDENTIFIER', 2);
define('TOK_NUMBER', 3);
$lexer = new Parle\Lexer();
$lexer->push('\s+', Parle\Lexer::SKIP);
// Schlüsselwörter müssen VOR allgemeinen Identifiern registriert werden
$lexer->push('if|else|while|return', TOK_KEYWORD);
$lexer->push('[a-zA-Z_][a-zA-Z0-9_]*', TOK_IDENTIFIER);
$lexer->push('[0-9]+', TOK_NUMBER);
$lexer->build();
$lexer->consume('if count return myVar 42');
$labels = [TOK_KEYWORD => 'KEYWORD', TOK_IDENTIFIER => 'IDENT', TOK_NUMBER => 'NUMBER'];
while (Parle\Lexer::EOI !== $lexer->token->id) {
$id = $lexer->token->id;
$val = $lexer->token->value;
echo ($labels[$id] ?? 'UNKNOWN') . ': ' . $val . PHP_EOL;
$lexer->advance();
}
// Wichtig · Fallstricke
Reihenfolge der Regeln: Token-Muster werden in der Reihenfolge ausgewertet, in der sie mit push() hinzugefügt wurden. Spezifischere Muster (z. B. Schlüsselwörter) sollten vor allgemeineren (z. B. generischen Identifiern) registriert werden, damit sie Vorrang erhalten.
Einmaliges Build: Nach dem Aufruf von build() dürfen keine weiteren Regeln per push() hinzugefügt werden. Soll der Lexer mit neuen Regeln verwendet werden, muss ein neues Objekt erstellt werden.
Kein Zustandswechsel: Benötigt man kontextabhängige Tokenisierung (z. B. für String-Literale mit Escape-Sequenzen), sollte stattdessen Parle\RLexer verwendet werden, der mehrere Zustände unterstützt.
Erweiterung erforderlich: Parle\Lexer ist Teil der PECL-Erweiterung parle und nicht im PHP-Core enthalten. Die Erweiterung muss separat installiert werden (pecl install parle).