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

$resultus3r.nam3」です。期待したほどではありません。記録として、予想される出力はもちろん「D3nnis」です。(user.nameは最初に文字列 'Dennis' に置き換えられ、その後関数に渡されstr_replace()ます)。

優先度に関係があると思います。しかし、これを行うために何を変更すればよいかわかりません。非常にまばらな Lemon のドキュメントはあまり役に立ちません。

どんな助けでも大歓迎です!ありがとう

4

1 に答える 1

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

他の人が私の過ちから利益を得ることができるように、質問と回答をここに残しておきます:)誰かが何か共有することがあれば、してください.

于 2012-04-10T13:32:52.380 に答える