Проблемы с лимонной грамматикой (приоритет?)
У меня проблемы с простой грамматикой, которую я создал для поддержки вызовов функций.
Я использую основанный на лимоне 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". (user.name сначала заменяется строкой 'Dennis', а затем передается str_replace()
функция).
Я подозреваю, что это как-то связано с приоритетом. Но я не могу понять, что я должен изменить, чтобы сделать это. Очень редкая документация по 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];
}
Я оставлю вопрос и отвечу здесь, чтобы другие могли извлечь выгоду из моих ошибок:) Если кому-то есть, чем поделиться, пожалуйста, сделайте.