2012-04-10 13 views
5

Ich habe Probleme mit einer einfachen Grammatik, die ich erstellt habe, um Funktionsaufrufe zu unterstützen.
Ich verwende den Citron-basierten PHP_ParserGenerator von Greg.Probleme mit Zitrone Grammatik (Vorrang?)

Dies ist der relevante Teil der Grammatik:

$parser->doParse(PelParser::CONTEXT_REFERENCE, 'user.name'); 
$parser->doParse(0, 0); 

Die $result wie folgt: '

program ::= expr(A).      { $this->result = A; } 

value(A) ::= SIMPLE_STRING(B).    { A = B; } 
value(A) ::= NUMBER(B).      { A = B; } 
value(A) ::= CONTEXT_REFERENCE(B).   { A = B; } 

arg_list ::= arg_list SEPARATOR value(B). { $this->args[] = B; } 
arg_list ::= value(B).      { $this->args[] = B; } 
arg_list ::= . 

expr(A) ::= SIMPLE_STRING(B) PAREN_LEFT arg_list PAREN_RIGHT. { A = call_user_func_array(B, $this->args); } 

expr(A) ::= CONTEXT_REFERENCE(B). { 
    list($context, $key) = explode('.', B); 
    A = $this->context[$context][$key]; 
} 

Wenn ich den Parser mit einem Kontext von array('user' => array('name' => 'Dennis')); und führen Sie den folgenden Code initialisieren Dennis. Das leben ist gut.

Aber wenn ich ein CONTEXT_REFERENCE als Argument für einen Funktionsaufruf liefern, funktioniert es nicht:

$parser->doParse(PelParser::SIMPLE_STRING, 'str_replace'); 
$parser->doParse(PelParser::PAREN_LEFT, '('); 
$parser->doParse(PelParser::SIMPLE_STRING, 'e'); 
$parser->doParse(PelParser::SEPARATOR, ','); 
$parser->doParse(PelParser::NUMBER, 3); 
$parser->doParse(PelParser::SEPARATOR, ','); 
$parser->doParse(PelParser::CONTEXT_REFERENCE, 'user.name'); 
$parser->doParse(PelParser::PAREN_RIGHT, ')'); 
$parser->doParse(0, 0); 

Die $result ist 'us3r.nam3'. Nicht ganz wie erwartet. Für die Aufzeichnung ist die erwartete Ausgabe natürlich "D3nnis". (user.name zuerst wird durch die Zeichenfolge 'Dennis' ersetzt und danach an die str_replace() Funktion übergeben).

Ich vermute, es hat etwas mit Vorrang zu tun. Aber ich kann mir nicht vorstellen, was ich ändern sollte, um das zu machen. Die sehr spärliche Lemon-Dokumentation ist keine große Hilfe.

Jede Hilfe würde sehr geschätzt werden! Danke

Antwort

1

Ich habe die Antwort auf meine Frage gefunden.

Wenn ich meine Grammatik zu ändern:

program ::= expr(A).      { $this->result = A; } 

value(A) ::= SIMPLE_STRING(B).    { A = B; } 
value(A) ::= NUMBER(B).      { A = B; } 
value(A) ::= CONTEXT_REFERENCE(B). { 
    // B=='{context}.{name}' 
    list($context, $key) = explode('.', B); 
    A = $this->context[$context][$key]; 
} 

arg_list ::= arg_list SEPARATOR value(B). { $this->args[] = B; } 
arg_list ::= value(B).      { $this->args[] = B; } 
arg_list ::= . 

expr(A) ::= SIMPLE_STRING(B) PAREN_LEFT arg_list PAREN_RIGHT. { A = call_user_func_array(B, $this->args); } 

Es scheint wie erwartet zu funktionieren.
Das Problem war, dass ich eine Zweideutigkeit in der ersten Grammatik erstellt:

value(A) ::= CONTEXT_REFERENCE(B).   { A = B; } 

expr(A) ::= CONTEXT_REFERENCE(B). { 
    list($context, $key) = explode('.', B); 
    A = $this->context[$context][$key]; 
} 

ich die Frage verlassen würde und hier beantworten, so dass andere aus meinen Fehlern profitieren könnten :) Wenn jemand etwas, bitte zu teilen muss tun .