From 4a861f08a8f1ee67fdbfd2dbfedb439dc6e657a4 Mon Sep 17 00:00:00 2001 From: guilhermeblanco Date: Wed, 4 Nov 2009 01:52:40 +0000 Subject: [PATCH] [2.0] More refactorings in Annotations parser and DQL parser. Now they only use constants instead of string processment --- lib/Doctrine/Common/Annotations/Lexer.php | 50 +++-- lib/Doctrine/Common/Annotations/Parser.php | 65 +++---- lib/Doctrine/Common/Lexer.php | 30 ++- .../ORM/Query/AST/Functions/AbsFunction.php | 11 +- .../Query/AST/Functions/ConcatFunction.php | 11 +- .../AST/Functions/CurrentDateFunction.php | 9 +- .../AST/Functions/CurrentTimeFunction.php | 9 +- .../Functions/CurrentTimestampFunction.php | 9 +- .../Query/AST/Functions/LengthFunction.php | 8 +- .../Query/AST/Functions/LocateFunction.php | 14 +- .../ORM/Query/AST/Functions/LowerFunction.php | 8 +- .../ORM/Query/AST/Functions/ModFunction.php | 10 +- .../ORM/Query/AST/Functions/SizeFunction.php | 8 +- .../ORM/Query/AST/Functions/SqrtFunction.php | 8 +- .../Query/AST/Functions/SubstringFunction.php | 13 +- .../ORM/Query/AST/Functions/TrimFunction.php | 12 +- .../ORM/Query/AST/Functions/UpperFunction.php | 8 +- lib/Doctrine/ORM/Query/Lexer.php | 173 ++++++------------ lib/Doctrine/ORM/Query/Parser.php | 13 +- .../Annotations/AnnotationReaderTest.php | 6 +- .../Tests/Common/Annotations/ParserTest.php | 4 +- .../ORM/Query/DeleteSqlGenerationTest.php | 4 + .../ORM/Query/LanguageRecognitionTest.php | 1 + .../ORM/Query/SelectSqlGenerationTest.php | 6 +- 24 files changed, 252 insertions(+), 238 deletions(-) diff --git a/lib/Doctrine/Common/Annotations/Lexer.php b/lib/Doctrine/Common/Annotations/Lexer.php index f882b5a60..571be910d 100644 --- a/lib/Doctrine/Common/Annotations/Lexer.php +++ b/lib/Doctrine/Common/Annotations/Lexer.php @@ -34,13 +34,22 @@ namespace Doctrine\Common\Annotations; */ class Lexer extends \Doctrine\Common\Lexer { - const T_NONE = 1; - const T_FLOAT = 2; - const T_INTEGER = 3; - const T_STRING = 4; - const T_IDENTIFIER = 5; - const T_TRUE = 6; - const T_FALSE = 7; + const T_NONE = 1; + const T_IDENTIFIER = 2; + const T_INTEGER = 3; + const T_STRING = 4; + const T_FLOAT = 5; + + const T_AT = 101; + const T_CLOSE_CURLY_BRACES = 102; + const T_CLOSE_PARENTHESIS = 103; + const T_COMMA = 104; + const T_EQUALS = 105; + const T_FALSE = 106; + const T_NAMESPACE_SEPARATOR = 107; + const T_OPEN_CURLY_BRACES = 108; + const T_OPEN_PARENTHESIS = 109; + const T_TRUE = 110; /** * @inheritdoc @@ -70,21 +79,34 @@ class Lexer extends \Doctrine\Common\Lexer $type = self::T_NONE; $newVal = $this->_getNumeric($value); + // Checking numeric value if ($newVal !== false){ $value = $newVal; - if (strpos($value, '.') !== false || stripos($value, 'e') !== false) { - $type = self::T_FLOAT; - } else { - $type = self::T_INTEGER; - } + return (strpos($value, '.') !== false || stripos($value, 'e') !== false) + ? self::T_FLOAT : self::T_INTEGER; } if ($value[0] === '"') { - $type = self::T_STRING; $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2)); + + return self::T_STRING; } else if (ctype_alpha($value[0]) || $value[0] === '_') { - $type = $this->_checkLiteral($value); + return $this->_checkLiteral($value); + } else { + switch ($value) { + case '@': return self::T_AT; + case ',': return self::T_COMMA; + case '(': return self::T_OPEN_PARENTHESIS; + case ')': return self::T_CLOSE_PARENTHESIS; + case '{': return self::T_OPEN_CURLY_BRACES; + case '}': return self::T_CLOSE_CURLY_BRACES; + case '=': return self::T_EQUALS; + case '\\': return self::T_NAMESPACE_SEPARATOR; + default: + // Do nothing + break; + } } return $type; diff --git a/lib/Doctrine/Common/Annotations/Parser.php b/lib/Doctrine/Common/Annotations/Parser.php index 113bd72bf..b54e49ab8 100644 --- a/lib/Doctrine/Common/Annotations/Parser.php +++ b/lib/Doctrine/Common/Annotations/Parser.php @@ -130,7 +130,7 @@ class Parser $this->_lexer->setInput(trim($input, '* /')); $this->_lexer->moveNext(); - if ($this->_lexer->isNextToken('@')) { + if ($this->_lexer->isNextToken(Lexer::T_AT)) { return $this->Annotations(); } @@ -146,11 +146,8 @@ class Parser */ public function match($token) { - $key = (is_string($token)) ? 'value' : 'type'; - - if ( ! ($this->_lexer->lookahead[$key] === $token)) { - $token = (is_string($token)) ? $token : $token['value']; - $this->syntaxError($token); + if ( ! ($this->_lexer->lookahead['type'] === $token)) { + $this->syntaxError($this->_lexer->getLiteral($token)); } $this->_lexer->moveNext(); @@ -169,7 +166,7 @@ class Parser $token = $this->_lexer->lookahead; } - $message = "Expected '{$expected}', got "; + $message = "Expected {$expected}, got "; if ($this->_lexer->lookahead === null) { $message .= 'end of string'; @@ -201,7 +198,7 @@ class Parser $annotations[get_class($annot)] = $annot; } - while ($this->_lexer->lookahead !== null && $this->_lexer->lookahead['value'] == '@') { + while ($this->_lexer->lookahead !== null && $this->_lexer->isNextToken(Lexer::T_AT)) { $this->_isNestedAnnotation = false; $annot = $this->Annotation(); @@ -228,12 +225,12 @@ class Parser $values = array(); $nameParts = array(); - $this->match('@'); + $this->match(Lexer::T_AT); $this->match(Lexer::T_IDENTIFIER); $nameParts[] = $this->_lexer->token['value']; - while ($this->_lexer->isNextToken('\\')) { - $this->match('\\'); + while ($this->_lexer->isNextToken(Lexer::T_NAMESPACE_SEPARATOR)) { + $this->match(Lexer::T_NAMESPACE_SEPARATOR); $this->match(Lexer::T_IDENTIFIER); $nameParts[] = $this->_lexer->token['value']; } @@ -250,12 +247,12 @@ class Parser // If it really an annotation class? if ( (! $this->_isNestedAnnotation && $this->_lexer->lookahead != null && - ! $this->_lexer->isNextToken('(') && - ! $this->_lexer->isNextToken('@')) || + ! $this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS) && + ! $this->_lexer->isNextToken(Lexer::T_AT)) || ! class_exists($name, false) || ! is_subclass_of($name, 'Doctrine\Common\Annotations\Annotation') ) { - $this->_lexer->skipUntil('@'); + $this->_lexer->skipUntil(Lexer::T_AT); return false; } @@ -263,14 +260,14 @@ class Parser // Next will be nested $this->_isNestedAnnotation = true; - if ($this->_lexer->isNextToken('(')) { - $this->match('('); + if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { + $this->match(Lexer::T_OPEN_PARENTHESIS); - if ( ! $this->_lexer->isNextToken(')')) { + if ( ! $this->_lexer->isNextToken(Lexer::T_CLOSE_PARENTHESIS)) { $values = $this->Values(); } - $this->match(')'); + $this->match(Lexer::T_CLOSE_PARENTHESIS); } return new $name($values); @@ -286,19 +283,19 @@ class Parser $values = array(); // Handle the case of a single array as value, i.e. @Foo({....}) - if ($this->_lexer->isNextToken('{')) { + if ($this->_lexer->isNextToken(Lexer::T_OPEN_CURLY_BRACES)) { $values['value'] = $this->Value(); return $values; } $values[] = $this->Value(); - while ($this->_lexer->isNextToken(',')) { - $this->match(','); + while ($this->_lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); $value = $this->Value(); if ( ! is_array($value)) { - $this->syntaxError('FieldAssignment', $value); + $this->syntaxError('Value', $value); } $values[] = $value; @@ -341,11 +338,11 @@ class Parser */ public function PlainValue() { - if ($this->_lexer->lookahead['value'] == '{') { + if ($this->_lexer->isNextToken(Lexer::T_OPEN_CURLY_BRACES)) { return $this->Arrayx(); } - if ($this->_lexer->lookahead['value'] == '@') { + if ($this->_lexer->isNextToken(Lexer::T_AT)) { return $this->Annotation(); } @@ -385,7 +382,7 @@ class Parser { $this->match(Lexer::T_IDENTIFIER); $fieldName = $this->_lexer->token['value']; - $this->match('='); + $this->match(Lexer::T_EQUALS); return array($fieldName => $this->PlainValue()); } @@ -399,15 +396,15 @@ class Parser { $array = $values = array(); - $this->match('{'); + $this->match(Lexer::T_OPEN_CURLY_BRACES); $values[] = $this->ArrayEntry(); - while ($this->_lexer->isNextToken(',')) { - $this->match(','); + while ($this->_lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); $values[] = $this->ArrayEntry(); } - $this->match('}'); + $this->match(Lexer::T_CLOSE_CURLY_BRACES); foreach ($values as $value) { $key = key($value); @@ -434,14 +431,12 @@ class Parser $peek = $this->_lexer->glimpse(); if ($peek['value'] == '=') { - if ($this->_lexer->lookahead['type'] === Lexer::T_INTEGER) { - $this->match(Lexer::T_INTEGER); - } else { - $this->match(Lexer::T_STRING); - } + $this->match( + $this->_lexer->isNextToken(Lexer::T_INTEGER) ? Lexer::T_INTEGER : Lexer::T_STRING + ); $key = $this->_lexer->token['value']; - $this->match('='); + $this->match(Lexer::T_EQUALS); return array($key => $this->PlainValue()); } diff --git a/lib/Doctrine/Common/Lexer.php b/lib/Doctrine/Common/Lexer.php index f45bf2a2c..e4d39ce95 100644 --- a/lib/Doctrine/Common/Lexer.php +++ b/lib/Doctrine/Common/Lexer.php @@ -110,8 +110,7 @@ abstract class Lexer */ public function isNextToken($token) { - $la = $this->lookahead; - return ($la['type'] === $token || $la['value'] === $token); + return $this->lookahead['type'] === $token; } /** @@ -138,11 +137,11 @@ abstract class Lexer /** * Tells the lexer to skip input tokens until it sees a token with the given value. * - * @param $value The value to skip until. + * @param $type The token type to skip until. */ - public function skipUntil($value) + public function skipUntil($type) { - while ($this->lookahead !== null && $this->lookahead['value'] !== $value) { + while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { $this->moveNext(); } } @@ -214,6 +213,27 @@ abstract class Lexer } } + /** + * Gets the literal for a given token. + * + * @param integer $token + * @return string + */ + public function getLiteral($token) + { + $className = get_class($this); + $reflClass = new \ReflectionClass($className); + $constants = $reflClass->getConstants(); + + foreach ($constants as $name => $value) { + if ($value === $token) { + return $className . '::' . $name; + } + } + + return $token; + } + /** * Lexical catchable patterns * diff --git a/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php index 862eb0737..040ec59e0 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "ABS" "(" SimpleArithmeticExpression ")" * @@ -52,10 +54,13 @@ class AbsFunction extends FunctionNode public function parse(\Doctrine\ORM\Query\Parser $parser) { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + + $parser->match(Lexer::T_ABS); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - $parser->match(')'); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php index 48261ecab..5615190c8 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "CONCAT" "(" StringPrimary "," StringPrimary ")" * @@ -55,14 +57,15 @@ class ConcatFunction extends FunctionNode public function parse(\Doctrine\ORM\Query\Parser $parser) { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->firstStringPrimary = $parser->StringPrimary(); - $parser->match(','); + $parser->match(Lexer::T_COMMA); $this->secondStringPrimary = $parser->StringPrimary(); - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php index 9d23a7a24..2b33514b9 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "CURRENT_DATE" * @@ -48,8 +50,9 @@ class CurrentDateFunction extends FunctionNode public function parse(\Doctrine\ORM\Query\Parser $parser) { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); - $parser->match(')'); + + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php index be9b9725c..f3599fe22 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "CURRENT_TIME" * @@ -48,8 +50,9 @@ class CurrentTimeFunction extends FunctionNode public function parse(\Doctrine\ORM\Query\Parser $parser) { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); - $parser->match(')'); + + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php index 1443e657c..449c1d55a 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php @@ -6,6 +6,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "CURRENT_TIMESTAMP" * @@ -27,8 +29,9 @@ class CurrentTimestampFunction extends FunctionNode public function parse(\Doctrine\ORM\Query\Parser $parser) { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); - $parser->match(')'); + + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php index ba932c963..61bcdf200 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "LENGTH" "(" StringPrimary ")" * @@ -52,12 +54,12 @@ class LengthFunction extends FunctionNode { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->stringPrimary = $parser->StringPrimary(); - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php index dcc5c5229..aa158a916 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" * @@ -59,22 +61,22 @@ class LocateFunction extends FunctionNode { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->firstStringPrimary = $parser->StringPrimary(); - $parser->match(','); + $parser->match(Lexer::T_COMMA); $this->secondStringPrimary = $parser->StringPrimary(); - if ($lexer->isNextToken(',')) { - $parser->match(','); + if ($lexer->isNextToken(Lexer::T_COMMA)) { + $parser->match(Lexer::T_COMMA); $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); } - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php index 77db9959b..20ae182d9 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "LOWER" "(" StringPrimary ")" * @@ -52,12 +54,12 @@ class LowerFunction extends FunctionNode { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->stringPrimary = $parser->StringPrimary(); - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php index 7b60f013f..b9bb92656 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" * @@ -57,16 +59,16 @@ class ModFunction extends FunctionNode { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + $parser->match(Lexer::T_MOD); + $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->firstSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - $parser->match(','); + $parser->match(Lexer::T_COMMA); $this->secondSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php index 13603822b..c6f069692 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "SIZE" "(" CollectionValuedPathExpression ")" * @@ -77,12 +79,12 @@ class SizeFunction extends FunctionNode { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + $parser->match(Lexer::T_SIZE); + $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->collectionPathExpression = $parser->CollectionValuedPathExpression(); - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php index 4ddb8a1cd..ab0f8b348 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "SQRT" "(" SimpleArithmeticExpression ")" * @@ -52,12 +54,12 @@ class SqrtFunction extends FunctionNode { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php index 903076504..16fce7a2d 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" * @@ -60,19 +62,20 @@ class SubstringFunction extends FunctionNode { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->stringPrimary = $parser->StringPrimary(); - $parser->match(','); + $parser->match(Lexer::T_COMMA); $this->firstSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - $parser->match(','); + + $parser->match(Lexer::T_COMMA); $this->secondSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php index 16d3c6d1c..a70600919 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php @@ -71,17 +71,17 @@ class TrimFunction extends FunctionNode { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); if (strcasecmp('leading', $lexer->lookahead['value']) === 0) { - $parser->match($lexer->lookahead['value']); + $parser->match(Lexer::T_LEADING); $this->leading = true; } else if (strcasecmp('trailing', $lexer->lookahead['value']) === 0) { - $parser->match($lexer->lookahead['value']); + $parser->match(Lexer::T_TRAILING); $this->trailing = true; } else if (strcasecmp('both', $lexer->lookahead['value']) === 0) { - $parser->match($lexer->lookahead['value']); + $parser->match(Lexer::T_BOTH); $this->both = true; } @@ -96,7 +96,7 @@ class TrimFunction extends FunctionNode $this->stringPrimary = $parser->StringPrimary(); - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php index f91a36259..e9206fe43 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query\AST\Functions; +use Doctrine\ORM\Query\Lexer; + /** * "UPPER" "(" StringPrimary ")" * @@ -52,12 +54,12 @@ class UpperFunction extends FunctionNode { $lexer = $parser->getLexer(); - $parser->match($lexer->lookahead['value']); - $parser->match('('); + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->stringPrimary = $parser->StringPrimary(); - $parser->match(')'); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } diff --git a/lib/Doctrine/ORM/Query/Lexer.php b/lib/Doctrine/ORM/Query/Lexer.php index 6ad701985..3fff56fc3 100644 --- a/lib/Doctrine/ORM/Query/Lexer.php +++ b/lib/Doctrine/ORM/Query/Lexer.php @@ -48,59 +48,62 @@ class Lexer extends \Doctrine\Common\Lexer const T_ASC = 105; const T_AVG = 106; const T_BETWEEN = 107; - const T_BY = 108; - const T_CLOSE_PARENTHESIS = 109; - const T_COMMA = 110; - const T_COUNT = 111; - const T_DELETE = 112; - const T_DESC = 113; - const T_DISTINCT = 114; - const T_DIVIDE = 115; - const T_DOT = 116; - const T_EMPTY = 117; - const T_EQUALS = 118; - const T_ESCAPE = 119; - const T_EXISTS = 120; - const T_FALSE = 121; - const T_FROM = 122; - const T_GREATER_THAN = 123; - const T_GROUP = 124; - const T_HAVING = 125; - const T_IN = 126; - const T_INDEX = 127; - const T_INNER = 128; - const T_IS = 129; - const T_JOIN = 130; - const T_LEFT = 131; - const T_LIKE = 132; - const T_LIMIT = 133; - const T_LOWER_THAN = 134; - const T_MAX = 135; - const T_MEMBER = 136; - const T_MIN = 137; - const T_MINUS = 138; - const T_MOD = 139; - const T_MULTIPLY = 140; - const T_NEGATE = 141; - const T_NOT = 142; - const T_NULL = 143; - const T_OF = 144; - const T_OFFSET = 145; - const T_ON = 146; - const T_OPEN_PARENTHESIS = 147; - const T_OR = 148; - const T_ORDER = 149; - const T_OUTER = 150; - const T_PLUS = 151; - const T_SELECT = 152; - const T_SET = 153; - const T_SIZE = 154; - const T_SOME = 155; - const T_SUM = 156; - const T_TRUE = 157; - const T_UPDATE = 158; - const T_WHERE = 159; - const T_WITH = 160; + const T_BOTH = 108; + const T_BY = 109; + const T_CLOSE_PARENTHESIS = 110; + const T_COMMA = 111; + const T_COUNT = 112; + const T_DELETE = 113; + const T_DESC = 114; + const T_DISTINCT = 115; + const T_DIVIDE = 116; + const T_DOT = 117; + const T_EMPTY = 118; + const T_EQUALS = 119; + const T_ESCAPE = 120; + const T_EXISTS = 121; + const T_FALSE = 122; + const T_FROM = 123; + const T_GREATER_THAN = 124; + const T_GROUP = 125; + const T_HAVING = 126; + const T_IN = 127; + const T_INDEX = 128; + const T_INNER = 129; + const T_IS = 130; + const T_JOIN = 131; + const T_LEADING = 132; + const T_LEFT = 133; + const T_LIKE = 134; + const T_LIMIT = 135; + const T_LOWER_THAN = 136; + const T_MAX = 137; + const T_MEMBER = 138; + const T_MIN = 139; + const T_MINUS = 140; + const T_MOD = 141; + const T_MULTIPLY = 142; + const T_NEGATE = 143; + const T_NOT = 144; + const T_NULL = 145; + const T_OF = 146; + const T_OFFSET = 147; + const T_ON = 148; + const T_OPEN_PARENTHESIS = 149; + const T_OR = 150; + const T_ORDER = 151; + const T_OUTER = 152; + const T_PLUS = 153; + const T_SELECT = 154; + const T_SET = 155; + const T_SIZE = 156; + const T_SOME = 157; + const T_SUM = 158; + const T_TRAILING = 159; + const T_TRUE = 160; + const T_UPDATE = 161; + const T_WHERE = 162; + const T_WITH = 163; private $_keywordsTable; @@ -217,68 +220,4 @@ class Lexer extends \Doctrine\Common\Lexer return self::T_IDENTIFIER; } - - /** - * Gets the literal for a given token. - * - * @param mixed $token - * @return string - */ - public function getLiteral($token) - { - if ( ! $this->_keywordsTable) { - $this->_keywordsTable = array( - self::T_ALL => "ALL", - self::T_AND => "AND", - self::T_ANY => "ANY", - self::T_AS => "AS", - self::T_ASC => "ASC", - self::T_AVG => "AVG", - self::T_BETWEEN => "BETWEEN", - self::T_BY => "BY", - self::T_COMMA => ",", - self::T_COUNT => "COUNT", - self::T_DELETE => "DELETE", - self::T_DESC => "DESC", - self::T_DISTINCT => "DISTINCT", - self::T_DOT => ".", - self::T_EMPTY => "EMPTY", - self::T_ESCAPE => "ESCAPE", - self::T_EXISTS => "EXISTS", - self::T_FALSE => "FALSE", - self::T_FROM => "FROM", - self::T_GROUP => "GROUP", - self::T_HAVING => "HAVING", - self::T_IN => "IN", - self::T_INDEX => "INDEX", - self::T_INNER => "INNER", - self::T_IS => "IS", - self::T_JOIN => "JOIN", - self::T_LEFT => "LEFT", - self::T_LIKE => "LIKE", - self::T_LIMIT => "LIMIT", - self::T_MAX => "MAX", - self::T_MIN => "MIN", - self::T_MOD => "MOD", - self::T_NOT => "NOT", - self::T_NULL => "NULL", - self::T_OFFSET => "OFFSET", - self::T_ON => "ON", - self::T_OR => "OR", - self::T_ORDER => "ORDER", - self::T_OUTER => "OUTER", - self::T_SELECT => "SELECT", - self::T_SET => "SET", - self::T_SIZE => "SIZE", - self::T_SOME => "SOME", - self::T_SUM => "SUM", - self::T_TRUE => "TRUE", - self::T_UPDATE => "UPDATE", - self::T_WHERE => "WHERE", - self::T_WITH => "WITH"); - } - return isset($this->_keywordsTable[$token]) - ? $this->_keywordsTable[$token] - : (is_string($token) ? $token : ''); - } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index 60e4c5767..095299943 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -237,9 +237,7 @@ class Parser */ public function match($token) { - $key = (is_string($token)) ? 'value' : 'type'; - - if ( ! ($this->_lexer->lookahead[$key] === $token)) { + if ( ! ($this->_lexer->lookahead['type'] === $token)) { $this->syntaxError($this->_lexer->getLiteral($token)); } @@ -334,7 +332,7 @@ class Parser $message = "line 0, col {$tokenPos}: Error: "; if ($expected !== '') { - $message .= "Expected '{$expected}', got "; + $message .= "Expected {$expected}, got "; } else { $message .= 'Unexpected '; } @@ -1601,9 +1599,7 @@ class Parser return new AST\SimpleSelectExpression($this->StateFieldPathExpression()); } - // TODO Fix this!!! - echo 'SimpleSelectExpression: '; var_dump($this->_lexer->lookahead); - $this->match($this->_lexer->lookahead['value']); + $this->match(Lexer::T_IDENTIFIER); return new AST\SimpleSelectExpression($this->_lexer->token['value']); } @@ -1696,7 +1692,7 @@ class Parser { $condPrimary = new AST\ConditionalPrimary; - if ($this->_lexer->isNextToken('(')) { + if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { // Peek beyond the matching closing paranthesis ')' $numUnmatched = 1; $peek = $this->_lexer->peek(); @@ -2023,6 +2019,7 @@ class Parser if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { $this->match(Lexer::T_OPEN_PARENTHESIS); $expr = $this->SimpleArithmeticExpression(); + $this->match(Lexer::T_CLOSE_PARENTHESIS); return $expr; diff --git a/tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php b/tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php index 013a4dc39..3f3ece930 100644 --- a/tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php +++ b/tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php @@ -62,7 +62,7 @@ class AnnotationReaderTest extends \Doctrine\Tests\DoctrineTestCase { $this->setExpectedException( "Doctrine\Common\Annotations\AnnotationException", - "[Syntax Error] Expected '', got ')' at position 18 in class ". + "[Syntax Error] Expected Doctrine\Common\Annotations\Lexer::T_IDENTIFIER, got ')' at position 18 in class ". "Doctrine\Tests\Common\Annotations\DummyClassSyntaxError." ); @@ -76,7 +76,7 @@ class AnnotationReaderTest extends \Doctrine\Tests\DoctrineTestCase { $this->setExpectedException( "Doctrine\Common\Annotations\AnnotationException", - "[Syntax Error] Expected '', got ')' at position 18 in ". + "[Syntax Error] Expected Doctrine\Common\Annotations\Lexer::T_IDENTIFIER, got ')' at position 18 in ". "method Doctrine\Tests\Common\Annotations\DummyClassMethodSyntaxError::foo()." ); @@ -91,7 +91,7 @@ class AnnotationReaderTest extends \Doctrine\Tests\DoctrineTestCase { $this->setExpectedException( "Doctrine\Common\Annotations\AnnotationException", - "[Syntax Error] Expected '', got ')' at position 18 in ". + "[Syntax Error] Expected Doctrine\Common\Annotations\Lexer::T_IDENTIFIER, got ')' at position 18 in ". "property Doctrine\Tests\Common\Annotations\DummyClassPropertySyntaxError::\$foo." ); diff --git a/tests/Doctrine/Tests/Common/Annotations/ParserTest.php b/tests/Doctrine/Tests/Common/Annotations/ParserTest.php index 8f663d05f..b1f7a292c 100644 --- a/tests/Doctrine/Tests/Common/Annotations/ParserTest.php +++ b/tests/Doctrine/Tests/Common/Annotations/ParserTest.php @@ -94,7 +94,7 @@ DOCBLOCK; { $this->setExpectedException( 'Doctrine\Common\Annotations\AnnotationException', - "[Syntax Error] Expected 'PlainValue', got ''' at position 10." + "[Syntax Error] Expected PlainValue, got ''' at position 10." ); $parser = $this->createTestParser(); @@ -115,7 +115,7 @@ DOCBLOCK; { $this->setExpectedException( 'Doctrine\Common\Annotations\AnnotationException', - "[Syntax Error] Expected 'PlainValue', got ''' at position 10 ". + "[Syntax Error] Expected PlainValue, got ''' at position 10 ". "in class \Doctrine\Tests\Common\Annotations\Name" ); diff --git a/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php index 8d1597629..1f50d7d7a 100644 --- a/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php @@ -52,6 +52,10 @@ class DeleteSqlGenerationTest extends \Doctrine\Tests\OrmTestCase parent::assertEquals($sqlToBeConfirmed, $query->getSql()); $query->free(); } catch (\Exception $e) { + if ($debug) { + echo $e->getTraceAsString() . PHP_EOL; + } + $this->fail($e->getMessage()); } } diff --git a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php index 457d80467..82cfe9a86 100644 --- a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php +++ b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php @@ -22,6 +22,7 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase if ($debug) { echo $e->getTraceAsString() . PHP_EOL; } + $this->fail($e->getMessage()); } } diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index 161be88c4..7c6924d59 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -23,8 +23,10 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase parent::assertEquals($sqlToBeConfirmed, $query->getSql()); $query->free(); } catch (Doctrine_Exception $e) { - echo $e->getMessage(); - echo $e->getTraceAsString(); + if ($debug) { + echo $e->getTraceAsString() . PHP_EOL; + } + $this->fail($e->getMessage()); } }