Completed
Push — master ( f6f8bd...61d974 )
by Kirill
02:08
created

RuleResolver   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 2
dl 0
loc 131
ccs 0
cts 60
cp 0
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A resolve() 0 16 4
A next() 0 14 3
B resolveCurrent() 0 23 4
A getRules() 0 4 1
A getKeep() 0 4 1
A getDelegates() 0 4 1
A getFiles() 0 4 1
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\Compiler\Reader\Resolver;
11
12
use Railt\Compiler\Exception\GrammarException;
13
use Railt\Io\Readable;
14
use Railt\Lexer\TokenInterface;
15
16
/**
17
 * Class RuleResolver
18
 */
19
class RuleResolver implements ResolverInterface
20
{
21
    /**
22
     * @var array|array[]
23
     */
24
    private $rules = [];
25
26
    /**
27
     * @var string|null
28
     */
29
    private $current;
30
31
    /**
32
     * @var array|string[]
33
     */
34
    private $keep = [];
35
36
    /**
37
     * @var array|string[]
38
     */
39
    private $delegates = [];
40
41
    /**
42
     * @var array|Readable[]
43
     */
44
    private $files = [];
45
46
    /**
47
     * @param Readable $readable
48
     * @param TokenInterface $token
49
     * @throws \Railt\Io\Exception\ExternalFileException
50
     */
51
    public function resolve(Readable $readable, TokenInterface $token): void
52
    {
53
        if ($this->next($readable, $token)) {
54
            return;
55
        }
56
57
        if (! \array_key_exists($this->current, $this->rules)) {
58
            $this->rules[$this->current] = [];
59
        }
60
61
        if (! \array_key_exists($this->current, $this->files)) {
62
            $this->files[$this->current] = $readable;
63
        }
64
65
        $this->rules[$this->current][] = $token;
66
    }
67
68
    /**
69
     * @param Readable $readable
70
     * @param TokenInterface $token
71
     * @return bool
72
     * @throws \Railt\Io\Exception\ExternalFileException
73
     */
74
    private function next(Readable $readable, TokenInterface $token): bool
75
    {
76
        if ($token->name() === 'T_NODE_DEFINITION') {
77
            $this->resolveCurrent($readable, $token);
78
            return true;
79
        }
80
81
        if ($this->current === null) {
82
            $error = \sprintf('Unprocessed production %s', $token->value(0));
83
            throw (new GrammarException($error))->throwsIn($readable, $token->offset());
84
        }
85
86
        return false;
87
    }
88
89
    /**
90
     * @param Readable $readable
91
     * @param TokenInterface $token
92
     * @throws \Railt\Io\Exception\ExternalFileException
93
     */
94
    private function resolveCurrent(Readable $readable, TokenInterface $token): void
95
    {
96
        [$name, $delegate, $keep] = [
0 ignored issues
show
Bug introduced by
The variable $name does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $delegate does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $keep does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
97
            \trim($token->value(1), '#'),
98
            $token->value(2),
99
            $token->value(1){0} === '#'
100
        ];
101
102
        $this->current = $name;
103
104
        if ($keep) {
105
            $this->keep[] = $this->current;
106
        }
107
108
        if ($delegate) {
109
            if (! \class_exists($delegate)) {
110
                $error = \sprintf('Could not found class "%s" to delegate rule "%s"', $delegate, $name);
111
                throw (new GrammarException($error))->throwsIn($readable, $token->offset());
112
            }
113
114
            $this->delegates[$this->current] = $delegate;
115
        }
116
    }
117
118
    /**
119
     * @return array|array[]
120
     */
121
    public function getRules(): array
122
    {
123
        return $this->rules;
124
    }
125
126
    /**
127
     * @return array|string[]
128
     */
129
    public function getKeep(): array
130
    {
131
        return $this->keep;
132
    }
133
134
    /**
135
     * @return array|string[]
136
     */
137
    public function getDelegates(): array
138
    {
139
        return $this->delegates;
140
    }
141
142
    /**
143
     * @return array
144
     */
145
    public function getFiles(): array
146
    {
147
        return $this->files;
148
    }
149
}
150