1
0
mirror of https://github.com/halaxa/json-machine.git synced 2025-01-17 04:58:16 +01:00

Stateful Lexer

This commit is contained in:
Filip Halaxa 2022-01-09 16:45:08 +01:00
parent f5492d7223
commit 955a90f637
4 changed files with 69 additions and 10 deletions

View File

@ -9,6 +9,10 @@ class Lexer implements \IteratorAggregate, PositionAware
/** @var iterable */
private $jsonChunks;
private $inString = false;
private $tokenBuffer = '';
private $escaping = false;
/**
* @param iterable<string> $jsonChunks
*/
@ -31,9 +35,9 @@ class Lexer implements \IteratorAggregate, PositionAware
$tokenBoundaries = $this->tokenBoundaries();
$colonCommaBracket = $this->colonCommaBracketTokenBoundaries();
$inString = false;
$tokenBuffer = '';
$escaping = false;
$inString = $this->inString;
$tokenBuffer = $this->tokenBuffer;
$escaping = $this->escaping;
foreach ($this->jsonChunks as $jsonChunk) {
$bytesLength = strlen($jsonChunk);
@ -75,9 +79,10 @@ class Lexer implements \IteratorAggregate, PositionAware
}
}
}
if ($tokenBuffer != '') {
yield $tokenBuffer;
}
$this->inString = $inString;
$this->tokenBuffer = $tokenBuffer;
$this->escaping = $escaping;
}
private function tokenBoundaries()

23
src/QueueChunks.php Normal file
View File

@ -0,0 +1,23 @@
<?php declare(strict_types=1);
namespace JsonMachine;
use Exception;
use Traversable;
class QueueChunks implements \IteratorAggregate
{
private $queue = [];
public function push(string $jsonChunk)
{
$this->queue[] = $jsonChunk;
}
public function getIterator()
{
yield from $this->queue;
$this->queue = [];
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace JsonMachineTest;
use JsonMachine\Lexer;
use JsonMachine\QueueChunks;
use PHPUnit\Framework\TestCase;
class FollowUpParserTest extends TestCase
{
public function testParses()
{
}
}

View File

@ -5,6 +5,7 @@ namespace JsonMachineTest;
use JsonMachine\DebugLexer;
use JsonMachine\Lexer;
use JsonMachine\Exception;
use JsonMachine\QueueChunks;
use JsonMachine\StreamChunks;
use JsonMachine\StringChunks;
@ -23,8 +24,8 @@ class LexerTest extends \PHPUnit_Framework_TestCase
*/
public function testCorrectlyYieldsZeroToken($lexerClass)
{
$data = ['0'];
$expected = ['0'];
$data = ['[0]'];
$expected = ['[', '0', ']'];
$this->assertEquals($expected, iterator_to_array(new $lexerClass(new \ArrayIterator($data))));
$stream = fopen('data://text/plain,{"value":0}', 'r');
@ -37,8 +38,8 @@ class LexerTest extends \PHPUnit_Framework_TestCase
*/
public function testGeneratesTokens($lexerClass)
{
$data = ['{}[],:null,"string" false:', 'true,1,100000,1.555{-56]"","\\""'];
$expected = ['{','}','[',']',',',':','null',',','"string"','false',':','true',',','1',',','100000',',','1.555','{','-56',']','""',',','"\\""'];
$data = ['{}[],:null,"string" false:', 'true,1,100000,1.555{-56]"","\\""]'];
$expected = ['{','}','[',']',',',':','null',',','"string"','false',':','true',',','1',',','100000',',','1.555','{','-56',']','""',',','"\\""',']'];
$this->assertEquals($expected, iterator_to_array(new $lexerClass(new \ArrayIterator($data))));
}
@ -144,6 +145,21 @@ class LexerTest extends \PHPUnit_Framework_TestCase
}
}
public function testRepeatedlyParsesModifiedQueue()
{
$queue = new QueueChunks();
$lexer = new Lexer($queue);
$queue->push('[1,2,4');
$this->assertEquals(['[', '1', ',', '2', ','], iterator_to_array($lexer));
$queue->push('2,"some ');
$this->assertEquals(['42', ','], iterator_to_array($lexer));
$queue->push('string"]');
$this->assertEquals(['"some string"', ']'], iterator_to_array($lexer));
}
/**
* @param string $formattedJsonFilePath
* @dataProvider dataProvidesLocationalData