Passed
Push — master ( f8eb54...68901a )
by Kirill
04:07
created

Analyzer::getMapping()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
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\Grammar\PP2;
11
12
use Railt\Compiler\Iterator\LookaheadIterator;
13
use Railt\Compiler\Reader\ProvideTokens;
14
use Railt\Parser\Rule\Production;
15
use Railt\Parser\Rule\Symbol;
16
use Railt\Parser\Rule\Terminal;
17
18
/**
19
 * Class Analyzer
20
 */
21
class Analyzer
22
{
23
    /**
24
     * A list of parsed rules
25
     *
26
     * @var array|Symbol[]|Terminal[]|Production[]
27
     */
28
    private $parsed = [];
29
30
    /**
31
     * A list of kept rule names.
32
     *
33
     * @var array
34
     */
35
    private $keep;
36
37
    /**
38
     * @var Mapping
39
     */
40
    private $mapping;
41
42
    /**
43
     * @var array
44
     */
45
    private $ruleTokens = [];
46
47
    /**
48
     * @var ProvideTokens
49
     */
50
    private $tokens;
51
52
    /**
53
     * Analyzer constructor.
54
     * @param array $keep
55
     * @param ProvideTokens $tokens
56
     */
57
    public function __construct(array $keep, ProvideTokens $tokens)
58
    {
59
        $this->keep = $keep;
60
        $this->mapping = new Mapping();
61
        $this->tokens = $tokens;
62
    }
63
64
    /**
65
     * @param string $rule
66
     * @param iterable $tokens
67
     */
68
    public function add(string $rule, iterable $tokens): void
69
    {
70
        $this->ruleTokens[$rule] = $tokens;
71
    }
72
73
    /**
74
     * @param string $rule
75
     * @return bool
76
     */
77
    public function isCompleted(string $rule): bool
78
    {
79
        return \array_key_exists($rule, $this->parsed);
80
    }
81
82
    /**
83
     * @return array
84
     * @throws \InvalidArgumentException
85
     */
86
    public function getResult(): array
87
    {
88
        $this->parsed = [];
89
        $this->parse();
90
91
        return $this->parsed;
92
    }
93
94
    /**
95
     * @throws \InvalidArgumentException
96
     */
97
    private function parse(): void
98
    {
99
        foreach ($this->ruleTokens as $rule => $tokens) {
100
            $this->store($this->build($rule, $tokens));
101
        }
102
    }
103
104
    /**
105
     * @param Symbol $symbol
106
     */
107
    public function store(Symbol $symbol): void
108
    {
109
        $this->parsed[] = $symbol;
110
    }
111
112
    /**
113
     * @return Mapping
114
     */
115
    public function getMapping(): Mapping
116
    {
117
        return $this->mapping;
118
    }
119
120
    /**
121
     * @param string $rule
122
     * @param array $tokens
123
     * @return Production
124
     * @throws \InvalidArgumentException
125
     */
126
    public function build(string $rule, array $tokens): Production
127
    {
128
        return $this->group(new LookaheadIterator($tokens), $rule)->reduce();
0 ignored issues
show
Documentation introduced by
$tokens is of type array, but the function expects a object<Railt\Compiler\Iterator\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
129
    }
130
131
    /**
132
     * @param string $rule
133
     * @return int
134
     * @throws \InvalidArgumentException
135
     */
136
    public function fetchId(string $rule): int
137
    {
138
        if ($this->mapping->has($rule)) {
139
            return $this->mapping->id($rule);
140
        }
141
142
        return $this->build($rule, $this->ruleTokens[$rule])->getId();
143
    }
144
145
    /**
146
     * @param LookaheadIterator $iterator
147
     * @param string|null $rule
148
     * @return Group
149
     */
150
    public function group(LookaheadIterator $iterator, string $rule = null): Group
151
    {
152
        if ($rule && ! \in_array($rule, $this->keep, true)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $rule of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
153
            $rule = null;
154
        }
155
156
        return new Group($iterator, $this, $rule);
157
    }
158
}
159