【问题标题】:Troubles with lemon grammar (precedence?)柠檬语法的问题(优先级?)
【发布时间】:2012-04-10 12:36:37
【问题描述】:

我为支持函数调用而创建的简单语法遇到了问题。
我正在使用 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 如下:'Dennis'。生活是美好的。

但是当我提供一个 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”。 (user.name first 被字符串 'Dennis' 替换,然后传递给 str_replace() 函数)。

我怀疑它与优先级有关。但我不知道我应该改变什么来做到这一点。非常稀疏的 Lemon 文档并没有太大的帮助。

任何帮助将不胜感激! 谢谢

【问题讨论】:

    标签: php parser-generator lemon


    【解决方案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]; 
    }
    

    我将把问题和答案留在这里,这样其他人可能会从我的错误中受益:) 如果有人有什么要分享的,请做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多