Passed
Push — master ( c01dfe...f39ce2 )
by Edward
04:04
created

StateMap   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 44
dl 0
loc 172
rs 10
c 1
b 0
f 0
wmc 25

15 Methods

Rating   Name   Duplication   Size   Complexity  
A getStartState() 0 7 2
A replaceStartStateList() 0 4 1
A getValidState() 0 7 2
A importState() 0 9 3
A stateExists() 0 3 1
A createState() 0 9 2
A isFinishState() 0 5 1
A stateValueExists() 0 3 1
A getValueState() 0 8 2
A addStartState() 0 8 3
A getStateValue() 0 3 1
A getStartStateList() 0 3 1
A getStateList() 0 3 1
A addFinishState() 0 8 3
A getFinishStateList() 0 3 1
1
<?php
2
3
namespace Remorhaz\UniLex\RegExp\FSM;
4
5
use Remorhaz\UniLex\Exception;
6
7
use function array_key_first;
8
use function array_keys;
9
use function count;
10
11
class StateMap implements StateMapInterface
12
{
13
14
    private $lastStateId = 0;
15
16
    private $stateList = [];
17
18
    private $startStateList = [];
19
20
    private $finishStateList = [];
21
22
    /**
23
     * @param bool $value
24
     * @return int
25
     * @throws Exception
26
     */
27
    public function createState($value = true): int
28
    {
29
        if (is_null($value)) {
0 ignored issues
show
introduced by
The condition is_null($value) is always false.
Loading history...
30
            throw new Exception("Null state value is not allowed");
31
        }
32
        $stateId = ++$this->lastStateId;
33
        $this->stateList[$stateId] = $value;
34
35
        return $stateId;
36
    }
37
38
    /**
39
     * @return int[]
40
     */
41
    public function getStateList(): array
42
    {
43
        return array_keys($this->stateList);
44
    }
45
46
    /**
47
     * @param int $stateId
48
     * @return mixed
49
     * @throws Exception
50
     */
51
    public function getStateValue(int $stateId)
52
    {
53
        return $this->stateList[$this->getValidState($stateId)];
54
    }
55
56
    /**
57
     * @param     $value
58
     * @param int ...$stateList
59
     * @throws Exception
60
     */
61
    public function importState($value, int ...$stateList): void
62
    {
63
        foreach ($stateList as $stateId) {
64
            if (isset($this->stateList[$stateId])) {
65
                throw new Exception("State {$stateId} already exists");
66
            }
67
            $this->stateList[$stateId] = $value;
68
        }
69
        $this->lastStateId = max(array_keys($this->stateList));
70
    }
71
72
    /**
73
     * @param int ...$stateList
74
     * @throws Exception
75
     */
76
    public function addStartState(int ...$stateList): void
77
    {
78
        foreach ($stateList as $stateId) {
79
            $validStateId = $this->getValidState($stateId);
80
            if (isset($this->startStateList[$validStateId])) {
81
                throw new Exception("Start state {$validStateId} is already set");
82
            }
83
            $this->startStateList[$validStateId] = $this->stateList[$validStateId];
84
        }
85
    }
86
87
    /**
88
     * @return int
89
     * @throws Exception
90
     */
91
    public function getStartState(): int
92
    {
93
        if (count($this->startStateList) == 1) {
94
            return array_key_first($this->startStateList);
95
        }
96
97
        throw new Exception("Start state is undefined");
98
    }
99
100
    public function getStartStateList(): array
101
    {
102
        return array_keys($this->startStateList);
103
    }
104
105
    public function replaceStartStateList(int ...$stateIdList): void
106
    {
107
        $this->startStateList = [];
108
        $this->addStartState(...$stateIdList);
109
    }
110
111
    /**
112
     * @param int[] $stateList
113
     * @throws Exception
114
     */
115
    public function addFinishState(int ...$stateList): void
116
    {
117
        foreach ($stateList as $stateId) {
118
            $validStateId = $this->getValidState($stateId);
119
            if (isset($this->finishStateList[$validStateId])) {
120
                throw new Exception("Finish state {$validStateId} is already set");
121
            }
122
            $this->finishStateList[$validStateId] = $this->stateList[$validStateId];
123
        }
124
    }
125
126
    /**
127
     * @param int $stateId
128
     * @return bool
129
     * @throws Exception
130
     */
131
    public function isFinishState(int $stateId): bool
132
    {
133
        $validStateId = $this->getValidState($stateId);
134
135
        return isset($this->finishStateList[$validStateId]);
136
    }
137
138
    /**
139
     * @return int[]
140
     */
141
    public function getFinishStateList(): array
142
    {
143
        return array_keys($this->finishStateList);
144
    }
145
146
    public function stateExists(int $stateId): bool
147
    {
148
        return isset($this->stateList[$stateId]);
149
    }
150
151
    public function stateValueExists($value): bool
152
    {
153
        return false !== array_search($value, $this->stateList);
154
    }
155
156
    /**
157
     * @param $value
158
     * @return false|int|string
159
     * @throws Exception
160
     */
161
    public function getValueState($value)
162
    {
163
        $stateId = array_search($value, $this->stateList);
164
        if (false === $stateId) {
165
            throw new Exception("Value not found in state map");
166
        }
167
168
        return $stateId;
169
    }
170
171
    /**
172
     * @param int $stateId
173
     * @return int
174
     * @throws Exception
175
     */
176
    private function getValidState(int $stateId): int
177
    {
178
        if (!$this->stateExists($stateId)) {
179
            throw new Exception("State {$stateId} is undefined");
180
        }
181
182
        return $stateId;
183
    }
184
}
185