FirstBuilder::addTokensFromTerminalMap()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 5
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Remorhaz\UniLex\Parser\LL1\Lookup;
6
7
use Remorhaz\UniLex\Grammar\ContextFree\GrammarInterface;
8
9
class FirstBuilder
10
{
11
    private $grammar;
12
13
    private $first;
14
15
    public function __construct(GrammarInterface $grammar)
16
    {
17
        $this->grammar = $grammar;
18
    }
19
20
    /**
21
     * @return FirstInterface
22
     */
23
    public function getFirst(): FirstInterface
24
    {
25
        if (!isset($this->first)) {
26
            $first = new First();
27
            $this->addTokensFromTerminalMap($first);
28
            do {
29
                $first->resetChangeCount();
30
                $this->mergeProductionsFromNonTerminalMap($first);
31
            } while ($first->getChangeCount() > 0);
32
            $this->first = $first;
33
        }
34
        return $this->first;
35
    }
36
37
    /**
38
     * @param First $first
39
     */
40
    private function addTokensFromTerminalMap(First $first): void
41
    {
42
        foreach ($this->grammar->getTerminalList() as $symbolId) {
43
            $tokenId = $this->grammar->getToken($symbolId);
44
            $first->addToken($symbolId, $tokenId);
45
        }
46
    }
47
48
    /**
49
     * @param First $first
50
     */
51
    private function mergeProductionsFromNonTerminalMap(First $first): void
52
    {
53
        foreach ($this->grammar->getFullProductionList() as $production) {
54
            $first->mergeProductionEpsilons($production->getHeaderId(), ...$production->getSymbolList());
55
            $first->mergeProductionTokens($production->getHeaderId(), ...$production->getSymbolList());
56
        }
57
    }
58
}
59