2012-04-10 84 views
5

我遇到了一個簡單的語法問題,我創建它來支持函數調用。
我正在使用Greg的基於檸檬的PHP_ParserGenerator。檸檬語法問題(優先級?)

這是語法的相關部分:

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'。 (用戶名第一個被替換爲字符串'Dennis',然後傳遞給str_replace()函數)。

我懷疑它與優先順序有關。但我無法弄清楚我應該改變做什麼。非常稀少的檸檬文檔不是非常有幫助。

任何幫助將不勝感激! 謝謝

回答

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

我會離開的問題和答案在這裏,所以如果有人有什麼分享他人可能會受益於我的錯誤:) ,請不要。