TokenReader   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 23
c 1
b 0
f 0
dl 0
loc 88
ccs 24
cts 24
cp 1
rs 10
wmc 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getEmptyLexeme() 0 3 1
A isFinished() 0 3 1
A getOffset() 0 3 1
A __construct() 0 4 1
A read() 0 19 4
A getIterator() 0 4 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Remorhaz\Lexer\Runtime\Token;
6
7
use Iterator;
8
use IteratorAggregate;
9
use Remorhaz\Lexer\Runtime\IO\EmptyLexeme;
10
use Remorhaz\Lexer\Runtime\IO\LexemeInterface;
11
use Remorhaz\Lexer\Runtime\IO\PreviewBufferInterface;
12
13
final class TokenReader implements IteratorAggregate, TokenReaderInterface
14
{
15
16
    /**
17
     * @var PreviewBufferInterface
18
     */
19
    private $previewBuffer;
20
21
    /**
22
     * @var MatcherSelectorInterface
23
     */
24
    private $matcherSelector;
25
26
    /**
27
     * @var int
28
     */
29
    private $offset = 0;
30
31
    /**
32
     * @var bool
33
     */
34
    private $isFinished = false;
35
36 12
    public function __construct(PreviewBufferInterface $previewBuffer, MatcherSelectorInterface $tokenContext)
37
    {
38 12
        $this->previewBuffer = $previewBuffer;
39 12
        $this->matcherSelector = $tokenContext;
40 12
    }
41
42
    /**
43
     * @return bool
44
     * @psalm-pure
45
     */
46 3
    public function isFinished(): bool
47
    {
48 3
        return $this->isFinished;
49
    }
50
51
    /**
52
     * @return int
53
     * @psalm-pure
54
     */
55 5
    public function getOffset(): int
56
    {
57 5
        return $this->offset;
58
    }
59
60
    /**
61
     * @return TokenInterface
62
     */
63 8
    public function read(): TokenInterface
64
    {
65 8
        if ($this->isFinished) {
66 1
            throw new Exception\UnexpectedEndOfInputException($this->getEmptyLexeme()->getStartOffsets());
67
        }
68
69 8
        if ($this->previewBuffer->isFinished()) {
70 5
            $this->isFinished = true;
71
72 5
            return Token::createEoi($this->offset, $this->previewBuffer->getEmptyLexeme());
73
        }
74
75
        do {
76 4
            $matcher = $this->matcherSelector->getMatcher();
77 4
            $matchResult = $matcher->match($this->offset, $this->previewBuffer, $this->matcherSelector);
78 4
        } while ($matchResult->shouldRepeat());
79 4
        $this->offset++;
80
81 4
        return $matchResult->getToken();
82
    }
83
84
    /**
85
     * @return LexemeInterface
86
     * @psalm-pure
87
     */
88 4
    public function getEmptyLexeme(): LexemeInterface
89
    {
90 4
        return new EmptyLexeme($this->offset, $this->previewBuffer->getEmptyLexeme());
91
    }
92
93
    /**
94
     * @return Iterator
95
     * @psalm-return Iterator<int, TokenInterface>
96
     */
97 1
    public function getIterator(): Iterator
98
    {
99 1
        while (!$this->isFinished()) {
100 1
            yield $this->getOffset() => $this->read();
101
        }
102 1
    }
103
}
104