Passed
Branch feature/first-release (263de3)
by Andrea Marco
10:41
created

Lexer::getIterator()   B

Complexity

Conditions 11
Paths 30

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 11

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 11
eloc 17
c 2
b 0
f 0
nc 30
nop 0
dl 0
loc 25
ccs 18
cts 18
cp 1
crap 11
rs 7.3166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Cerbero\JsonParser\Tokens;
4
5
use Cerbero\JsonParser\Exceptions\SyntaxException;
6
use Cerbero\JsonParser\Sources\Source;
7
use Cerbero\JsonParser\Tokens\Token;
8
use Cerbero\JsonParser\Tokens\Tokenizer;
9
use Cerbero\JsonParser\Tokens\Tokens;
10
use Cerbero\JsonParser\ValueObjects\Progress;
11
use IteratorAggregate;
12
use Traversable;
13
14
use function strlen;
15
16
/**
17
 * The JSON lexer.
18
 *
19
 * @implements IteratorAggregate<int, Token>
20
 */
21
final class Lexer implements IteratorAggregate
22
{
23
    /**
24
     * The parsing progress.
25
     *
26
     * @var Progress
27
     */
28
    private Progress $progress;
29
30
    /**
31
     * The current position.
32
     *
33
     * @var int
34
     */
35
    private int $position = 1;
36
37
    /**
38
     * Instantiate the class.
39
     *
40
     * @param Source $source
41
     */
42 344
    public function __construct(private Source $source)
43
    {
44 344
        $this->progress = new Progress();
45
    }
46
47
    /**
48
     * Retrieve the JSON fragments
49
     *
50
     * @return \Generator<int, Token>
51
     */
52 332
    public function getIterator(): Traversable
53
    {
54 332
        $buffer = '';
55 332
        $inString = $isEscaping = false;
56 332
        $tokenizer = Tokenizer::instance();
57
58 332
        foreach ($this->source as $chunk) {
59 329
            for ($i = 0, $size = strlen($chunk); $i < $size; $i++, $this->position++) {
60 329
                $character = $chunk[$i];
61 329
                $inString = ($character == '"') != $inString || $isEscaping;
62 329
                $isEscaping = $character == '\\' && !$isEscaping;
63
64 329
                if ($inString || !isset(Tokens::BOUNDARIES[$character])) {
65 279
                    $buffer == '' && !isset(Tokens::TYPES[$character]) && throw new SyntaxException($character);
66 276
                    $buffer .= $character;
67 276
                    continue;
68
                }
69
70 328
                if ($buffer != '') {
71 276
                    yield $tokenizer->toToken($buffer);
72 272
                    $buffer = '';
73
                }
74
75 328
                if (isset(Tokens::DELIMITERS[$character])) {
76 328
                    yield $tokenizer->toToken($character);
77
                }
78
            }
79
        }
80
    }
81
82
    /**
83
     * Retrieve the current position
84
     *
85
     * @return int
86
     */
87 11
    public function position(): int
88
    {
89 11
        return $this->position;
90
    }
91
92
    /**
93
     * Retrieve the parsing progress
94
     *
95
     * @return Progress
96
     */
97
    public function progress(): Progress
98
    {
99
        return $this->progress->setCurrent($this->position)->setTotal($this->source->size());
100
    }
101
}
102