Start · Sprachen · PHP · Referenz · Parle\Parser

Parle\Parser

Klasse

Parser-Klasse der <code>parle</code>-Erweiterung, deren Grammatikregeln zur Laufzeit dynamisch definiert werden können.

seit PHP 0.5.1 Kategorie: misc

Signatur

class Parle\Parser

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

Typ

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);
Eingabe akzeptiert.

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";
Korrekt geparst.

// 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.