Move Tokenizer logic to Lexer to improve speed

This commit is contained in:
Andrea Marco Sartori 2023-01-24 17:32:39 +10:00
parent 898e1feff0
commit 6710ef4415
2 changed files with 28 additions and 74 deletions

View File

@ -4,11 +4,12 @@ namespace Cerbero\JsonParser;
use Cerbero\JsonParser\Sources\Source;
use Cerbero\JsonParser\Tokens\Token;
use Cerbero\JsonParser\Tokens\Tokenizer;
use Cerbero\JsonParser\Tokens\Tokens;
use IteratorAggregate;
use Traversable;
use function strlen;
/**
* The JSON lexer.
*
@ -23,6 +24,13 @@ final class Lexer implements IteratorAggregate
*/
private Progress $progress;
/**
* The map of token instances by type.
*
* @var array<int, Token>
*/
private array $tokensMap;
/**
* The current position.
*
@ -38,6 +46,21 @@ final class Lexer implements IteratorAggregate
public function __construct(private Source $source)
{
$this->progress = new Progress();
$this->setTokensMap();
}
/**
* Set the tokens map
*
* @return void
*/
private function setTokensMap(): void
{
$instances = [];
foreach (Tokens::MAP as $type => $class) {
$this->tokensMap[$type] = $instances[$class] ??= new $class();
}
}
/**
@ -64,12 +87,14 @@ final class Lexer implements IteratorAggregate
}
if ($buffer != '') {
yield Tokenizer::instance()->toToken($buffer);
$type = Tokens::TYPES[$buffer[0]];
yield $this->tokensMap[$type]->setValue($buffer);
$buffer = '';
}
if (isset(Tokens::DELIMITERS[$character])) {
yield Tokenizer::instance()->toToken($character);
$type = Tokens::TYPES[$character];
yield $this->tokensMap[$type]->setValue($character);
}
}
}

View File

@ -1,71 +0,0 @@
<?php
namespace Cerbero\JsonParser\Tokens;
/**
* The tokenizer.
*
*/
final class Tokenizer
{
/**
* The singleton instance.
*
* @var static
*/
private static self $instance;
/**
* The map of token instances by type.
*
* @var array<int, Token>
*/
private array $tokensMap;
/**
* Retrieve the singleton instance
*
* @return static
*/
public static function instance(): static
{
return static::$instance ??= new static();
}
/**
* Instantiate the class.
*
*/
private function __construct()
{
$this->setTokensMap();
}
/**
* Set the tokens map
*
* @return void
*/
private function setTokensMap(): void
{
$instances = [];
foreach (Tokens::MAP as $type => $class) {
$this->tokensMap[$type] = $instances[$class] ??= new $class();
}
}
/**
* Turn the given value into a token
*
* @param string $value
* @return Token
*/
public function toToken(string $value): Token
{
$character = $value[0];
$type = Tokens::TYPES[$character];
return $this->tokensMap[$type]->setValue($value);
}
}