Skip to content

Commit

Permalink
Add support for float and bool as token value
Browse files Browse the repository at this point in the history
That means that `Lexer\::getType()` might transform `$value` into
string|int|float|bool, but never into objects.
  • Loading branch information
PowerKiKi committed Jul 12, 2024
1 parent cd03cc3 commit ba7456e
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/AbstractLexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* Base class for writing simple lexers, i.e. for creating small DSLs.
*
* @template T of UnitEnum|string|int
* @template V of string|int
* @template V of string|int|float|bool
*/
abstract class AbstractLexer
{
Expand Down
6 changes: 3 additions & 3 deletions src/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

/**
* @template T of UnitEnum|string|int
* @template V of string|int
* @template V of string|int|float|bool
*/
final class Token
{
Expand All @@ -20,7 +20,7 @@ final class Token
* @readonly
* @var V
*/
public string|int $value;
public string|int|float|bool $value;

/**
* The type of the token (identifier, numeric, string, input parameter, none)
Expand All @@ -41,7 +41,7 @@ final class Token
* @param V $value
* @param T|null $type
*/
public function __construct(string|int $value, $type, int $position)
public function __construct(string|int|float|bool $value, $type, int $position)
{
$this->value = $value;
$this->type = $type;
Expand Down
59 changes: 59 additions & 0 deletions tests/AbstractLexerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@

namespace Doctrine\Tests\Common\Lexer;

use Doctrine\Common\Lexer\AbstractLexer;
use Doctrine\Common\Lexer\Token;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

use function array_map;
use function assert;
use function count;
use function is_int;
use function is_numeric;
use function setlocale;

use const LC_ALL;
Expand Down Expand Up @@ -279,4 +282,60 @@ public function testMarkerAnnotationLocaleTr(): void
self::assertEquals('@', $mutableLexer->token->value);
self::assertEquals('ODM\Id', $mutableLexer->lookahead->value);
}

public function testCanTokenizeFloatValue(): void
{
$lexer = new /** @template-extends AbstractLexer<int, string|int|float|bool> */ class () extends AbstractLexer {
public const T_NONE = 1;

Check failure on line 289 in tests/AbstractLexerTest.php

View workflow job for this annotation

GitHub Actions / Static Analysis / Psalm (8.3)

MissingClassConstType

tests/AbstractLexerTest.php:289:26: MissingClassConstType: Class constant "Doctrine\Tests\Common\Lexer\_home_runner_work_lexer_lexer_tests_AbstractLexerTest_php_288_10102::T_NONE" should have a declared type. (see https://psalm.dev/359)
public const T_INTEGER = 2;

Check failure on line 290 in tests/AbstractLexerTest.php

View workflow job for this annotation

GitHub Actions / Static Analysis / Psalm (8.3)

MissingClassConstType

tests/AbstractLexerTest.php:290:26: MissingClassConstType: Class constant "Doctrine\Tests\Common\Lexer\_home_runner_work_lexer_lexer_tests_AbstractLexerTest_php_288_10102::T_INTEGER" should have a declared type. (see https://psalm.dev/359)
public const T_FLOAT = 4;

Check failure on line 291 in tests/AbstractLexerTest.php

View workflow job for this annotation

GitHub Actions / Static Analysis / Psalm (8.3)

MissingClassConstType

tests/AbstractLexerTest.php:291:26: MissingClassConstType: Class constant "Doctrine\Tests\Common\Lexer\_home_runner_work_lexer_lexer_tests_AbstractLexerTest_php_288_10102::T_FLOAT" should have a declared type. (see https://psalm.dev/359)
public const T_BOOL = 4;

Check failure on line 292 in tests/AbstractLexerTest.php

View workflow job for this annotation

GitHub Actions / Static Analysis / Psalm (8.3)

MissingClassConstType

tests/AbstractLexerTest.php:292:26: MissingClassConstType: Class constant "Doctrine\Tests\Common\Lexer\_home_runner_work_lexer_lexer_tests_AbstractLexerTest_php_288_10102::T_BOOL" should have a declared type. (see https://psalm.dev/359)

protected function getType(string|int|float|bool &$value): int
{
if ($value === 'y') {
$value = true;

return self::T_BOOL;
}

if (is_numeric($value)) {
$value += 0;

if (is_int($value)) {
return self::T_INTEGER;
}

return self::T_FLOAT;
}

return self::T_NONE;
}

/** {@inheritDoc} */
protected function getCatchablePatterns(): array
{
return [
'(?:[0-9]+)(?:[\.][0-9]+)?(?:e[+-]?[0-9]+)?',
'y',
];
}

/** {@inheritDoc} */
protected function getNonCatchablePatterns(): array
{
return ['\s+'];
}
};

$lexer->setInput('123.456');
$token = $lexer->peek();
assert($token !== null);
self::assertSame(123.456, $token->value, 'expect a real float, not a numerical string');

$lexer->setInput('y');
$token = $lexer->peek();
assert($token !== null);
self::assertTrue($token->value, 'expect a real bool, not a numerical string');
}
}

0 comments on commit ba7456e

Please sign in to comment.