2009-03-20 20:53:14 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Doctrine\Tests\ORM\Query;
|
|
|
|
|
|
|
|
use Doctrine\ORM\Query\Lexer;
|
2016-05-11 01:55:12 +07:00
|
|
|
use Doctrine\Tests\OrmTestCase;
|
2009-03-20 20:53:14 +00:00
|
|
|
|
2016-05-11 01:55:12 +07:00
|
|
|
class LexerTest extends OrmTestCase
|
2009-03-20 20:53:14 +00:00
|
|
|
{
|
|
|
|
//private $_lexer;
|
|
|
|
|
|
|
|
protected function setUp() {
|
|
|
|
}
|
|
|
|
|
2015-04-26 23:10:51 +02:00
|
|
|
/**
|
|
|
|
* @dataProvider provideTokens
|
|
|
|
*/
|
|
|
|
public function testScannerRecognizesTokens($type, $value)
|
2009-03-20 20:53:14 +00:00
|
|
|
{
|
2015-04-26 23:10:51 +02:00
|
|
|
$lexer = new Lexer($value);
|
2011-12-19 22:56:19 +01:00
|
|
|
|
2009-03-20 20:53:14 +00:00
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
|
2015-04-26 23:10:51 +02:00
|
|
|
$this->assertEquals($type, $token['type']);
|
|
|
|
$this->assertEquals($value, $token['value']);
|
2009-03-20 20:53:14 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 23:10:51 +02:00
|
|
|
public function testScannerRecognizesTerminalString()
|
2009-03-20 20:53:14 +00:00
|
|
|
{
|
2015-04-26 23:10:51 +02:00
|
|
|
/*
|
|
|
|
* "all" looks like an identifier, but in fact it's a reserved word
|
|
|
|
* (a terminal string). It's up to the parser to accept it as an identifier
|
|
|
|
* (with its literal value) when appropriate.
|
|
|
|
*/
|
2009-03-20 20:53:14 +00:00
|
|
|
|
2015-04-26 23:10:51 +02:00
|
|
|
$lexer = new Lexer('all');
|
2009-03-20 20:53:14 +00:00
|
|
|
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
|
2015-04-26 23:10:51 +02:00
|
|
|
$this->assertEquals(Lexer::T_ALL, $token['type']);
|
2009-03-20 20:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesDecimalInteger()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer('1234');
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_INTEGER, $token['type']);
|
|
|
|
$this->assertEquals(1234, $token['value']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesFloat()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer('1.234');
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_FLOAT, $token['type']);
|
|
|
|
$this->assertEquals(1.234, $token['value']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesFloatWithExponent()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer('1.2e3');
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_FLOAT, $token['type']);
|
|
|
|
$this->assertEquals(1.2e3, $token['value']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesFloatWithExponent2()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer('0.2e3');
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_FLOAT, $token['type']);
|
|
|
|
$this->assertEquals(.2e3, $token['value']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesFloatWithNegativeExponent()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer('7E-10');
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_FLOAT, $token['type']);
|
|
|
|
$this->assertEquals(7E-10, $token['value']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesFloatBig()
|
|
|
|
{
|
2009-08-05 21:13:42 +00:00
|
|
|
$lexer = new Lexer('123456789.01');
|
2009-03-20 20:53:14 +00:00
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_FLOAT, $token['type']);
|
2009-08-05 21:13:42 +00:00
|
|
|
$this->assertEquals(1.2345678901e8, $token['value']);
|
2009-03-20 20:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesFloatContainingWhitespace()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer('- 1.234e2');
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
2009-11-03 21:42:58 +00:00
|
|
|
$this->assertEquals(Lexer::T_MINUS, $token['type']);
|
2009-03-20 20:53:14 +00:00
|
|
|
$this->assertEquals('-', $token['value']);
|
|
|
|
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_FLOAT, $token['type']);
|
|
|
|
$this->assertNotEquals(-1.234e2, $token['value']);
|
|
|
|
$this->assertEquals(1.234e2, $token['value']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesStringContainingWhitespace()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer("'This is a string.'");
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_STRING, $token['type']);
|
2009-06-14 17:34:28 +00:00
|
|
|
$this->assertEquals("This is a string.", $token['value']);
|
2009-03-20 20:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesStringContainingSingleQuotes()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer("'abc''defg'''");
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_STRING, $token['type']);
|
2009-06-14 17:34:28 +00:00
|
|
|
$this->assertEquals("abc'defg'", $token['value']);
|
2009-03-20 20:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesInputParameter()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer('?1');
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_INPUT_PARAMETER, $token['type']);
|
|
|
|
$this->assertEquals('?1', $token['value']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testScannerRecognizesNamedInputParameter()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer(':name');
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_INPUT_PARAMETER, $token['type']);
|
|
|
|
$this->assertEquals(':name', $token['value']);
|
|
|
|
}
|
|
|
|
|
2013-07-05 09:21:24 +02:00
|
|
|
public function testScannerRecognizesNamedInputParameterStartingWithUnderscore()
|
|
|
|
{
|
|
|
|
$lexer = new Lexer(':_name');
|
|
|
|
$lexer->moveNext();
|
|
|
|
$token = $lexer->lookahead;
|
|
|
|
$this->assertEquals(Lexer::T_INPUT_PARAMETER, $token['type']);
|
|
|
|
$this->assertEquals(':_name', $token['value']);
|
|
|
|
}
|
|
|
|
|
2009-03-20 20:53:14 +00:00
|
|
|
public function testScannerTokenizesASimpleQueryCorrectly()
|
|
|
|
{
|
|
|
|
$dql = "SELECT u FROM My\Namespace\User u WHERE u.name = 'Jack O''Neil'";
|
|
|
|
$lexer = new Lexer($dql);
|
|
|
|
|
2016-12-07 23:33:41 +01:00
|
|
|
$tokens = [
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => 'SELECT',
|
|
|
|
'type' => Lexer::T_SELECT,
|
|
|
|
'position' => 0
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => 'u',
|
|
|
|
'type' => Lexer::T_IDENTIFIER,
|
|
|
|
'position' => 7
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => 'FROM',
|
|
|
|
'type' => Lexer::T_FROM,
|
|
|
|
'position' => 9
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => 'My\Namespace\User',
|
2015-04-26 23:10:51 +02:00
|
|
|
'type' => Lexer::T_FULLY_QUALIFIED_NAME,
|
2009-03-20 20:53:14 +00:00
|
|
|
'position' => 14
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => 'u',
|
|
|
|
'type' => Lexer::T_IDENTIFIER,
|
|
|
|
'position' => 32
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => 'WHERE',
|
|
|
|
'type' => Lexer::T_WHERE,
|
|
|
|
'position' => 34
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => 'u',
|
|
|
|
'type' => Lexer::T_IDENTIFIER,
|
|
|
|
'position' => 40
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => '.',
|
2009-11-03 21:42:58 +00:00
|
|
|
'type' => Lexer::T_DOT,
|
2009-03-20 20:53:14 +00:00
|
|
|
'position' => 41
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => 'name',
|
|
|
|
'type' => Lexer::T_IDENTIFIER,
|
|
|
|
'position' => 42
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-03-20 20:53:14 +00:00
|
|
|
'value' => '=',
|
2009-11-03 21:42:58 +00:00
|
|
|
'type' => Lexer::T_EQUALS,
|
2009-03-20 20:53:14 +00:00
|
|
|
'position' => 47
|
2016-12-07 23:33:41 +01:00
|
|
|
],
|
|
|
|
[
|
2009-06-14 17:34:28 +00:00
|
|
|
'value' => "Jack O'Neil",
|
2009-03-20 20:53:14 +00:00
|
|
|
'type' => Lexer::T_STRING,
|
|
|
|
'position' => 49
|
2016-12-07 23:33:41 +01:00
|
|
|
]
|
|
|
|
];
|
2009-03-20 20:53:14 +00:00
|
|
|
|
|
|
|
foreach ($tokens as $expected) {
|
|
|
|
$lexer->moveNext();
|
|
|
|
$actual = $lexer->lookahead;
|
|
|
|
$this->assertEquals($expected['value'], $actual['value']);
|
|
|
|
$this->assertEquals($expected['type'], $actual['type']);
|
|
|
|
$this->assertEquals($expected['position'], $actual['position']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->assertFalse($lexer->moveNext());
|
|
|
|
}
|
2015-04-26 23:10:51 +02:00
|
|
|
|
|
|
|
public function provideTokens()
|
|
|
|
{
|
2016-12-07 23:33:41 +01:00
|
|
|
return [
|
|
|
|
[Lexer::T_IDENTIFIER, 'u'], // one char
|
|
|
|
[Lexer::T_IDENTIFIER, 'someIdentifier'],
|
|
|
|
[Lexer::T_IDENTIFIER, 's0m31d3nt1f13r'], // including digits
|
|
|
|
[Lexer::T_IDENTIFIER, 'some_identifier'], // including underscore
|
|
|
|
[Lexer::T_IDENTIFIER, '_some_identifier'], // starts with underscore
|
|
|
|
[Lexer::T_IDENTIFIER, 'comma'], // name of a token class with value < 100 (whitebox test)
|
|
|
|
[Lexer::T_FULLY_QUALIFIED_NAME, 'Some\Class'], // DQL class reference
|
|
|
|
[Lexer::T_ALIASED_NAME, 'Some:Name'],
|
|
|
|
[Lexer::T_ALIASED_NAME, 'Some:Subclassed\Name']
|
|
|
|
];
|
2015-04-26 23:10:51 +02:00
|
|
|
}
|
2009-03-20 20:53:14 +00:00
|
|
|
}
|