Skip to content

Commit b7d3232

Browse files
authored
Merge pull request #5 from deliangyang/optimize-code
feat: optimize state
2 parents c848b40 + ac33a05 commit b7d3232

File tree

2 files changed

+93
-85
lines changed

2 files changed

+93
-85
lines changed

StateMachine/State.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace StateMachine;
4+
5+
class State
6+
{
7+
8+
const EXPECT_SINGLE_VALUE = 0x1;
9+
10+
const EXPECT_BEGIN_OBJECT = 0x2;
11+
12+
const EXPECT_BEGIN_ARRAY = 0x4;
13+
14+
const EXPECT_END_DOCUMENT = 0x8;
15+
16+
const EXPECT_COMMA = 0x10;
17+
18+
const EXPECT_COLON = 0x20;
19+
20+
const EXPECT_OBJECT_KEY = 0x40;
21+
22+
const EXPECT_OBJECT_VALUE = 0x80;
23+
24+
const EXPECT_END_OBJECT = 0x100;
25+
26+
const EXPECT_END_ARRAY = 0x200;
27+
28+
const EXPECT_ARRAY_VALUE = 0x400;
29+
30+
public static array $stateMap = [
31+
self::EXPECT_SINGLE_VALUE => 'EXPECT_SINGLE_VALUE',
32+
self::EXPECT_BEGIN_OBJECT => 'EXPECT_BEGIN_OBJECT',
33+
self::EXPECT_BEGIN_ARRAY => 'EXPECT_BEGIN_ARRAY',
34+
self::EXPECT_END_DOCUMENT => 'EXPECT_END_DOCUMENT',
35+
self::EXPECT_COMMA => 'EXPECT_COMMA',
36+
self::EXPECT_COLON => 'EXPECT_COLON',
37+
self::EXPECT_OBJECT_KEY => 'EXPECT_OBJECT_KEY',
38+
self::EXPECT_OBJECT_VALUE => 'EXPECT_OBJECT_VALUE',
39+
self::EXPECT_END_OBJECT => 'EXPECT_END_OBJECT',
40+
self::EXPECT_END_ARRAY => 'EXPECT_END_ARRAY',
41+
self::EXPECT_ARRAY_VALUE => 'EXPECT_ARRAY_VALUE',
42+
];
43+
44+
}

StateMachine/StateParser.php

Lines changed: 49 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,7 @@
55
class StateParser
66
{
77

8-
const EXPECT_SINGLE_VALUE = 0x1;
9-
10-
const EXPECT_BEGIN_OBJECT = 0x2;
11-
12-
const EXPECT_BEGIN_ARRAY = 0x4;
13-
14-
const EXPECT_END_DOCUMENT = 0x8;
15-
16-
const EXPECT_COMMA = 0x10;
17-
18-
const EXPECT_COLON = 0x20;
19-
20-
const EXPECT_OBJECT_KEY = 0x40;
21-
22-
const EXPECT_OBJECT_VALUE = 0x80;
23-
24-
const EXPECT_END_OBJECT = 0x100;
25-
26-
const EXPECT_END_ARRAY = 0x200;
27-
28-
const EXPECT_ARRAY_VALUE = 0x400;
29-
30-
protected array $stateMap = [
31-
self::EXPECT_SINGLE_VALUE => 'EXPECT_SINGLE_VALUE',
32-
self::EXPECT_BEGIN_OBJECT => 'EXPECT_BEGIN_OBJECT',
33-
self::EXPECT_BEGIN_ARRAY => 'EXPECT_BEGIN_ARRAY',
34-
self::EXPECT_END_DOCUMENT => 'EXPECT_END_DOCUMENT',
35-
self::EXPECT_COMMA => 'EXPECT_COMMA',
36-
self::EXPECT_COLON => 'EXPECT_COLON',
37-
self::EXPECT_OBJECT_KEY => 'EXPECT_OBJECT_KEY',
38-
self::EXPECT_OBJECT_VALUE => 'EXPECT_OBJECT_VALUE',
39-
self::EXPECT_END_OBJECT => 'EXPECT_END_OBJECT',
40-
self::EXPECT_END_ARRAY => 'EXPECT_END_ARRAY',
41-
self::EXPECT_ARRAY_VALUE => 'EXPECT_ARRAY_VALUE',
42-
];
43-
44-
protected $state = 0;
8+
protected int $state = 0;
459

4610
protected Reader $reader;
4711

@@ -57,41 +21,41 @@ public function parser()
5721
{
5822
$result = null;
5923
$stack = [];
60-
$this->state = self::EXPECT_SINGLE_VALUE | self::EXPECT_BEGIN_ARRAY | self::EXPECT_BEGIN_OBJECT;
24+
$this->state = State::EXPECT_SINGLE_VALUE | State::EXPECT_BEGIN_ARRAY | State::EXPECT_BEGIN_OBJECT;
6125
for (; ;) {
6226
$token = $this->reader->nextToken();
6327
// echo implode(' => ', [Token::token2name($token), $this->state()]), PHP_EOL;
6428
switch ($token) {
6529
case Token::OBJECT_BEGIN:
66-
if ($this->hasState(self::EXPECT_BEGIN_OBJECT)) {
30+
if ($this->hasState(State::EXPECT_BEGIN_OBJECT)) {
6731
/**
6832
* {{ | { "a" | {}
6933
*/
7034
array_push($stack, []);
71-
$this->state = self::EXPECT_OBJECT_KEY | self::EXPECT_BEGIN_OBJECT | self::EXPECT_END_OBJECT;
35+
$this->state = State::EXPECT_OBJECT_KEY | State::EXPECT_BEGIN_OBJECT | State::EXPECT_END_OBJECT;
7236
break;
7337
}
7438
throw new \Exception('unexpected char: {');
7539
case Token::OBJECT_END:
76-
if ($this->hasState(self::EXPECT_END_OBJECT)) {
40+
if ($this->hasState(State::EXPECT_END_OBJECT)) {
7741
$lastValue = array_pop($stack);
7842
if (empty($stack)) {
7943
array_push($stack, $lastValue);
80-
$this->state = self::EXPECT_END_DOCUMENT;
44+
$this->state = State::EXPECT_END_DOCUMENT;
8145
break;
8246
}
8347
$topValue = array_pop($stack);
8448
if (is_string($topValue)) {
8549
$object = array_pop($stack);
8650
$object[$topValue] = $lastValue;
8751
array_push($stack, $object);
88-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_OBJECT;
52+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_OBJECT;
8953
break;
9054
} else if (is_array($topValue)) {
9155
// 前面是一个数组
9256
$topValue[] = $lastValue;
9357
array_push($stack, $topValue);
94-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_ARRAY;
58+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_ARRAY;
9559
break;
9660
}
9761
}
@@ -101,9 +65,9 @@ public function parser()
10165
$this->state()
10266
));
10367
case Token::ARRAY_BEGIN:
104-
if ($this->hasState(self::EXPECT_BEGIN_ARRAY)) {
68+
if ($this->hasState(State::EXPECT_BEGIN_ARRAY)) {
10569
array_push($stack, []);
106-
$this->state = self::EXPECT_ARRAY_VALUE | self::EXPECT_BEGIN_OBJECT | self::EXPECT_BEGIN_ARRAY | self::EXPECT_END_ARRAY;
70+
$this->state = State::EXPECT_ARRAY_VALUE | State::EXPECT_BEGIN_OBJECT | State::EXPECT_BEGIN_ARRAY | State::EXPECT_END_ARRAY;
10771
break;
10872
}
10973
throw new \Exception(sprintf(
@@ -112,9 +76,9 @@ public function parser()
11276
$this->state()
11377
));
11478
case Token::ARRAY_END:
115-
if ($this->hasState(self::EXPECT_END_ARRAY)) {
79+
if ($this->hasState(State::EXPECT_END_ARRAY)) {
11680
if (1 >= count($stack)) {
117-
$this->state = self::EXPECT_END_DOCUMENT;
81+
$this->state = State::EXPECT_END_DOCUMENT;
11882
break;
11983
}
12084
$val = array_pop($stack);
@@ -123,11 +87,11 @@ public function parser()
12387
$obj = array_pop($stack);
12488
$obj[$first] = $val;
12589
array_push($stack, $obj);
126-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_OBJECT;
90+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_OBJECT;
12791
} else if (is_array($first)) {
12892
array_push($first, $val);
12993
array_push($stack, $first);
130-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_ARRAY;
94+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_ARRAY;
13195
break;
13296
}
13397
break;
@@ -138,96 +102,96 @@ public function parser()
138102
$this->state()
139103
));
140104
case Token::NUMBER:
141-
if ($this->hasState(self::EXPECT_SINGLE_VALUE)) {
105+
if ($this->hasState(State::EXPECT_SINGLE_VALUE)) {
142106
array_push($stack, $this->reader->readNumber());
143-
$this->state = self::EXPECT_END_DOCUMENT;
107+
$this->state = State::EXPECT_END_DOCUMENT;
144108
break;
145-
} else if ($this->hasState(self::EXPECT_ARRAY_VALUE)) {
109+
} else if ($this->hasState(State::EXPECT_ARRAY_VALUE)) {
146110
$number = $this->reader->readNumber();
147111
$array = array_pop($stack);
148112
$array[] = $number;
149113
array_push($stack, $array);
150-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_ARRAY;
114+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_ARRAY;
151115
break;
152-
} else if ($this->hasState(self::EXPECT_OBJECT_VALUE)) {
116+
} else if ($this->hasState(State::EXPECT_OBJECT_VALUE)) {
153117
$number = $this->reader->readNumber();
154118
$key = array_pop($stack);
155119
$object = array_pop($stack);
156120
$object[$key] = $number;
157121
array_push($stack, $object);
158-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_OBJECT;
122+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_OBJECT;
159123
break;
160124
}
161125
break;
162126
case Token::STRING:
163-
if ($this->hasState(self::EXPECT_SINGLE_VALUE)) {
127+
if ($this->hasState(State::EXPECT_SINGLE_VALUE)) {
164128
$value = $this->reader->readString();
165129
array_push($stack, $value);
166-
$this->state = self::EXPECT_END_DOCUMENT;
130+
$this->state = State::EXPECT_END_DOCUMENT;
167131
break;
168-
} else if ($this->hasState(self::EXPECT_ARRAY_VALUE)) {
132+
} else if ($this->hasState(State::EXPECT_ARRAY_VALUE)) {
169133
$str = $this->reader->readString();
170134
$array = array_pop($stack);
171135
$array[] = $str;
172136
array_push($stack, $array);
173-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_ARRAY;
137+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_ARRAY;
174138
break;
175-
} else if ($this->hasState(self::EXPECT_OBJECT_KEY)) {
139+
} else if ($this->hasState(State::EXPECT_OBJECT_KEY)) {
176140
$value = $this->reader->readString();
177141
array_push($stack, $value);
178-
$this->state = self::EXPECT_COLON;
142+
$this->state = State::EXPECT_COLON;
179143
break;
180-
} else if ($this->hasState(self::EXPECT_OBJECT_VALUE)) {
144+
} else if ($this->hasState(State::EXPECT_OBJECT_VALUE)) {
181145
$value = $this->reader->readString();
182146
$key = array_pop($stack);
183147
$object = array_pop($stack);
184148
$object[$key] = $value;
185149
array_push($stack, $object);
186-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_OBJECT;
150+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_OBJECT;
187151
break;
188152
}
189153
throw new \Exception('unexpected string');
190154
case Token::BOOLEAN:
191-
if ($this->hasState(self::EXPECT_SINGLE_VALUE)) {
155+
if ($this->hasState(State::EXPECT_SINGLE_VALUE)) {
192156
array_push($stack, $this->reader->readBoolean());
193-
$this->state = self::EXPECT_END_DOCUMENT;
157+
$this->state = State::EXPECT_END_DOCUMENT;
194158
break;
195-
} else if ($this->hasState(self::EXPECT_OBJECT_VALUE)) {
159+
} else if ($this->hasState(State::EXPECT_OBJECT_VALUE)) {
196160
// {'aa': bool,?},
197161
$value = $this->reader->readBoolean();
198162
$key = array_pop($stack);
199163
$object = array_pop($stack);
200164
$object[$key] = $value;
201165
array_push($stack, $object);
202-
$this->state = self::EXPECT_END_OBJECT | self::EXPECT_COMMA;
166+
$this->state = State::EXPECT_END_OBJECT | State::EXPECT_COMMA;
203167
break;
204-
} else if ($this->hasState(self::EXPECT_ARRAY_VALUE)) {
168+
} else if ($this->hasState(State::EXPECT_ARRAY_VALUE)) {
205169
$value = $this->reader->readBoolean();
206170
$array = array_pop($stack);
207171
$array[] = $value;
208172
array_push($array);
209-
$this->state = self::EXPECT_END_ARRAY | self::EXPECT_COMMA;
173+
$this->state = State::EXPECT_END_ARRAY | State::EXPECT_COMMA;
210174
break;
211175
}
212176
throw new \Exception('unexpected boolean.');
213177
case Token::VALUE_NULL:
214178
$isNull = $this->reader->readNull();
215-
if ($isNull && $this->hasState(self::EXPECT_SINGLE_VALUE)) {
179+
if ($isNull && $this->hasState(State::EXPECT_SINGLE_VALUE)) {
216180
array_push($stack, null);
217-
$this->state = self::EXPECT_END_DOCUMENT;
181+
$this->state = State::EXPECT_END_DOCUMENT;
218182
break;
219-
} else if ($isNull && $this->hasState(self::EXPECT_ARRAY_VALUE)) {
183+
} else if ($isNull && $this->hasState(State::EXPECT_ARRAY_VALUE)) {
220184
$array = array_pop($stack);
221185
$array[] = null;
222186
array_push($stack, $array);
223-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_ARRAY;
187+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_ARRAY;
224188
break;
225-
} else if ($isNull && $this->hasState(self::EXPECT_OBJECT_VALUE)) {
189+
} else if ($isNull && $this->hasState(State::EXPECT_OBJECT_VALUE)) {
226190
$key = array_pop($stack);
227191
$obj = array_pop($stack);
228192
$obj[$key] = null;
229193
array_push($stack, $obj);
230-
$this->state = self::EXPECT_COMMA | self::EXPECT_END_OBJECT;
194+
$this->state = State::EXPECT_COMMA | State::EXPECT_END_OBJECT;
231195
break;
232196
}
233197
throw new \Exception(sprintf(
@@ -236,7 +200,7 @@ public function parser()
236200
$this->state()
237201
));
238202
case Token::END:
239-
if ($this->hasState(self::EXPECT_END_DOCUMENT)) {
203+
if ($this->hasState(State::EXPECT_END_DOCUMENT)) {
240204
$value = array_pop($stack);
241205
if (count($stack) <= 0) {
242206
return $value;
@@ -249,12 +213,12 @@ public function parser()
249213
));
250214
case Token::COMMA:
251215
// ,
252-
if ($this->hasState(self::EXPECT_COMMA)) {
253-
if ($this->hasState(self::EXPECT_END_OBJECT)) {
254-
$this->state = self::EXPECT_OBJECT_KEY;
216+
if ($this->hasState(State::EXPECT_COMMA)) {
217+
if ($this->hasState(State::EXPECT_END_OBJECT)) {
218+
$this->state = State::EXPECT_OBJECT_KEY;
255219
break;
256-
} else if ($this->hasState(self::EXPECT_END_ARRAY)) {
257-
$this->state = self::EXPECT_ARRAY_VALUE | self::EXPECT_BEGIN_ARRAY | self::EXPECT_BEGIN_OBJECT;
220+
} else if ($this->hasState(State::EXPECT_END_ARRAY)) {
221+
$this->state = State::EXPECT_ARRAY_VALUE | State::EXPECT_BEGIN_ARRAY | State::EXPECT_BEGIN_OBJECT;
258222
break;
259223
}
260224
}
@@ -265,8 +229,8 @@ public function parser()
265229
));
266230
case Token::COLON:
267231
// :
268-
if (self::EXPECT_COLON === $this->state) {
269-
$this->state = self::EXPECT_OBJECT_VALUE | self::EXPECT_BEGIN_OBJECT | self::EXPECT_BEGIN_ARRAY;
232+
if (State::EXPECT_COLON === $this->state) {
233+
$this->state = State::EXPECT_OBJECT_VALUE | State::EXPECT_BEGIN_OBJECT | State::EXPECT_BEGIN_ARRAY;
270234
break;
271235
}
272236
throw new \Exception(sprintf(
@@ -295,7 +259,7 @@ protected function hasState(int $state): bool
295259
protected function state(): string
296260
{
297261
$states = [];
298-
foreach ($this->stateMap as $state => $name) {
262+
foreach (State::$stateMap as $state => $name) {
299263
if ($state & $this->state) {
300264
$states[] = $name;
301265
}

0 commit comments

Comments
 (0)