Yaffs site version 1.1
[yaffs-website] / vendor / symfony / expression-language / ExpressionLanguage.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\ExpressionLanguage;
13
14 use Symfony\Component\ExpressionLanguage\ParserCache\ArrayParserCache;
15 use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
16
17 /**
18  * Allows to compile and evaluate expressions written in your own DSL.
19  *
20  * @author Fabien Potencier <fabien@symfony.com>
21  */
22 class ExpressionLanguage
23 {
24     /**
25      * @var ParserCacheInterface
26      */
27     private $cache;
28     private $lexer;
29     private $parser;
30     private $compiler;
31
32     protected $functions = array();
33
34     /**
35      * @param ParserCacheInterface                  $cache
36      * @param ExpressionFunctionProviderInterface[] $providers
37      */
38     public function __construct(ParserCacheInterface $cache = null, array $providers = array())
39     {
40         $this->cache = $cache ?: new ArrayParserCache();
41         $this->registerFunctions();
42         foreach ($providers as $provider) {
43             $this->registerProvider($provider);
44         }
45     }
46
47     /**
48      * Compiles an expression source code.
49      *
50      * @param Expression|string $expression The expression to compile
51      * @param array             $names      An array of valid names
52      *
53      * @return string The compiled PHP source code
54      */
55     public function compile($expression, $names = array())
56     {
57         return $this->getCompiler()->compile($this->parse($expression, $names)->getNodes())->getSource();
58     }
59
60     /**
61      * Evaluate an expression.
62      *
63      * @param Expression|string $expression The expression to compile
64      * @param array             $values     An array of values
65      *
66      * @return string The result of the evaluation of the expression
67      */
68     public function evaluate($expression, $values = array())
69     {
70         return $this->parse($expression, array_keys($values))->getNodes()->evaluate($this->functions, $values);
71     }
72
73     /**
74      * Parses an expression.
75      *
76      * @param Expression|string $expression The expression to parse
77      * @param array             $names      An array of valid names
78      *
79      * @return ParsedExpression A ParsedExpression instance
80      */
81     public function parse($expression, $names)
82     {
83         if ($expression instanceof ParsedExpression) {
84             return $expression;
85         }
86
87         asort($names);
88         $cacheKeyItems = array();
89
90         foreach ($names as $nameKey => $name) {
91             $cacheKeyItems[] = is_int($nameKey) ? $name : $nameKey.':'.$name;
92         }
93
94         $key = $expression.'//'.implode('|', $cacheKeyItems);
95
96         if (null === $parsedExpression = $this->cache->fetch($key)) {
97             $nodes = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names);
98             $parsedExpression = new ParsedExpression((string) $expression, $nodes);
99
100             $this->cache->save($key, $parsedExpression);
101         }
102
103         return $parsedExpression;
104     }
105
106     /**
107      * Registers a function.
108      *
109      * @param string   $name      The function name
110      * @param callable $compiler  A callable able to compile the function
111      * @param callable $evaluator A callable able to evaluate the function
112      *
113      * @throws \LogicException when registering a function after calling evaluate(), compile() or parse()
114      *
115      * @see ExpressionFunction
116      */
117     public function register($name, $compiler, $evaluator)
118     {
119         if (null !== $this->parser) {
120             throw new \LogicException('Registering functions after calling evaluate(), compile() or parse() is not supported.');
121         }
122
123         $this->functions[$name] = array('compiler' => $compiler, 'evaluator' => $evaluator);
124     }
125
126     public function addFunction(ExpressionFunction $function)
127     {
128         $this->register($function->getName(), $function->getCompiler(), $function->getEvaluator());
129     }
130
131     public function registerProvider(ExpressionFunctionProviderInterface $provider)
132     {
133         foreach ($provider->getFunctions() as $function) {
134             $this->addFunction($function);
135         }
136     }
137
138     protected function registerFunctions()
139     {
140         $this->register('constant', function ($constant) {
141             return sprintf('constant(%s)', $constant);
142         }, function (array $values, $constant) {
143             return constant($constant);
144         });
145     }
146
147     private function getLexer()
148     {
149         if (null === $this->lexer) {
150             $this->lexer = new Lexer();
151         }
152
153         return $this->lexer;
154     }
155
156     private function getParser()
157     {
158         if (null === $this->parser) {
159             $this->parser = new Parser($this->functions);
160         }
161
162         return $this->parser;
163     }
164
165     private function getCompiler()
166     {
167         if (null === $this->compiler) {
168             $this->compiler = new Compiler($this->functions);
169         }
170
171         return $this->compiler->reset();
172     }
173 }