Adds an expression parameter to the collection.

@param O\Expression     $expression
@param IParameterHasher $hasher
@param IFunction|null   $context
@param mixed            $data

@return void
320159
public function addExpression(
            O\Expression $expression,
            IParameterHasher $hasher,
            IFunction $context = null,
            $data = null
    ) {
        $this->parameters[] = new ExpressionParameter($expression, $hasher, $context, $data);
    }
324161
public function apply($builder, CriterionInterface $where): ?iterable
    {
        $expression = new Expression($builder, $where->getOperator(), $where->getValue());
        yield from $result = $expression->create($where->getField());

        if ($where->isAnd()) {
            $builder->andWhere($result->getReturn());
        } else {
            $builder->orWhere($result->getReturn());
        }
    }
913972
protected function compileForelse($expression)
    {
        $empty = '$__empty_'.++$this->forElseCounter;

        preg_match('/\( *(.*) +as *(.*)\)$/is', $expression, $matches);

        $iteratee = trim($matches[1]);

        $iteration = trim($matches[2]);

        $initLoop = "\$__currentLoopData = {$iteratee}; \$__env->addLoop(\$__currentLoopData);";

        $iterateLoop = '$__env->incrementLoopIndices(); $loop = $__env->getLastLoop();';

        return "<?php {$empty} = true; {$initLoop} foreach(\$__currentLoopData as {$iteration}): {$iterateLoop} {$empty} = false; ?>";
    }
1370786
public static function evaluateEelExpression($expression, EelEvaluatorInterface $eelEvaluator, array $contextVariables, array $defaultContextConfiguration = [])
    {
        $matches = null;
        if (!preg_match(Package::EelExpressionRecognizer, $expression, $matches)) {
            throw new Exception('The EEL expression "' . $expression . '" was not a valid EEL expression. Perhaps you forgot to wrap it in ${...}?', 1410441849);
        }

        $defaultContextVariables = self::getDefaultContextVariables($defaultContextConfiguration);
        $contextVariables = array_merge($defaultContextVariables, $contextVariables);

        if (isset($contextVariables['q'])) {
            throw new Exception('Context variable "q" not allowed, as it is already reserved for FlowQuery use.', 1410441819);
        }

        $contextVariables['q'] = function ($element) {
            return new FlowQuery\FlowQuery(is_array($element) || $element instanceof \Traversable ? $element : [$element]);
        };

        $context = new ProtectedContext($contextVariables);
        $context->whitelist('q');

        return $eelEvaluator->evaluate($matches['exp'], $context);
    }
470541
public static <T> void invoke(String expression,
                                  QueryExprInvoker<T> invoker,
                                  ExprApplier<T> exprApplier) {
        QueryExprInvoker.invoke(parse(expression), invoker, exprApplier);
    }
1318851
public function addExpression($expression)
    {
        if (!$this->expressions->contains($expression)) {
            $this->expressions[] = $expression;
        }

        return $this;
    }
141414
public function addExpression($name, $expression = null)
    {
        /** @type Field_Expression $f */
        $f = $this->add('Field_Expression', $name);

        return $f->set($expression);
    }
270719
protected function buildExpression($collection, $type = AndX::class)
    {
        $expressions = [];

        /** @var Expression $expression */
        foreach ($collection as $expression) {
            if (!$expression instanceof Expression) {
                throw new \Exception(sprintf('Expressions must be of type %s', Expression::class));
            }

            if (count($expression->getChildren())) {
                $expressions[] = $this->buildExpression($expression->getChildren(), $expression->getConstraint());
            } else {
                $expressions[] = $this->transform($expression);
            }
        }

        return new $type($expressions);
    }
1074688
final public static function simplifyAll(
            array $expressions,
            IEvaluationContext $context = null
    ) {
        $simplifiedExpressions = [];
        foreach ($expressions as $expression) {
            $simplifiedExpressions[] = $expression->simplify($context);
        }

        return $simplifiedExpressions;
    }
599009
public function evaluate(array $values, Context $context, Token $token)
    {
        if (count($values) !== $this->getOperands()) {
            throw new ExpressionException('Invalid number of operands for operator.',
              $this, $values);
        }
        $evaluator = $this->evaluator;
        return (string)$evaluator($values, $context, $token);
    }
1298556
public function onPropertyAccessExpression($expression)
    {
        $parent = $expression;
        $variable = null;
        do {
            $variable = $parent->getResourceProperty()->getName() . self::MEMBER_ACCESS . $variable;
            $parent = $parent->getParent();
        } while ($parent != null);
        $variable = rtrim($variable, self::MEMBER_ACCESS);
        $variable = $this->getIteratorName() . self::MEMBER_ACCESS . $variable;
        return $variable;
    }
946007
protected function _compileExpressionTerms(
        ExpressionInterface $expression,
        array $renderedTerms,
        $context = null
    ) {
        $opStr = $this->_getOperatorString();
        $glueStr = sprintf(' %s ', $opStr);
        $joined = implode($glueStr, $renderedTerms);

        return sprintf('(%s)', $joined);
    }
643810
public function add(Expression $expr)
    {
        if(!$expr instanceof OrderExpression) {
            throw new \InvalidArgumentException('OrderClause only accept OrderExpression as its part.');
        }

        // internal Expression has to be an unique by field 
        $this->expressions[$expr->getField()->getName()] = $expr;

        return $this;
    }
333191
public static void onLogicalExpression(Expression expression, EntityMetadata m, KunderaMetadata kunderaMetadata,
            KunderaQuery kunderaQuery)
    {
        if (expression instanceof OrExpression)
        {
            kunderaQuery.addFilterClause("(");
        }

        traverse(((LogicalExpression) expression).getLeftExpression(), m, kunderaMetadata, kunderaQuery, false);

        if (expression instanceof OrExpression)
        {
            kunderaQuery.addFilterClause(")");
        }

        kunderaQuery.addFilterClause(((LogicalExpression) expression).getIdentifier());

        if (expression instanceof OrExpression)
        {
            kunderaQuery.addFilterClause("(");
        }

        traverse(((LogicalExpression) expression).getRightExpression(), m, kunderaMetadata, kunderaQuery, false);

        if (expression instanceof OrExpression)
        {
            kunderaQuery.addFilterClause(")");
        }
    }
1181179
public function applyFilters(CompositeExpression $expression, string $tableOrAlias, iterable $filters): self
    {
        foreach ($filters as $columnName => $operationsWithArgs) {
            assert(
                is_string($columnName) === true && empty($columnName) === false,
                "Haven't you forgotten to specify a column name in a relationship that joins `$tableOrAlias` table?"
            );
            $fullColumnName = $this->quoteDoubleIdentifier($tableOrAlias, $columnName);
            foreach ($operationsWithArgs as $operation => $arguments) {
                assert(
                    is_iterable($arguments) === true || is_array($arguments) === true,
                    "Operation arguments are missing for `$columnName` column. " .
                    'Use an empty array as an empty argument list.'
                );
                $expression->add($this->createFilterExpression($fullColumnName, $operation, $arguments));
            }
        }

        return $this;
    }
847208
protected static function _tokenize($expression_src)
    {
        // Child selectors
        $expression = str_replace('>', '/', $expression_src);

        // IDs
        $expression = preg_replace('|#([a-z][a-z0-9_-]*)|i', "[@id='$1']", $expression);
        $expression = preg_replace('|(?<![a-z0-9_-])(\[@id=)|i', '*$1', $expression);

        // arbitrary attribute strict equality
        $expression = preg_replace_callback(
            '|\[@?([a-z0-9_-]*)([~\*\^\$\|\!])?=([^\[]+)\]|i',
            static function ($matches) {
                $attr = strtolower($matches[1]);
                $type = $matches[2];
                $val = trim($matches[3], "'\" \t");

                $field = ($attr === '' ? 'text()' : '@' . $attr);

                $items = [];
                foreach (explode(strpos($val, '|') !== false ? '|' : '&', $val) as $word) {
                    if ($type === '') {
                        $items[] = "$field='$word'";
                    } elseif ($type === '~') {
                        $items[] = "contains(concat(' ', normalize-space($field), ' '), ' $word ')";
                    } elseif ($type === '|') {
                        $item = "$field='$word' or starts-with($field,'$word-')";
                        $items[] = $word === $val ? $item : "($item)";
                    } elseif ($type === '!') {
                        $item = "not($field) or $field!='$word'";
                        $items[] = $word === $val ? $item : "($item)";
                    } else {
                        $items[] = ['*' => 'contains', '^' => 'starts-with', '$' => 'ends-with'][$type] . "($field, '$word')";
                    }
                }
                return '[' . implode(strpos($val, '|') !== false ? ' or ' : ' and ', $items) . ']';
            },
            $expression
        );

        //attribute contains specified content
        $expression = preg_replace_callback(
            '|\[(!?)([a-z][a-z0-9_-\|&]*)\]|i',
            static function ($matches) {
                $val = $matches[2];
                $op = strpos($val, '|') !== false ? '|' : '&';

                $items = [];
                foreach (explode($op, $val) as $word) {
                    $items[] = '@' . $word;
                }

                $r = '[' . implode($op === '|' ? ' or ' : ' and ', $items) . ']';
                return $matches[1] === '!' ? "not($r)" : $r;
            },
            $expression
        );
        // Classes
        if (false === strpos($expression, '[@')) {
            $expression = preg_replace(
                '|\.([a-z][a-z0-9_-]*)|i',
                "[contains(concat(' ', normalize-space(@class), ' '), ' \$1 ')]",
                $expression
            );
        }

        /** ZF-9764 -- remove double asterisk */
        $expression = str_replace('**', '*', $expression);

        return $expression;
    }
216318
public function compileHashTraverse($expression, CompilationContext $compilationContext, Variable $exprVariable)
    {
        /*
         * Initialize 'key' variable
         */
        if (isset($this->statement['key'])) {
            if ('_' != $this->statement['key']) {
                $keyVariable = $compilationContext->symbolTable->getVariableForWrite($this->statement['key'], $compilationContext, $this->statement['expr']);
                if ('variable' != $keyVariable->getType()) {
                    throw new CompilerException('Cannot use variable: '.$this->statement['key'].' type: '.$keyVariable->getType().' as key in hash traversal', $this->statement['expr']);
                }
            } else {
                $keyVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
            }

            $keyVariable->setMustInitNull(true);
            $keyVariable->setIsInitialized(true, $compilationContext);
            $keyVariable->setDynamicTypes('undefined');
        }

        /*
         * Initialize 'value' variable
         */
        if (isset($this->statement['value'])) {
            if ('_' != $this->statement['value']) {
                $variable = $compilationContext->symbolTable->getVariableForWrite($this->statement['value'], $compilationContext, $this->statement['expr']);
                if ('variable' != $variable->getType()) {
                    throw new CompilerException('Cannot use variable: '.$this->statement['value'].' type: '.$variable->getType().' as value in hash traversal', $this->statement['expr']);
                }
            } else {
                $variable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
            }

            $variable->setMustInitNull(true);
            $variable->setIsInitialized(true, $compilationContext);
            $variable->increaseVariantIfNull();
            $variable->setDynamicTypes('undefined');
        }

        /*
         * Variables are initialized in a different way inside cycle
         */
        ++$compilationContext->insideCycle;

//         $compilationContext->headersManager->add('kernel/hash');

        $duplicateHash = '0';
        $duplicateKey = true;

        /**
         * We have to check if hashes are modified within the for's block.
         */
        $st = null;
        if (isset($this->statement['statements'])) {
            /**
             * Create the statements block here to obtain the last use line.
             */
            $st = new StatementsBlock($this->statement['statements']);

            $detector = new ForValueUseDetector();
            if ($detector->detect($exprVariable->getName(), $this->statement['statements'])) {
                $duplicateHash = '1';
            }

            /*
             * Detect if the key is modified or passed to an external scope
             */
            if (isset($this->statement['key'])) {
                if (!$keyVariable->isTemporal()) {
                    $detector->setDetectionFlags(ForValueUseDetector::DETECT_ALL);
                    if ($detector->detect($keyVariable->getName(), $this->statement['statements'])) {
                        $duplicateKey = true;
                    }
                }
            }
        }

        $compilationContext->backend->forStatement(
            $exprVariable,
            isset($this->statement['key']) ? $keyVariable : null,
            isset($this->statement['value']) ? $variable : null,
            $duplicateKey,
            $duplicateHash,
            $this->statement,
            $st,
            $compilationContext
        );

        /*
         * Restore the cycle counter
         */
        --$compilationContext->insideCycle;
    }