Signatur
Beschreibung
Parle\Parser ist ein LALR(1)-Parser, der zusammen mit Parle\Lexer eingesetzt wird, um zur Laufzeit vollständige Grammatiken zu definieren und Eingabetexte nach diesen Regeln zu analysieren. Im Gegensatz zu statischen Parser-Generatoren (z. B. bison) werden Tokens, Symbole und Produktionsregeln direkt im PHP-Code festgelegt, ohne Codegenerierungsschritt.
Der typische Arbeitsablauf besteht aus drei Phasen: Definition (Tokens und Grammatikregeln hinzufügen), Bau (Aufruf von build() zur internen Tabellengenerierung) und Parsing (Übergabe eines Eingabestrings mittels consume(), anschließend schrittweise Verarbeitung über advance() und Auswertung von action/reduceId).
Typische Anwendungsfälle sind das Parsen eigener Mini-Sprachen, Konfigurations-DSLs, mathematischer Ausdrücke oder einfacher Templatesprachen innerhalb einer PHP-Anwendung, ohne auf externe Tools angewiesen zu sein.
Die Klasse ist Teil der PECL-Erweiterung parle und muss explizit installiert werden (pecl install parle). Sie arbeitet eng mit Parle\Lexer und Parle\RParser/Parle\RLexer zusammen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $flags | int | 0 | Optionale Flags zur Steuerung des Parser-Verhaltens, z. B. Parle\Parser::ACTION_ERROR. In den meisten Fällen wird kein Flag benötigt. |
Rückgabewert
Beispiele
Einfache Additions-Grammatik parsen
<?php
// Benötigt PECL-Erweiterung "parle"
$lexer = new Parle\Lexer();
$lexer->push('[0-9]+', 1); // Token-ID 1 = Zahl
$lexer->push('[+]', 2); // Token-ID 2 = Plus
$lexer->build();
$parser = new Parle\Parser();
$parser->token('INTEGER'); // Token 'INTEGER' anmelden
$parser->token('PLUS');
// Grammatik definieren:
// expr : expr PLUS expr | INTEGER
$parser->push('start', 'expr');
$parser->push('expr', 'expr PLUS expr');
$parser->push('expr', 'INTEGER');
$parser->build();
$input = '3+5';
$parser->consume($input, $lexer);
do {
$parser->advance();
switch ($parser->action) {
case Parle\Parser::ACTION_ACCEPT:
echo "Eingabe akzeptiert.\n";
break;
case Parle\Parser::ACTION_ERROR:
echo "Fehler bei Token: " . $parser->reduceId . "\n";
break;
}
} while (Parle\Parser::ACTION_ACCEPT !== $parser->action
&& Parle\Parser::ACTION_ERROR !== $parser->action);
Grammatik mit Priorität und Assoziativität
<?php
$lexer = new Parle\Lexer();
$lexer->push('[0-9]+', 1);
$lexer->push('[+]', 2);
$lexer->push('[*]', 3);
$lexer->build();
$parser = new Parle\Parser();
$parser->token('INTEGER');
$parser->token('PLUS');
$parser->token('STAR');
// Punkt vor Strich: STAR hat höhere Präzedenz
$parser->left('PLUS'); // PLUS ist linksassoziativ
$parser->left('STAR'); // STAR ebenfalls, aber höhere Ebene
$parser->push('start', 'expr');
$parser->push('expr', 'expr PLUS expr');
$parser->push('expr', 'expr STAR expr');
$parser->push('expr', 'INTEGER');
$parser->build();
$input = '2+3*4';
$parser->consume($input, $lexer);
do {
$parser->advance();
} while (Parle\Parser::ACTION_ACCEPT !== $parser->action
&& Parle\Parser::ACTION_ERROR !== $parser->action);
echo ($parser->action === Parle\Parser::ACTION_ACCEPT)
? "Korrekt geparst.\n"
: "Fehler.\n";
// Wichtig · Fallstricke
Installation: Parle\Parser ist nur verfügbar, wenn die PECL-Erweiterung parle installiert ist (pecl install parle und extension=parle in der php.ini). Die Erweiterung ist nicht standardmäßig in PHP enthalten.
Reihenfolge beachten: Tokens müssen vor Grammatikregeln registriert werden, und build() muss aufgerufen werden, bevor consume() verwendet wird. Ein fehlender build()-Aufruf führt zu einem fatalen Fehler.
Thread-Safety: Parser-Instanzen sollten nicht über Request-Grenzen hinweg in Shared Memory abgelegt werden, da der interne Zustand bei consume() verändert wird.
Für komplexere Grammatiken mit mehrdeutigen Regeln steht die Klasse Parle\RParser (Earley-basiert) zur Verfügung, die mehr Mehrdeutigkeit toleriert, aber langsamer ist.