2013-09-01 20:41:49 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is part of the Symfony package.
|
|
|
|
*
|
|
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
|
|
*
|
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
* file that was distributed with this source code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Symfony\Component\ExpressionLanguage;
|
|
|
|
|
2013-09-06 07:52:21 +01:00
|
|
|
use Symfony\Component\ExpressionLanguage\Node\Node;
|
|
|
|
|
2013-09-01 20:41:49 +01:00
|
|
|
/**
|
|
|
|
* Allows to compile and evaluate expressions written in your own DSL.
|
|
|
|
*
|
|
|
|
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
|
*/
|
|
|
|
class ExpressionLanguage
|
|
|
|
{
|
|
|
|
private $lexer;
|
|
|
|
private $parser;
|
|
|
|
private $compiler;
|
|
|
|
private $cache;
|
|
|
|
|
|
|
|
protected $functions;
|
|
|
|
|
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
$this->functions = array();
|
|
|
|
$this->registerFunctions();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compiles an expression source code.
|
|
|
|
*
|
2013-09-20 14:35:54 +01:00
|
|
|
* @param Expression|string $expression The expression to compile
|
|
|
|
* @param array $names An array of valid names
|
2013-09-01 20:41:49 +01:00
|
|
|
*
|
|
|
|
* @return string The compiled PHP source code
|
|
|
|
*/
|
|
|
|
public function compile($expression, $names = array())
|
|
|
|
{
|
2013-09-20 14:35:54 +01:00
|
|
|
return $this->getCompiler()->compile($this->parse($expression, $names)->getNodes())->getSource();
|
2013-09-01 20:41:49 +01:00
|
|
|
}
|
|
|
|
|
2013-09-06 07:52:21 +01:00
|
|
|
/**
|
|
|
|
* Evaluate an expression.
|
|
|
|
*
|
|
|
|
* @param Expression|string $expression The expression to compile
|
|
|
|
* @param array $values An array of values
|
|
|
|
*
|
|
|
|
* @return string The result of the evaluation of the expression
|
|
|
|
*/
|
2013-09-01 20:41:49 +01:00
|
|
|
public function evaluate($expression, $values = array())
|
|
|
|
{
|
2013-09-20 14:35:54 +01:00
|
|
|
return $this->parse($expression, array_keys($values))->getNodes()->evaluate($this->functions, $values);
|
2013-09-06 07:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parses an expression.
|
|
|
|
*
|
|
|
|
* @param Expression|string $expression The expression to parse
|
|
|
|
*
|
2013-09-20 14:35:54 +01:00
|
|
|
* @return ParsedExpression A ParsedExpression instance
|
2013-09-06 07:52:21 +01:00
|
|
|
*/
|
|
|
|
public function parse($expression, $names)
|
|
|
|
{
|
2013-09-20 14:35:54 +01:00
|
|
|
if ($expression instanceof ParsedExpression) {
|
|
|
|
return $expression;
|
|
|
|
}
|
|
|
|
|
2013-09-06 07:52:21 +01:00
|
|
|
$key = $expression.'//'.implode('-', $names);
|
|
|
|
|
|
|
|
if (!isset($this->cache[$key])) {
|
2013-09-20 14:35:54 +01:00
|
|
|
$nodes = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names);
|
|
|
|
$this->cache[$key] = new ParsedExpression((string) $expression, $nodes);
|
2013-09-06 07:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return $this->cache[$key];
|
2013-09-01 20:41:49 +01:00
|
|
|
}
|
|
|
|
|
2013-09-20 15:16:44 +01:00
|
|
|
/**
|
|
|
|
* Registers a function.
|
|
|
|
*
|
|
|
|
* @param string $name The function name
|
|
|
|
* @param callable $compiler A callable able to compile the function
|
|
|
|
* @param callable $evaluator A callable able to evaluate the function
|
|
|
|
*/
|
|
|
|
public function register($name, $compiler, $evaluator)
|
2013-09-01 20:41:49 +01:00
|
|
|
{
|
|
|
|
$this->functions[$name] = array('compiler' => $compiler, 'evaluator' => $evaluator);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function registerFunctions()
|
|
|
|
{
|
2013-09-20 15:16:44 +01:00
|
|
|
$this->register('constant', function ($constant) {
|
2013-09-01 20:41:49 +01:00
|
|
|
return sprintf('constant(%s)', $constant);
|
|
|
|
}, function (array $values, $constant) {
|
|
|
|
return constant($constant);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getLexer()
|
|
|
|
{
|
|
|
|
if (null === $this->lexer) {
|
|
|
|
$this->lexer = new Lexer();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->lexer;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getParser()
|
|
|
|
{
|
|
|
|
if (null === $this->parser) {
|
|
|
|
$this->parser = new Parser($this->functions);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->parser;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getCompiler()
|
|
|
|
{
|
|
|
|
if (null === $this->compiler) {
|
|
|
|
$this->compiler = new Compiler($this->functions);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->compiler->reset();
|
|
|
|
}
|
|
|
|
}
|