1
0
mirror of synced 2025-01-31 04:21:44 +03:00

[2.0] Moved string tokens to be constants. No more string comparisons inside parser

This commit is contained in:
guilhermeblanco 2009-11-03 21:42:58 +00:00
parent a72977b33d
commit e05ec39ff3
3 changed files with 179 additions and 148 deletions

View File

@ -49,48 +49,58 @@ class Lexer extends \Doctrine\Common\Lexer
const T_AVG = 106;
const T_BETWEEN = 107;
const T_BY = 108;
const T_COMMA = 109;
const T_COUNT = 110;
const T_DELETE = 111;
const T_DESC = 112;
const T_DISTINCT = 113;
const T_DOT = 114;
const T_EMPTY = 115;
const T_ESCAPE = 116;
const T_EXISTS = 117;
const T_FROM = 118;
const T_GROUP = 119;
const T_HAVING = 120;
const T_IN = 121;
const T_INDEX = 122;
const T_INNER = 123;
const T_IS = 124;
const T_JOIN = 125;
const T_LEFT = 126;
const T_LIKE = 127;
const T_LIMIT = 128;
const T_MAX = 129;
const T_MIN = 130;
const T_MOD = 131;
const T_NOT = 132;
const T_NULL = 133;
const T_OFFSET = 134;
const T_ON = 135;
const T_OR = 136;
const T_ORDER = 137;
const T_OUTER = 138;
const T_SELECT = 139;
const T_SET = 140;
const T_SIZE = 141;
const T_SOME = 142;
const T_SUM = 143;
const T_UPDATE = 144;
const T_WHERE = 145;
const T_WITH = 146;
const T_TRUE = 147;
const T_FALSE = 148;
const T_MEMBER = 149;
const T_OF = 150;
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;
private $_keywordsTable;
@ -131,23 +141,42 @@ class Lexer extends \Doctrine\Common\Lexer
protected function _getType(&$value)
{
$type = self::T_NONE;
$newVal = $this->_getNumeric($value);
// Recognizing numeric values
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 if ($value[0] === '?' || $value[0] === ':') {
$type = self::T_INPUT_PARAMETER;
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;
default:
// Do nothing
break;
}
}
return $type;

View File

@ -41,27 +41,27 @@ class Parser
{
/** Maps registered string function names to class names. */
private static $_STRING_FUNCTIONS = array(
'concat' => 'Doctrine\ORM\Query\AST\Functions\ConcatFunction',
'concat' => 'Doctrine\ORM\Query\AST\Functions\ConcatFunction',
'substring' => 'Doctrine\ORM\Query\AST\Functions\SubstringFunction',
'trim' => 'Doctrine\ORM\Query\AST\Functions\TrimFunction',
'lower' => 'Doctrine\ORM\Query\AST\Functions\LowerFunction',
'upper' => 'Doctrine\ORM\Query\AST\Functions\UpperFunction'
'trim' => 'Doctrine\ORM\Query\AST\Functions\TrimFunction',
'lower' => 'Doctrine\ORM\Query\AST\Functions\LowerFunction',
'upper' => 'Doctrine\ORM\Query\AST\Functions\UpperFunction'
);
/** Maps registered numeric function names to class names. */
private static $_NUMERIC_FUNCTIONS = array(
'length' => 'Doctrine\ORM\Query\AST\Functions\LengthFunction',
'locate' => 'Doctrine\ORM\Query\AST\Functions\LocateFunction',
'abs' => 'Doctrine\ORM\Query\AST\Functions\AbsFunction',
'sqrt' => 'Doctrine\ORM\Query\AST\Functions\SqrtFunction',
'mod' => 'Doctrine\ORM\Query\AST\Functions\ModFunction',
'size' => 'Doctrine\ORM\Query\AST\Functions\SizeFunction'
'abs' => 'Doctrine\ORM\Query\AST\Functions\AbsFunction',
'sqrt' => 'Doctrine\ORM\Query\AST\Functions\SqrtFunction',
'mod' => 'Doctrine\ORM\Query\AST\Functions\ModFunction',
'size' => 'Doctrine\ORM\Query\AST\Functions\SizeFunction'
);
/** Maps registered datetime function names to class names. */
private static $_DATETIME_FUNCTIONS = array(
'current_date' => 'Doctrine\ORM\Query\AST\Functions\CurrentDateFunction',
'current_time' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimeFunction',
'current_date' => 'Doctrine\ORM\Query\AST\Functions\CurrentDateFunction',
'current_time' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimeFunction',
'current_timestamp' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimestampFunction'
);
@ -792,7 +792,7 @@ class Parser
{
$token = $this->_lexer->lookahead;
$identVariable = $this->IdentificationVariable();
$this->match('.');
$this->match(Lexer::T_DOT);
$this->match(Lexer::T_IDENTIFIER);
$field = $this->_lexer->token['value'];
@ -825,11 +825,11 @@ class Parser
$parts = array();
do {
$this->match('.');
$this->match(Lexer::T_DOT);
$this->match(Lexer::T_IDENTIFIER);
$parts[] = $this->_lexer->token['value'];
} while ($this->_lexer->isNextToken('.'));
} while ($this->_lexer->isNextToken(Lexer::T_DOT));
// Creating AST node
$pathExpr = new AST\PathExpression($expectedType, $identVariable, $parts);
@ -950,8 +950,8 @@ class Parser
$selectExpressions = array();
$selectExpressions[] = $this->SelectExpression();
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$selectExpressions[] = $this->SelectExpression();
}
@ -1016,8 +1016,8 @@ class Parser
$updateItems = array();
$updateItems[] = $this->UpdateItem();
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$updateItems[] = $this->UpdateItem();
}
@ -1083,8 +1083,8 @@ class Parser
$identificationVariableDeclarations = array();
$identificationVariableDeclarations[] = $this->IdentificationVariableDeclaration();
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$identificationVariableDeclarations[] = $this->IdentificationVariableDeclaration();
}
@ -1102,8 +1102,8 @@ class Parser
$identificationVariables = array();
$identificationVariables[] = $this->SubselectIdentificationVariableDeclaration();
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$identificationVariables[] = $this->SubselectIdentificationVariableDeclaration();
}
@ -1146,8 +1146,8 @@ class Parser
$groupByItems = array($this->GroupByItem());
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$groupByItems[] = $this->GroupByItem();
}
@ -1167,8 +1167,8 @@ class Parser
$orderByItems = array();
$orderByItems[] = $this->OrderByItem();
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$orderByItems[] = $this->OrderByItem();
}
@ -1223,7 +1223,7 @@ class Parser
// Validate if IdentificationVariable is defined
$queryComponent = $this->_validateIdentificationVariable($identVariable, null, $token);
$this->match('.');
$this->match(Lexer::T_DOT);
$this->match(Lexer::T_IDENTIFIER);
$field = $this->_lexer->token['value'];
@ -1236,7 +1236,7 @@ class Parser
);
}
$this->match('=');
$this->match(Lexer::T_EQUALS);
$newValue = $this->NewValue();
@ -1551,9 +1551,9 @@ class Parser
$expression = $this->FunctionDeclaration();
}
} else {
$this->match('(');
$this->match(Lexer::T_OPEN_PARENTHESIS);
$expression = $this->Subselect();
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
}
if ($this->_lexer->isNextToken(Lexer::T_AS)) {
@ -1601,6 +1601,8 @@ class Parser
return new AST\SimpleSelectExpression($this->StateFieldPathExpression());
}
// TODO Fix this!!!
echo 'SimpleSelectExpression: '; var_dump($this->_lexer->lookahead);
$this->match($this->_lexer->lookahead['value']);
return new AST\SimpleSelectExpression($this->_lexer->token['value']);
@ -1717,9 +1719,9 @@ class Parser
$peek['type'] === Lexer::T_EXISTS) {
$condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression();
} else {
$this->match('(');
$this->match(Lexer::T_OPEN_PARENTHESIS);
$condPrimary->conditionalExpression = $this->ConditionalExpression();
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
}
} else {
$condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression();
@ -1778,7 +1780,11 @@ class Parser
if ($pathExprOrInputParam) {
switch ($token['type']) {
case Lexer::T_NONE:
case Lexer::T_EQUALS:
case Lexer::T_LOWER_THAN:
case Lexer::T_GREATER_THAN:
case Lexer::T_NEGATE:
case Lexer::T_OPEN_PARENTHESIS:
return $this->ComparisonExpression();
case Lexer::T_BETWEEN:
@ -1874,16 +1880,23 @@ class Parser
{
switch ($this->_lexer->lookahead['type']) {
case Lexer::T_STRING:
$this->match($this->_lexer->lookahead['value']);
$this->match(Lexer::T_STRING);
return new AST\Literal(AST\Literal::STRING, $this->_lexer->token['value']);
case Lexer::T_INTEGER:
case Lexer::T_FLOAT:
$this->match($this->_lexer->lookahead['value']);
$this->match(
$this->_lexer->isNextToken(Lexer::T_INTEGER) ? Lexer::T_INTEGER : Lexer::T_FLOAT
);
return new AST\Literal(AST\Literal::NUMERIC, $this->_lexer->token['value']);
case Lexer::T_TRUE:
case Lexer::T_FALSE:
$this->match($this->_lexer->lookahead['value']);
$this->match(
$this->_lexer->isNextToken(Lexer::T_TRUE) ? Lexer::T_TRUE : Lexer::T_FALSE
);
return new AST\Literal(AST\Literal::BOOLEAN, $this->_lexer->token['value']);
default:
$this->syntaxError('Literal');
}
@ -1911,7 +1924,7 @@ class Parser
*/
public function InputParameter()
{
$this->match($this->_lexer->lookahead['value']);
$this->match(Lexer::T_INPUT_PARAMETER);
return new AST\InputParameter($this->_lexer->token['value']);
}
@ -1926,13 +1939,13 @@ class Parser
{
$expr = new AST\ArithmeticExpression;
if ($this->_lexer->lookahead['value'] === '(') {
if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
$peek = $this->_lexer->glimpse();
if ($peek['type'] === Lexer::T_SELECT) {
$this->match('(');
$this->match(Lexer::T_OPEN_PARENTHESIS);
$expr->subselect = $this->Subselect();
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
return $expr;
}
@ -1953,12 +1966,8 @@ class Parser
$terms = array();
$terms[] = $this->ArithmeticTerm();
while ($this->_lexer->lookahead['value'] == '+' || $this->_lexer->lookahead['value'] == '-') {
if ($this->_lexer->lookahead['value'] == '+') {
$this->match('+');
} else {
$this->match('-');
}
while (($isPlus = $this->_lexer->isNextToken(Lexer::T_PLUS)) || $this->_lexer->isNextToken(Lexer::T_MINUS)) {
$this->match(($isPlus) ? Lexer::T_PLUS : Lexer::T_MINUS);
$terms[] = $this->_lexer->token['value'];
$terms[] = $this->ArithmeticTerm();
@ -1977,12 +1986,8 @@ class Parser
$factors = array();
$factors[] = $this->ArithmeticFactor();
while ($this->_lexer->lookahead['value'] == '*' || $this->_lexer->lookahead['value'] == '/') {
if ($this->_lexer->lookahead['value'] == '*') {
$this->match('*');
} else {
$this->match('/');
}
while (($isMult = $this->_lexer->isNextToken(Lexer::T_MULTIPLY)) || $this->_lexer->isNextToken(Lexer::T_DIVIDE)) {
$this->match(($isMult) ? Lexer::T_MULTIPLY : Lexer::T_DIVIDE);
$factors[] = $this->_lexer->token['value'];
$factors[] = $this->ArithmeticFactor();
@ -1998,15 +2003,12 @@ class Parser
*/
public function ArithmeticFactor()
{
$sign = null;
$sign = null;
if ($this->_lexer->lookahead['value'] == '+') {
$this->match('+');
$sign = true;
} else if ($this->_lexer->lookahead['value'] == '-') {
$this->match('-');
$sign = false;
}
if (($isPlus = $this->_lexer->isNextToken(Lexer::T_PLUS)) || $this->_lexer->isNextToken(Lexer::T_MINUS)) {
$this->match(($isPlus) ? Lexer::T_PLUS : Lexer::T_MINUS);
$sign = $isPlus;
}
return new AST\ArithmeticFactor($this->ArithmeticPrimary(), $sign);
}
@ -2018,10 +2020,10 @@ class Parser
*/
public function ArithmeticPrimary()
{
if ($this->_lexer->lookahead['value'] === '(') {
$this->match('(');
if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
$this->match(Lexer::T_OPEN_PARENTHESIS);
$expr = $this->SimpleArithmeticExpression();
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
return $expr;
}
@ -2066,13 +2068,13 @@ class Parser
*/
public function StringExpression()
{
if ($this->_lexer->lookahead['value'] === '(') {
if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
$peek = $this->_lexer->glimpse();
if ($peek['type'] === Lexer::T_SELECT) {
$this->match('(');
$this->match(Lexer::T_OPEN_PARENTHESIS);
$expr = $this->Subselect();
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
return $expr;
}
@ -2086,7 +2088,7 @@ class Parser
*/
public function StringPrimary()
{
if ($this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER) {
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
$peek = $this->_lexer->glimpse();
if ($peek['value'] == '.') {
@ -2096,11 +2098,11 @@ class Parser
} else {
$this->syntaxError("'.' or '('");
}
} else if ($this->_lexer->lookahead['type'] === Lexer::T_STRING) {
} else if ($this->_lexer->isNextToken(Lexer::T_STRING)) {
$this->match(Lexer::T_STRING);
return $this->_lexer->token['value'];
} else if ($this->_lexer->lookahead['type'] === Lexer::T_INPUT_PARAMETER) {
} else if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
return $this->InputParameter();
} else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
return $this->AggregateExpression();
@ -2156,7 +2158,7 @@ class Parser
if ($this->_lexer->isNextToken(Lexer::T_COUNT)) {
$this->match(Lexer::T_COUNT);
$functionName = $this->_lexer->token['value'];
$this->match('(');
$this->match(Lexer::T_OPEN_PARENTHESIS);
if ($this->_lexer->isNextToken(Lexer::T_DISTINCT)) {
$this->match(Lexer::T_DISTINCT);
@ -2164,7 +2166,7 @@ class Parser
}
$pathExp = $this->SingleValuedPathExpression();
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
} else {
if ($this->_lexer->isNextToken(Lexer::T_AVG)) {
$this->match(Lexer::T_AVG);
@ -2179,9 +2181,9 @@ class Parser
}
$functionName = $this->_lexer->token['value'];
$this->match('(');
$this->match(Lexer::T_OPEN_PARENTHESIS);
$pathExp = $this->StateFieldPathExpression();
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
}
return new AST\AggregateExpression($functionName, $pathExp, $isDistinct);
@ -2210,10 +2212,10 @@ class Parser
$this->syntaxError('ALL, ANY or SOME');
}
$this->match('(');
$this->match(Lexer::T_OPEN_PARENTHESIS);
$qExpr = new AST\QuantifiedExpression($this->Subselect());
$qExpr->type = $type;
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
return $qExpr;
}
@ -2280,7 +2282,7 @@ class Parser
}
$this->match(Lexer::T_IN);
$this->match('(');
$this->match(Lexer::T_OPEN_PARENTHESIS);
if ($this->_lexer->isNextToken(Lexer::T_SELECT)) {
$inExpression->subselect = $this->Subselect();
@ -2288,15 +2290,15 @@ class Parser
$literals = array();
$literals[] = $this->InParameter();
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$literals[] = $this->InParameter();
}
$inExpression->literals = $literals;
}
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
return $inExpression;
}
@ -2311,7 +2313,7 @@ class Parser
$stringExpr = $this->StringExpression();
$not = false;
if ($this->_lexer->lookahead['type'] === Lexer::T_NOT) {
if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
$this->match(Lexer::T_NOT);
$not = true;
}
@ -2382,10 +2384,10 @@ class Parser
}
$this->match(Lexer::T_EXISTS);
$this->match('(');
$this->match(Lexer::T_OPEN_PARENTHESIS);
$existsExpression = new AST\ExistsExpression($this->Subselect());
$existsExpression->not = $not;
$this->match(')');
$this->match(Lexer::T_CLOSE_PARENTHESIS);
return $existsExpression;
}
@ -2399,38 +2401,38 @@ class Parser
{
switch ($this->_lexer->lookahead['value']) {
case '=':
$this->match('=');
$this->match(Lexer::T_EQUALS);
return '=';
case '<':
$this->match('<');
$this->match(Lexer::T_LOWER_THAN);
$operator = '<';
if ($this->_lexer->isNextToken('=')) {
$this->match('=');
if ($this->_lexer->isNextToken(Lexer::T_EQUALS)) {
$this->match(Lexer::T_EQUALS);
$operator .= '=';
} else if ($this->_lexer->isNextToken('>')) {
$this->match('>');
} else if ($this->_lexer->isNextToken(Lexer::T_GREATER_THAN)) {
$this->match(Lexer::T_GREATER_THAN);
$operator .= '>';
}
return $operator;
case '>':
$this->match('>');
$this->match(Lexer::T_GREATER_THAN);
$operator = '>';
if ($this->_lexer->isNextToken('=')) {
$this->match('=');
if ($this->_lexer->isNextToken(Lexer::T_EQUALS)) {
$this->match(Lexer::T_EQUALS);
$operator .= '=';
}
return $operator;
case '!':
$this->match('!');
$this->match('=');
$this->match(Lexer::T_NEGATE);
$this->match(Lexer::T_EQUALS);
return '<>';

View File

@ -112,7 +112,7 @@ class LexerTest extends \Doctrine\Tests\OrmTestCase
$lexer = new Lexer('- 1.234e2');
$lexer->moveNext();
$token = $lexer->lookahead;
$this->assertEquals(Lexer::T_NONE, $token['type']);
$this->assertEquals(Lexer::T_MINUS, $token['type']);
$this->assertEquals('-', $token['value']);
$lexer->moveNext();
@ -201,7 +201,7 @@ class LexerTest extends \Doctrine\Tests\OrmTestCase
),
array(
'value' => '.',
'type' => Lexer::T_NONE,
'type' => Lexer::T_DOT,
'position' => 41
),
array(
@ -211,7 +211,7 @@ class LexerTest extends \Doctrine\Tests\OrmTestCase
),
array(
'value' => '=',
'type' => Lexer::T_NONE,
'type' => Lexer::T_EQUALS,
'position' => 47
),
array(