https://github.com/tenderlove/nokogiri/blob/master/lib/nokogiri/css/xpath_visitor.rb

@param $expr
@param bool $last
@return string
164817
protected function _selector_an_plus_b($expr, $last = false)
    {
        $expr = preg_replace("/\s/", "", $expr);
        if (!preg_match("/^(?P<a>-?[0-9]*)?n(?P<b>[-+]?[0-9]+)?$/", $expr, $matches)) {
            return "false()";
        }

        $a = ((isset($matches["a"]) && $matches["a"] !== "") ? intval($matches["a"]) : 1);
        $b = ((isset($matches["b"]) && $matches["b"] !== "") ? intval($matches["b"]) : 0);

        $position = ($last ? "(last()-position()+1)" : "position()");

        if ($b == 0) {
            return "($position mod $a) = 0";
        } else {
            $compare = (($a < 0) ? "<=" : ">=");
            $b2 = -$b;
            if ($b2 >= 0) {
                $b2 = "+$b2";
            }
            return "($position $compare $b) and ((($position $b2) mod " . abs($a) . ") = 0)";
        }
    }
965574
public function xpathQuery(string $expression, \DOMNode $context_node=null)
    {
        if ($this->dom_xpath) {
            $node_list = $this->dom_xpath->query($expression, $context_node);

            if ($node_list instanceof \DOMNodeList) {
                return $node_list;
            } elseif ($node_list === false && $context_node) {
                throw new \Exception('Expression '.$expression.' is malformed or contextnode is invalid.');
            } elseif ($node_list === false) {
                throw new \Exception('Expression '.$expression.' is malformed.');
            }
        }

        return false;
    }
1088478
public function last($selector=null)
    {
        $result = $this[$this->length-1];
        if ($selector) {
            $result = $result->filter($selector);
        }
        return $result;
    }
1300922
public function leaveExpression(Expression $expr)
    {
        if ($expr instanceof OrX || $expr instanceof AndX) {
            $hash = spl_object_hash($expr);

            if ($expr instanceof OrX) {
                $composite = $this->qb->expr()->orX();
                $composite->addMultiple($this->map[$hash]);
            } else {
                $composite = $this->qb->expr()->andX();
                $composite->addMultiple($this->map[$hash]);
            }

            unset($this->hashes[array_search($hash, $this->hashes)]);

            if (!count($this->hashes)) {
                $this->qb->andWhere($composite);
            } else {
                $lastHash = end($this->hashes);

                $this->map[$lastHash][] = $composite;
            }
        }

        return $expr;
    }
1286473
public static function isExpressionNumeric($expr)
	{
		// Trim the expression and remove parentheses that are not part of a function call. PCRE
		// does not support lookbehind assertions of variable length so we have to flip the string.
		// We exclude the XPath operator "div" (flipped into "vid") to avoid false positives
		$expr = strrev(preg_replace('(\\((?!\\s*(?!vid(?!\\w))\\w))', ' ', strrev($expr)));
		$expr = str_replace(')', ' ', $expr);
		if (preg_match('(^\\s*([$@][-\\w]++|-?\\.\\d++|-?\\d++(?:\\.\\d++)?)(?>\\s*(?>[-+*]|div)\\s*(?1))++\\s*$)', $expr))
		{
			return true;
		}

		return false;
	}
745218
private function exprStatement() {
    $node = new ExpressionStatementNode();
    $this->matchDocComment($node);
    $node->addChild($this->expr(), 'expression');
    $this->endStatement($node);
    return $node;
  }
1162339
protected function evaluateExpression($expr)
	{
		$original = $expr;
		foreach ($this->getOptimizationPasses() as $regexp => $methodName)
		{
			$regexp = str_replace(' ', '\\s*', $regexp);
			$expr   = preg_replace_callback($regexp, [$this, $methodName], $expr);
		}

		return ($expr === $original) ? $expr : $this->evaluateExpression(trim($expr));
	}
454293
protected function matchXPathForExport($expr)
	{
		$tokenExprs = [
			'(?<current>\\bcurrent\\(\\))',
			'(?<param>\\$\\w+)',
			'(?<fragment>"[^"]*"|\'[^\']*\'|.)'
		];
		preg_match_all('(' . implode('|', $tokenExprs) . ')s', $expr, $matches, PREG_SET_ORDER);

		// Merge fragment tokens
		$i = count($matches);
		while (--$i > 0)
		{
			if (isset($matches[$i]['fragment'], $matches[$i - 1]['fragment']))
			{
				$matches[$i - 1]['fragment'] .= $matches[$i]['fragment'];
				unset($matches[$i]);
			}
		}

		return array_values($matches);
	}
421360
public function matchExpr() : QueryExpr
    {
        $expr = new QueryExpr($this->dm);
        $expr->setClassMetadata($this->class);

        return $expr;
    }
419927
public function get($expr, $unique = false)
    {
        if ((($exprs = $this->normalizedFirst($expr)) !== false) &&
            (is_array($exprs) || $exprs instanceof \Traversable)
        ) {
            $values = array();

            foreach ($exprs as $expr) {
                $o =& $this->data;
                $keys = preg_split(
                    "/([\"'])?\]\[([\"'])?/",
                    preg_replace(array("/^\\$\[[\"']?/", "/[\"']?\]$/"), "", $expr)
                );

                for ($i = 0; $i < count($keys); $i++) {
                    $o =& $o[$keys[$i]];
                }

                $values[] = & $o;
            }

            if (true === $unique) {
                if (!empty($values) && is_array($values[0])) {
                    array_walk($values, function(&$value) {
                        $value = json_encode($value);
                    });

                    $values = array_unique($values);
                    array_walk($values, function(&$value) {
                        $value = json_decode($value, true);
                    });

                    return array_values($values);
                }

                return array_unique($values);
            }

            return $values;
        }

        return self::$emptyArray;
    }
281576
public function buildExpression(Expression $expr = null)
    {
        if (!$this->defaultExpression) {
            $this->defaultExpression = Expr::method('isEnabled', Expr::same(true))
                ->andMethod('getTypeName', Expr::same(DiscoveryUrlGenerator::BINDING_TYPE))
                ->andMethod('getBinding', Expr::method('getQuery', Expr::endsWith('{,/**/*}')));
        }

        if (!$expr) {
            return $this->defaultExpression;
        }

        $traverser = new ExpressionTraverser();
        $traverser->addVisitor($this);

        return $this->defaultExpression->andX($traverser->traverse($expr));
    }
465035
private function forExpr(ForNode $parent, $terminator, $property_name, $is_last = FALSE, $terminator_name = NULL) {
    if ($this->tryMatch($terminator, $parent)) {
      $parent->addChild(new CommaListNode(), $property_name);
      return;
    }
    $parent->addChild($this->exprList(), $property_name);
    $this->mustMatch($terminator, $parent, $terminator_name, $is_last, FALSE);
  }
1188736
public function get($xpathExpression, $alwaysReturnArray = false)
    {
        if ($this->useCaching === true && $alwaysReturnArray === true) {
            if (!array_key_exists($xpathExpression, $this->cache['alwaysArray'])) {
                $this->cache['alwaysArray'][$xpathExpression] = $this->getFromDOMDocument($xpathExpression, $alwaysReturnArray);
            }

            return $this->cache['alwaysArray'][$xpathExpression];
        } elseif ($this->useCaching === true) {
            if (!array_key_exists($xpathExpression, $this->cache['optionalArray'])) {
                $this->cache['optionalArray'][$xpathExpression] = $this->getFromDOMDocument($xpathExpression, $alwaysReturnArray);
            }

            return $this->cache['optionalArray'][$xpathExpression];
        } else {
            return $this->getFromDOMDocument($xpathExpression, $alwaysReturnArray);
        }
    }
640771
public static function convertExpr($expr)
    {
        preg_match_all('/(==|!=|<=|>=|&&|\|\||<<|>>|[-!?:+*\/&|^~%<>()n]|[0-9]+)/', $expr, $matches);
        $tokens = $matches[0];
        $expr = '';
        $stack = array();
        foreach ($tokens as $token) {
            if ($token == 'n') {
                $expr .= '$n';
            } elseif ($token == ':') {
                array_push($stack, ':');
                $expr .= ':(';
            } elseif ($token == '(') {
                array_push($stack, '(');
                $expr .= '(';
            } elseif ($token == ')') {
                while (count($stack) > 0) {
                    $c = array_pop($stack);
                    $expr .= ')';
                    if ($c == '(') {
                        break;
                    }
                }
            } else {
                $expr .= $token;
            }
        }
        while (count($stack) > 0) {
            array_pop($stack);
            $expr .= ')';
        }
        return $expr;
    }
1279890
private function getLastUseEndPos(int $lastUsePos): int
    {
        $file = $this->getFile();
        $tokens = $file->getTokens();

        $lastUseEndPos = TokenHelper::findNextLocal(
            $file,
            [T_SEMICOLON, T_OPEN_CURLY_BRACKET],
            $lastUsePos + 1
        );

        if ($tokens[$lastUseEndPos]['code'] === T_OPEN_CURLY_BRACKET) {
            $lastUseEndPos = $tokens[$lastUseEndPos]['bracket_closer'];
        }

        return $lastUseEndPos;
    }
972470
protected function compileInclude($expr)
    {
        $expr = explode(',', $this->stripParentheses($expr), 2);
        $vars = isset($expr[1]) ? trim($expr[1]) : '';
        if (empty($vars)) {
            return "<?php echo \$this->make({$expr[0]}, get_defined_vars()); ?>";
        }
        else {
            $result = "<?php echo \$this->make({$expr[0]}, array_merge(get_defined_vars(), {$vars})); ?>";
            return $result;
        }
    }
1166692
protected function toExpr(Key $expr)
    {
        $left = $expr->getKey();
        $paramName = uniqid('K');

        if (strpos($left, '.') !== false) {
            $left = $this->shouldJoin($left);
        } else {
            $left = $this->getRootAlias().'.'.$left;
        }

        $comparator = $expr->getExpression();

        if ($comparator instanceof StartsWith) {
            $right = $comparator->getAcceptedPrefix();
        } elseif($comparator instanceof EndsWith){
            $right = $comparator->getAcceptedSuffix();
        } else {
            $right = $comparator->getComparedValue();
        }

        if ($comparator instanceof ConstraintInterface) {
            $left = $comparator->getLeft($left);
        }

        $this->qb->setParameter($paramName, $right);

        if ($comparator instanceof NotEquals) {
            return $this->qb->expr()->neq($left, ':'.$paramName);
        } elseif ($comparator instanceof GreaterThan) {
            return $this->qb->expr()->gt($left, ':'.$paramName);
        } elseif ($comparator instanceof GreaterThanEqual) {
            return $this->qb->expr()->gte($left, ':'.$paramName);
        } elseif ($comparator instanceof LessThan) {
            return $this->qb->expr()->lt($left, ':'.$paramName);
        } elseif ($comparator instanceof LessThanEqual) {
            return $this->qb->expr()->lte($left, ':'.$paramName);
        } elseif ($comparator instanceof StartsWith) {
            $this->qb->setParameter($paramName, $right.'%');
            return $this->qb->expr()->like($left, ':'.$paramName);
        } elseif ($comparator instanceof EndsWith) {
            $this->qb->setParameter($paramName, '%'.$right);
            return $this->qb->expr()->like($left, ':'.$paramName);
        } elseif ($comparator instanceof Contains) {
            $this->qb->setParameter($paramName, '%'.$right.'%');
            return $this->qb->expr()->like($left,':'.$paramName);
        } elseif ($comparator instanceof In) {
            if (is_array($right)) {
                return $this->qb->expr()->in($left,':'.$paramName);
            } else {
                $this->qb->setParameter($paramName, '%'.$right.'%');
                return $this->qb->expr()->like($left,':'.$paramName);
            }
        }

        return $this->qb->expr()->eq($left, ':'.$paramName);
    }