2012-04-10 5 views
5

У меня возникают проблемы с простой грамматикой, которую я создал для поддержки вызовов функций.
Я использую основанный на лимоне PHP_ParserGenerator от Greg.Проблемы с лимонной грамматикой (приоритет?)

Это соответствующая часть грамматики:

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]; 
} 

Когда я инициализировать анализатор с контекстом array('user' => array('name' => 'Dennis')); и выполнить следующий код:

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

$result выглядит следующим образом: ' Деннис. Жизнь хороша.

Но когда я поставить CONTEXT_REFERENCE в качестве аргумента вызова функции, он не работает:

$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); 

$result является "us3r.nam3. Не совсем так, как ожидалось. Для записи ожидаемый результат, конечно, «D3nnis». (имя пользователя сначала заменяется на строку «Деннис», а затем переходит к функции str_replace()).

Я подозреваю, что это имеет какое-то отношение к приоритету. Но я не могу понять, что я должен изменить, чтобы это сделать. Очень редкая лимонная документация не очень помогает.

Любая помощь была бы принята с благодарностью! Thanks

ответ

1

Кажется, я нашел ответ на свой вопрос.

Когда я изменить свою грамматику:

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); } 

Это, кажется, работает, как ожидалось.
Проблемы заключалась в том, что я создал неоднозначность в первых грамматиках:

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

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

Я оставлю этот вопрос и ответить здесь, чтобы другие могли бы извлечь выгоду из моих ошибок :) Если кто-то имеет что-нибудь поделиться, пожалуйста, ,

 Смежные вопросы

  • Нет связанных вопросов^_^