Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
66.67% covered (warning)
66.67%
8 / 12
CRAP
92.70% covered (success)
92.70%
165 / 178
Parser
0.00% covered (danger)
0.00%
0 / 1
66.67% covered (warning)
66.67%
8 / 12
64.55
92.70% covered (success)
92.70%
165 / 178
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
30 / 30
 parse
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 lint
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
 doParse
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
8 / 8
 parseExpression
100.00% covered (success)
100.00%
1 / 1
6
100.00% covered (success)
100.00%
11 / 11
 getPrimary
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
12 / 12
 parseConditionalExpression
0.00% covered (danger)
0.00%
0 / 1
4.20
76.92% covered (warning)
76.92%
10 / 13
 parsePrimaryExpression
0.00% covered (danger)
0.00%
0 / 1
18
96.97% covered (success)
96.97%
32 / 33
 parseArrayExpression
0.00% covered (danger)
0.00%
0 / 1
4.01
91.67% covered (success)
91.67%
11 / 12
 parseHashExpression
0.00% covered (danger)
0.00%
0 / 1
11.54
61.90% covered (warning)
61.90%
13 / 21
 parsePostfixExpression
100.00% covered (success)
100.00%
1 / 1
9
100.00% covered (success)
100.00%
25 / 25
 parseArguments
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
8 / 8
<?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;
/**
 * Parsers a token stream.
 *
 * This parser implements a "Precedence climbing" algorithm.
 *
 * @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
 * @see http://en.wikipedia.org/wiki/Operator-precedence_parser
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Parser
{
    const OPERATOR_LEFT = 1;
    const OPERATOR_RIGHT = 2;
    private $stream;
    private $unaryOperators;
    private $binaryOperators;
    private $functions;
    private $names;
    private $lint;
    public function __construct(array $functions)
    {
        $this->functions = $functions;
        $this->unaryOperators = [
            'not' => ['precedence' => 50],
            '!' => ['precedence' => 50],
            '-' => ['precedence' => 500],
            '+' => ['precedence' => 500],
        ];
        $this->binaryOperators = [
            'or' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT],
            '||' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT],
            'and' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT],
            '&&' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT],
            '|' => ['precedence' => 16, 'associativity' => self::OPERATOR_LEFT],
            '^' => ['precedence' => 17, 'associativity' => self::OPERATOR_LEFT],
            '&' => ['precedence' => 18, 'associativity' => self::OPERATOR_LEFT],
            '==' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            '===' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            '!=' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            '!==' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            '<' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            '>' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            '>=' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            '<=' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            'not in' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            'in' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            'matches' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT],
            '..' => ['precedence' => 25, 'associativity' => self::OPERATOR_LEFT],
            '+' => ['precedence' => 30, 'associativity' => self::OPERATOR_LEFT],
            '-' => ['precedence' => 30, 'associativity' => self::OPERATOR_LEFT],
            '~' => ['precedence' => 40, 'associativity' => self::OPERATOR_LEFT],
            '*' => ['precedence' => 60, 'associativity' => self::OPERATOR_LEFT],
            '/' => ['precedence' => 60, 'associativity' => self::OPERATOR_LEFT],
            '%' => ['precedence' => 60, 'associativity' => self::OPERATOR_LEFT],
            '**' => ['precedence' => 200, 'associativity' => self::OPERATOR_RIGHT],
        ];
    }
    /**
     * Converts a token stream to a node tree.
     *
     * The valid names is an array where the values
     * are the names that the user can use in an expression.
     *
     * If the variable name in the compiled PHP code must be
     * different, define it as the key.
     *
     * For instance, ['this' => 'container'] means that the
     * variable 'container' can be used in the expression
     * but the compiled code will use 'this'.
     *
     * @return Node\Node A node tree
     *
     * @throws SyntaxError
     */
    public function parse(TokenStream $stream, array $names = [])
    {
        $this->lint = false;
        return $this->doParse($stream, $names);
    }
    /**
     * Validates the syntax of an expression.
     *
     * The syntax of the passed expression will be checked, but not parsed.
     * If you want to skip checking dynamic variable names, pass `null` instead of the array.
     *
     * @throws SyntaxError When the passed expression is invalid
     */
    public function lint(TokenStream $stream, ?array $names = []): void
    {
        $this->lint = true;
        $this->doParse($stream, $names);
    }
    /**
     * @throws SyntaxError
     */
    private function doParse(TokenStream $stream, ?array $names = []): Node\Node
    {
        $this->stream = $stream;
        $this->names = $names;