1
0
mirror of synced 2025-01-29 19:41:45 +03:00

Improved code readability. Improved performance.

This commit is contained in:
Guilherme Blanco 2011-11-30 09:57:54 -05:00
parent 356f5874bf
commit 5b73f1bd82
5 changed files with 250 additions and 214 deletions

View File

@ -23,8 +23,9 @@ namespace Doctrine\ORM\Internal;
* The CommitOrderCalculator is used by the UnitOfWork to sort out the
* correct order in which changes to entities need to be persisted.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
*/
class CommitOrderCalculator
{
@ -60,10 +61,9 @@ class CommitOrderCalculator
{
// Check whether we need to do anything. 0 or 1 node is easy.
$nodeCount = count($this->_classes);
if ($nodeCount == 0) {
return array();
} else if ($nodeCount == 1) {
return array_values($this->_classes);
if ($nodeCount <= 1) {
return ($nodeCount == 1) ? array_values($this->_classes) : array();
}
// Init

View File

@ -36,11 +36,6 @@ use PDO,
* @author Guilherme Blanco <guilhermeblanoc@hotmail.com>
*
* @internal Highly performance-sensitive code.
*
* @todo General behavior is "wrong" if you define an alias to selected IdentificationVariable.
* Example: SELECT u AS user FROM User u
* The result should contains an array where each array index is an array: array('user' => [User object])
* Problem must be solved somehow by removing the isMixed in ResultSetMapping
*/
class ObjectHydrator extends AbstractHydrator
{

View File

@ -164,7 +164,7 @@ final class PersistentCollection implements Collection
// If _backRefFieldName is set and its a one-to-many association,
// we need to set the back reference.
if ($this->backRefFieldName && $this->association['type'] == ClassMetadata::ONE_TO_MANY) {
if ($this->backRefFieldName && $this->association['type'] === ClassMetadata::ONE_TO_MANY) {
// Set back reference to owner
$this->typeClass->reflFields[$this->backRefFieldName]->setValue(
$element, $this->owner
@ -189,7 +189,7 @@ final class PersistentCollection implements Collection
// If _backRefFieldName is set, then the association is bidirectional
// and we need to set the back reference.
if ($this->backRefFieldName && $this->association['type'] == ClassMetadata::ONE_TO_MANY) {
if ($this->backRefFieldName && $this->association['type'] === ClassMetadata::ONE_TO_MANY) {
// Set back reference to owner
$this->typeClass->reflFields[$this->backRefFieldName]->setValue(
$element, $this->owner
@ -304,7 +304,7 @@ final class PersistentCollection implements Collection
if ($this->association !== null &&
$this->association['isOwningSide'] &&
$this->association['type'] == ClassMetadata::MANY_TO_MANY &&
$this->association['type'] === ClassMetadata::MANY_TO_MANY &&
$this->em->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify()) {
$this->em->getUnitOfWork()->scheduleForDirtyCheck($this->owner);
}
@ -425,7 +425,7 @@ final class PersistentCollection implements Collection
$this->changed();
if ($this->association !== null &&
$this->association['type'] == ClassMetadata::ONE_TO_MANY &&
$this->association['type'] === ClassMetadata::ONE_TO_MANY &&
$this->association['orphanRemoval']) {
$this->em->getUnitOfWork()->scheduleOrphanRemoval($element);
}
@ -448,7 +448,7 @@ final class PersistentCollection implements Collection
*/
public function contains($element)
{
if ( ! $this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
if ( ! $this->initialized && $this->association['fetch'] === Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
$persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association);
return $this->coll->contains($element) || $persister->contains($this, $element);
@ -514,7 +514,7 @@ final class PersistentCollection implements Collection
*/
public function count()
{
if ( ! $this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
if ( ! $this->initialized && $this->association['fetch'] === Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
$persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association);
return $persister->count($this) + ($this->isDirty ? $this->coll->count() : 0);
@ -630,7 +630,7 @@ final class PersistentCollection implements Collection
$uow = $this->em->getUnitOfWork();
if ($this->association['type'] == ClassMetadata::ONE_TO_MANY && $this->association['orphanRemoval']) {
if ($this->association['type'] === ClassMetadata::ONE_TO_MANY && $this->association['orphanRemoval']) {
// we need to initialize here, as orphan removal acts like implicit cascadeRemove,
// hence for event listeners we need the objects in memory.
$this->initialize();

View File

@ -49,7 +49,7 @@ class Lexer extends \Doctrine\Common\Lexer
const T_PLUS = 17;
const T_OPEN_CURLY_BRACE = 18;
const T_CLOSE_CURLY_BRACE = 19;
// All tokens that are also identifiers should be >= 100
const T_IDENTIFIER = 100;
const T_ALL = 101;
@ -133,7 +133,7 @@ class Lexer extends \Doctrine\Common\Lexer
'\?[0-9]*|:[a-z]{1}[a-z0-9_]{0,}'
);
}
/**
* @inheritdoc
*/
@ -149,50 +149,58 @@ class Lexer extends \Doctrine\Common\Lexer
{
$type = self::T_NONE;
// Recognizing numeric values
if (is_numeric($value)) {
return (strpos($value, '.') !== false || stripos($value, 'e') !== false)
? self::T_FLOAT : self::T_INTEGER;
}
// Differentiate between quoted names, identifiers, input parameters and symbols
if ($value[0] === "'") {
$value = str_replace("''", "'", substr($value, 1, strlen($value) - 2));
return self::T_STRING;
} else if (ctype_alpha($value[0]) || $value[0] === '_') {
$name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($value);
if (defined($name)) {
$type = constant($name);
if ($type > 100) {
return $type;
switch (true) {
// Recognize numeric values
case (is_numeric($value)):
if (strpos($value, '.') !== false || stripos($value, 'e') !== false) {
return self::T_FLOAT;
}
}
return self::T_IDENTIFIER;
} else if ($value[0] === '?' || $value[0] === ':') {
return self::T_INPUT_PARAMETER;
} else {
switch ($value) {
case '.': return self::T_DOT;
case ',': return self::T_COMMA;
case '(': return self::T_OPEN_PARENTHESIS;
case ')': return self::T_CLOSE_PARENTHESIS;
case '=': return self::T_EQUALS;
case '>': return self::T_GREATER_THAN;
case '<': return self::T_LOWER_THAN;
case '+': return self::T_PLUS;
case '-': return self::T_MINUS;
case '*': return self::T_MULTIPLY;
case '/': return self::T_DIVIDE;
case '!': return self::T_NEGATE;
case '{': return self::T_OPEN_CURLY_BRACE;
case '}': return self::T_CLOSE_CURLY_BRACE;
default:
// Do nothing
break;
}
return self::T_INTEGER;
// Recognize quoted strings
case ($value[0] === "'"):
$value = str_replace("''", "'", substr($value, 1, strlen($value) - 2));
return self::T_STRING;
// Recognize identifiers
case (ctype_alpha($value[0]) || $value[0] === '_'):
$name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($value);
if (defined($name)) {
$type = constant($name);
if ($type > 100) {
return $type;
}
}
return self::T_IDENTIFIER;
// Recognize input parameters
case ($value[0] === '?' || $value[0] === ':'):
return self::T_INPUT_PARAMETER;
// Recognize symbols
case ($value === '.'): return self::T_DOT;
case ($value === ','): return self::T_COMMA;
case ($value === '('): return self::T_OPEN_PARENTHESIS;
case ($value === ')'): return self::T_CLOSE_PARENTHESIS;
case ($value === '='): return self::T_EQUALS;
case ($value === '>'): return self::T_GREATER_THAN;
case ($value === '<'): return self::T_LOWER_THAN;
case ($value === '+'): return self::T_PLUS;
case ($value === '-'): return self::T_MINUS;
case ($value === '*'): return self::T_MULTIPLY;
case ($value === '/'): return self::T_DIVIDE;
case ($value === '!'): return self::T_NEGATE;
case ($value === '{'): return self::T_OPEN_CURLY_BRACE;
case ($value === '}'): return self::T_CLOSE_CURLY_BRACE;
// Default
default:
// Do nothing
}
return $type;

View File

@ -677,13 +677,10 @@ class Parser
}
// Build the error message
$semanticalError = 'Invalid PathExpression. ';
if (count($expectedStringTypes) == 1) {
$semanticalError .= 'Must be a ' . $expectedStringTypes[0] . '.';
} else {
$semanticalError .= implode(' or ', $expectedStringTypes) . ' expected.';
}
$semanticalError = 'Invalid PathExpression. ';
$semanticalError .= (count($expectedStringTypes) == 1)
? 'Must be a ' . $expectedStringTypes[0] . '.'
: implode(' or ', $expectedStringTypes) . ' expected.';
$this->semanticalError($semanticalError, $deferredItem['token']);
}
@ -1866,53 +1863,78 @@ class Parser
$expression = null;
$identVariable = null;
$peek = $this->_lexer->glimpse();
$lookaheadType = $this->_lexer->lookahead['type'];
if ($this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER && $peek['type'] === Lexer::T_DOT) {
switch (true) {
// ScalarExpression (u.name)
$expression = $this->ScalarExpression();
} else if ($this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER && $peek['type'] !== Lexer::T_OPEN_PARENTHESIS) {
// IdentificationVariable (u)
$expression = $identVariable = $this->IdentificationVariable();
} else if (in_array($this->_lexer->lookahead['type'], array(Lexer::T_CASE, Lexer::T_COALESCE, Lexer::T_NULLIF))) {
// CaseExpression (CASE ... or NULLIF(...) or COALESCE(...))
$expression = $this->CaseExpression();
} else if ($this->_isFunction()) {
// DQL Function (SUM(u.value) or SUM(u.value) + 1)
$this->_lexer->peek(); // "("
$lookaheadType = $this->_lexer->lookahead['type'];
$beyond = $this->_peekBeyondClosingParenthesis();
if ($this->_isMathOperator($beyond)) {
// SUM(u.id) + COUNT(u.id)
case ($lookaheadType === Lexer::T_IDENTIFIER && $peek['type'] === Lexer::T_DOT):
$expression = $this->ScalarExpression();
} else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
// COUNT(u.id)
$expression = $this->AggregateExpression();
} else {
// SUM(u.id)
$expression = $this->FunctionDeclaration();
}
} else if ($this->_lexer->lookahead['type'] === Lexer::T_PARTIAL) {
break;
// IdentificationVariable (u)
case ($lookaheadType === Lexer::T_IDENTIFIER && $peek['type'] !== Lexer::T_OPEN_PARENTHESIS):
$expression = $identVariable = $this->IdentificationVariable();
break;
// CaseExpression (CASE ... or NULLIF(...) or COALESCE(...))
case ($lookaheadType === Lexer::T_CASE):
case ($lookaheadType === Lexer::T_COALESCE):
case ($lookaheadType === Lexer::T_NULLIF):
$expression = $this->CaseExpression();
break;
// DQL Function (SUM(u.value) or SUM(u.value) + 1)
case ($this->_isFunction()):
$this->_lexer->peek(); // "("
switch (true) {
case ($this->_isMathOperator($this->_peekBeyondClosingParenthesis())):
// SUM(u.id) + COUNT(u.id)
$expression = $this->ScalarExpression();
break;
case ($this->_isAggregateFunction($lookaheadType)):
// COUNT(u.id)
$expression = $this->AggregateExpression();
break;
default:
// IDENTITY(u)
$expression = $this->FunctionDeclaration();
break;
}
break;
// PartialObjectExpression (PARTIAL u.{id, name})
$expression = $this->PartialObjectExpression();
$identVariable = $expression->identificationVariable;
} else if ($this->_lexer->lookahead['type'] === Lexer::T_OPEN_PARENTHESIS && $peek['type'] === Lexer::T_SELECT) {
case ($lookaheadType === Lexer::T_PARTIAL):
$expression = $this->PartialObjectExpression();
$identVariable = $expression->identificationVariable;
break;
// Subselect
$this->match(Lexer::T_OPEN_PARENTHESIS);
$expression = $this->Subselect();
$this->match(Lexer::T_CLOSE_PARENTHESIS);
} else if (in_array($this->_lexer->lookahead['type'], array(Lexer::T_OPEN_PARENTHESIS, Lexer::T_INTEGER, Lexer::T_FLOAT, Lexer::T_STRING))) {
case ($lookaheadType === Lexer::T_OPEN_PARENTHESIS && $peek['type'] === Lexer::T_SELECT):
$this->match(Lexer::T_OPEN_PARENTHESIS);
$expression = $this->Subselect();
$this->match(Lexer::T_CLOSE_PARENTHESIS);
break;
// Shortcut: ScalarExpression => SimpleArithmeticExpression
$expression = $this->SimpleArithmeticExpression();
} else if (in_array($this->_lexer->lookahead['type'], array(Lexer::T_PLUS, Lexer::T_MINUS))) {
// SimpleArithmeticExpression : (- u.value ) or ( + u.value )
$expression = $this->SimpleArithmeticExpression();
} else {
$this->syntaxError(
'IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression',
$this->_lexer->lookahead
);
case ($lookaheadType === Lexer::T_OPEN_PARENTHESIS):
case ($lookaheadType === Lexer::T_INTEGER):
case ($lookaheadType === Lexer::T_STRING):
case ($lookaheadType === Lexer::T_FLOAT):
// SimpleArithmeticExpression : (- u.value ) or ( + u.value )
case ($lookaheadType === Lexer::T_MINUS):
case ($lookaheadType === Lexer::T_PLUS):
$expression = $this->SimpleArithmeticExpression();
break;
default:
$this->syntaxError(
'IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression',
$this->_lexer->lookahead
);
}
// [["AS"] ["HIDDEN"] AliasResultVariable]
@ -1965,25 +1987,41 @@ class Parser
{
$peek = $this->_lexer->glimpse();
if ($peek['value'] != '(' && $this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER) {
// SingleValuedPathExpression | IdentificationVariable
$expression = ($peek['value'] == '.')
? $this->StateFieldPathExpression()
: $this->IdentificationVariable();
switch ($this->_lexer->lookahead['type']) {
case Lexer::T_IDENTIFIER:
switch (true) {
case ($peek['type'] === Lexer::T_DOT):
$expression = $this->StateFieldPathExpression();
return new AST\SimpleSelectExpression($expression);
case ($peek['type'] !== Lexer::T_OPEN_PARENTHESIS):
$expression = $this->IdentificationVariable();
return new AST\SimpleSelectExpression($expression);
default:
// Do nothing
}
break;
case Lexer::T_OPEN_PARENTHESIS:
if ($peek['type'] !== Lexer::T_SELECT) {
// Shortcut: ScalarExpression => SimpleArithmeticExpression
$expression = $this->SimpleArithmeticExpression();
return new AST\SimpleSelectExpression($expression);
}
return new AST\SimpleSelectExpression($expression);
} else if ($this->_lexer->lookahead['value'] == '(') {
if ($peek['type'] == Lexer::T_SELECT) {
// Subselect
$this->match(Lexer::T_OPEN_PARENTHESIS);
$expression = $this->Subselect();
$this->match(Lexer::T_CLOSE_PARENTHESIS);
} else {
// Shortcut: ScalarExpression => SimpleArithmeticExpression
$expression = $this->SimpleArithmeticExpression();
}
return new AST\SimpleSelectExpression($expression);
return new AST\SimpleSelectExpression($expression);
default:
// Do nothing
}
$this->_lexer->peek();
@ -2099,27 +2137,26 @@ class Parser
{
$condPrimary = new AST\ConditionalPrimary;
if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
// Peek beyond the matching closing paranthesis ')'
$peek = $this->_peekBeyondClosingParenthesis();
if (in_array($peek['value'], array("=", "<", "<=", "<>", ">", ">=", "!=")) ||
$peek['type'] === Lexer::T_NOT ||
$peek['type'] === Lexer::T_BETWEEN ||
$peek['type'] === Lexer::T_LIKE ||
$peek['type'] === Lexer::T_IN ||
$peek['type'] === Lexer::T_IS ||
$peek['type'] === Lexer::T_EXISTS) {
$condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression();
} else {
$this->match(Lexer::T_OPEN_PARENTHESIS);
$condPrimary->conditionalExpression = $this->ConditionalExpression();
$this->match(Lexer::T_CLOSE_PARENTHESIS);
}
} else {
if ( ! $this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
$condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression();
return $condPrimary;
}
// Peek beyond the matching closing paranthesis ')'
$peek = $this->_peekBeyondClosingParenthesis();
if (in_array($peek['value'], array("=", "<", "<=", "<>", ">", ">=", "!=")) ||
in_array($peek['type'], array(Lexer::T_NOT, Lexer::T_BETWEEN, Lexer::T_LIKE, Lexer::T_IN, Lexer::T_IS, Lexer::T_EXISTS))) {
$condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression();
return $condPrimary;
}
$this->match(Lexer::T_OPEN_PARENTHESIS);
$condPrimary->conditionalExpression = $this->ConditionalExpression();
$this->match(Lexer::T_CLOSE_PARENTHESIS);
return $condPrimary;
}
@ -2132,10 +2169,10 @@ class Parser
*/
public function SimpleConditionalExpression()
{
$token = $this->_lexer->lookahead;
if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
$token = $this->_lexer->glimpse();
} else {
$token = $this->_lexer->lookahead;
}
if ($token['type'] === Lexer::T_EXISTS) {
@ -2464,9 +2501,9 @@ class Parser
}
return $this->FunctionDeclaration();
} else {
return $this->Literal();
}
return $this->Literal();
}
}
@ -2498,30 +2535,46 @@ class Parser
*/
public function StringPrimary()
{
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
$peek = $this->_lexer->glimpse();
$lookaheadType = $this->_lexer->lookahead['type'];
switch ($lookaheadType) {
case Lexer::T_IDENTIFIER:
$peek = $this->_lexer->glimpse();
if ($peek['value'] == '.') {
return $this->StateFieldPathExpression();
}
if ($peek['value'] == '(') {
// do NOT directly go to FunctionsReturningString() because it doesnt check for custom functions.
return $this->FunctionDeclaration();
}
if ($peek['value'] == '.') {
return $this->StateFieldPathExpression();
} else if ($peek['value'] == '(') {
// do NOT directly go to FunctionsReturningString() because it doesnt check for custom functions.
return $this->FunctionDeclaration();
} else {
$this->syntaxError("'.' or '('");
}
} else if ($this->_lexer->isNextToken(Lexer::T_STRING)) {
$this->match(Lexer::T_STRING);
break;
return $this->_lexer->token['value'];
} else if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
return $this->InputParameter();
} else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
return $this->AggregateExpression();
} else if (in_array($this->_lexer->lookahead['type'], array(Lexer::T_CASE, Lexer::T_COALESCE, Lexer::T_NULLIF))) {
return $this->CaseExpression();
case Lexer::T_STRING:
$this->match(Lexer::T_STRING);
return $this->_lexer->token['value'];
case Lexer::T_INPUT_PARAMETER:
return $this->InputParameter();
case Lexer::T_CASE:
case Lexer::T_COALESCE:
case Lexer::T_NULLIF:
return $this->CaseExpression();
default:
if ($this->_isAggregateFunction($lookaheadType)) {
return $this->AggregateExpression();
}
}
$this->syntaxError('StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression');
$this->syntaxError(
'StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression'
);
}
/**
@ -2564,40 +2617,28 @@ class Parser
*/
public function AggregateExpression()
{
$lookaheadType = $this->_lexer->lookahead['type'];
$isDistinct = false;
$functionName = '';
if ($this->_lexer->isNextToken(Lexer::T_COUNT)) {
$this->match(Lexer::T_COUNT);
$functionName = $this->_lexer->token['value'];
$this->match(Lexer::T_OPEN_PARENTHESIS);
if ($this->_lexer->isNextToken(Lexer::T_DISTINCT)) {
$this->match(Lexer::T_DISTINCT);
$isDistinct = true;
}
$pathExp = $this->SingleValuedPathExpression();
$this->match(Lexer::T_CLOSE_PARENTHESIS);
} else {
if ($this->_lexer->isNextToken(Lexer::T_AVG)) {
$this->match(Lexer::T_AVG);
} else if ($this->_lexer->isNextToken(Lexer::T_MAX)) {
$this->match(Lexer::T_MAX);
} else if ($this->_lexer->isNextToken(Lexer::T_MIN)) {
$this->match(Lexer::T_MIN);
} else if ($this->_lexer->isNextToken(Lexer::T_SUM)) {
$this->match(Lexer::T_SUM);
} else {
$this->syntaxError('One of: MAX, MIN, AVG, SUM, COUNT');
}
$functionName = $this->_lexer->token['value'];
$this->match(Lexer::T_OPEN_PARENTHESIS);
$pathExp = $this->SimpleArithmeticExpression();
$this->match(Lexer::T_CLOSE_PARENTHESIS);
if ( ! in_array($lookaheadType, array(Lexer::T_COUNT, Lexer::T_AVG, Lexer::T_MAX, Lexer::T_MIN, Lexer::T_SUM))) {
$this->syntaxError('One of: MAX, MIN, AVG, SUM, COUNT');
}
$this->match($lookaheadType);
$functionName = $this->_lexer->token['value'];
$this->match(Lexer::T_OPEN_PARENTHESIS);
if ($this->_lexer->isNextToken(Lexer::T_DISTINCT)) {
$this->match(Lexer::T_DISTINCT);
$isDistinct = true;
}
$pathExp = ($lookaheadType === Lexer::T_COUNT)
? $this->SingleValuedPathExpression()
: $this->SimpleArithmeticExpression();
$this->match(Lexer::T_CLOSE_PARENTHESIS);
return new AST\AggregateExpression($functionName, $pathExp, $isDistinct);
}
@ -2608,24 +2649,19 @@ class Parser
*/
public function QuantifiedExpression()
{
$type = '';
$lookaheadType = $this->_lexer->lookahead['type'];
$value = $this->_lexer->lookahead['value'];
if ($this->_lexer->isNextToken(Lexer::T_ALL)) {
$this->match(Lexer::T_ALL);
$type = 'ALL';
} else if ($this->_lexer->isNextToken(Lexer::T_ANY)) {
$this->match(Lexer::T_ANY);
$type = 'ANY';
} else if ($this->_lexer->isNextToken(Lexer::T_SOME)) {
$this->match(Lexer::T_SOME);
$type = 'SOME';
} else {
if ( ! in_array($lookaheadType, array(Lexer::T_ALL, Lexer::T_ANY, Lexer::T_SOME))) {
$this->syntaxError('ALL, ANY or SOME');
}
$this->match($lookaheadType);
$this->match(Lexer::T_OPEN_PARENTHESIS);
$qExpr = new AST\QuantifiedExpression($this->Subselect());
$qExpr->type = $type;
$qExpr->type = $value;
$this->match(Lexer::T_CLOSE_PARENTHESIS);
return $qExpr;
@ -2666,14 +2702,11 @@ class Parser
{
$peek = $this->_lexer->glimpse();
$leftExpr = $this->ArithmeticExpression();
$operator = $this->ComparisonOperator();
if ($this->_isNextAllAnySome()) {
$rightExpr = $this->QuantifiedExpression();
} else {
$rightExpr = $this->ArithmeticExpression();
}
$leftExpr = $this->ArithmeticExpression();
$operator = $this->ComparisonOperator();
$rightExpr = ($this->_isNextAllAnySome())
? $this->QuantifiedExpression()
: $this->ArithmeticExpression();
return new AST\ComparisonExpression($leftExpr, $operator, $rightExpr);
}