2012-04-10 55 views
5

Tôi đang gặp rắc rối với một ngữ pháp đơn giản mà tôi đã tạo để hỗ trợ các cuộc gọi chức năng.
Tôi đang sử dụng PHP_ParserGenerator dựa trên chanh của Greg.Troubles với ngữ pháp chanh (ưu tiên?)

Đây là phần liên quan của ngữ pháp:

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

Khi tôi khởi tạo phân tích cú pháp với một bối cảnh array('user' => array('name' => 'Dennis')); và thực hiện đoạn mã sau:

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

Các $result được như sau: ' Dennis '. Cuộc sống là tốt.

Nhưng khi tôi cung cấp một CONTEXT_REFERENCE như là đối số để gọi chức năng, nó không hoạt động:

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

Các $result là 'us3r.nam3'. Không hoàn toàn như mong đợi. Đối với hồ sơ, đầu ra dự kiến ​​là tất nhiên 'D3nnis'. (user.name đầu tiên được thay thế bằng chuỗi 'Dennis' và sau đó được chuyển đến hàm str_replace()).

Tôi nghi ngờ rằng nó có liên quan đến quyền ưu tiên. Nhưng tôi không thể hình dung những gì tôi nên thay đổi để làm điều này. Tài liệu Lemon rất thưa thớt không phải là sự giúp đỡ rất lớn.

Bất kỳ trợ giúp nào sẽ được đánh giá rất nhiều! Cảm ơn

Trả lời

1

Tôi dường như đã tìm thấy câu trả lời cho câu hỏi của mình.

Khi tôi thay đổi ngữ pháp của tôi để:

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

Có vẻ như để làm việc như mong đợi.
Vấn đề là tôi đã tạo một sự mơ hồ trong ngữ pháp đầu tiên:

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

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

Tôi sẽ để lại câu hỏi và trả lời ở đây để những người khác có thể được hưởng lợi từ những sai lầm của tôi :) Nếu ai đó có bất cứ điều gì để chia sẻ, xin vui lòng làm .