This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file is part of PHP-Yacc 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 PhpYacc\Compress; |
||
11 | |||
12 | use PhpYacc\Grammar\Context; |
||
13 | use PhpYacc\Grammar\Symbol; |
||
14 | use PhpYacc\Support\Utils; |
||
15 | |||
16 | /** |
||
17 | * Class Compress. |
||
18 | */ |
||
19 | class Compress |
||
20 | { |
||
21 | const UNEXPECTED = 32767; |
||
22 | const DEFAULT = -32766; |
||
23 | const VACANT = -32768; |
||
24 | |||
25 | /** |
||
26 | * @var Context |
||
27 | */ |
||
28 | private $context; |
||
29 | |||
30 | /** |
||
31 | * @var CompressResult |
||
32 | */ |
||
33 | private $result; |
||
34 | |||
35 | /** |
||
36 | * @param Context $context |
||
37 | * |
||
38 | * @return CompressResult |
||
39 | */ |
||
40 | public function compress(Context $context) |
||
0 ignored issues
–
show
Coding Style
Best Practice
introduced
by
![]() |
|||
41 | { |
||
42 | $this->result = new CompressResult(); |
||
43 | $this->context = $context; |
||
44 | |||
45 | $this->makeupTable2(); |
||
46 | |||
47 | return $this->result; |
||
48 | } |
||
49 | |||
50 | /** |
||
51 | * @return void |
||
52 | */ |
||
53 | private function computePreImages() |
||
54 | { |
||
55 | /** @var PreImage[] $preImages */ |
||
56 | $preImages = []; |
||
57 | |||
58 | for ($i = 0; $i < $this->context->countStates; $i++) { |
||
59 | $preImages[$i] = new PreImage($i); |
||
60 | } |
||
61 | |||
62 | for ($i = 0; $i < $this->context->countClasses; $i++) { |
||
63 | for ($j = 0; $j < $this->context->countTerminals; $j++) { |
||
64 | $s = $this->context->classAction[$i][$j]; |
||
65 | if ($s > 0) { |
||
66 | $preImages[$s]->classes[$preImages[$s]->length++] = $i; |
||
67 | } |
||
68 | } |
||
69 | } |
||
70 | |||
71 | Utils::stableSort($preImages, PreImage::class.'::compare'); |
||
72 | |||
73 | $this->context->primof = \array_fill(0, $this->context->countStates, 0); |
||
74 | $this->context->prims = \array_fill(0, $this->context->countStates, 0); |
||
75 | $this->context->countPrims = 0; |
||
76 | |||
77 | for ($i = 0; $i < $this->context->countStates;) { |
||
78 | $p = $preImages[$i]; |
||
79 | $this->context->prims[$this->context->countPrims] = $p; |
||
80 | |||
81 | for (; $i < $this->context->countStates && PreImage::compare($p, $preImages[$i]) === 0; $i++) { |
||
82 | $this->context->primof[$preImages[$i]->index] = $p; |
||
83 | } |
||
84 | |||
85 | $p->index = $this->context->countPrims++; |
||
86 | } |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * @param array $t |
||
91 | * @param int $count |
||
92 | * |
||
93 | * @return array |
||
94 | */ |
||
95 | private function encodeShiftReduce(array $t, int $count): array |
||
96 | { |
||
97 | for ($i = 0; $i < $count; $i++) { |
||
98 | if ($t[$i] >= $this->context->countNonLeafStates) { |
||
99 | $t[$i] = $this->context->countNonLeafStates + $this->context->defaultAct[$t[$i]]; |
||
100 | } |
||
101 | } |
||
102 | |||
103 | return $t; |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * @return void |
||
108 | */ |
||
109 | private function makeupTable2() |
||
110 | { |
||
111 | $this->context->termAction = \array_fill(0, $this->context->countNonLeafStates, 0); |
||
112 | $this->context->classAction = \array_fill(0, $this->context->countNonLeafStates * 2, 0); |
||
113 | $this->context->nonTermGoto = \array_fill(0, $this->context->countNonLeafStates, 0); |
||
114 | $this->context->defaultAct = \array_fill(0, $this->context->countStates, 0); |
||
115 | $this->context->defaultGoto = \array_fill(0, $this->context->countNonTerminals, 0); |
||
116 | |||
117 | $this->resetFrequency(); |
||
118 | $this->context->stateImageSorted = \array_fill(0, $this->context->countNonLeafStates, 0); |
||
119 | $this->context->classOf = \array_fill(0, $this->context->countStates, 0); |
||
120 | |||
121 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
122 | $this->context->termAction[$i] = \array_fill(0, $this->context->countTerminals, self::VACANT); |
||
123 | $this->context->nonTermGoto[$i] = \array_fill(0, $this->context->countNonTerminals, self::VACANT); |
||
124 | |||
125 | foreach ($this->context->states[$i]->shifts as $shift) { |
||
126 | if ($shift->through->isTerminal) { |
||
127 | $this->context->termAction[$i][$shift->through->code] = $shift->number; |
||
128 | } else { |
||
129 | $this->context->nonTermGoto[$i][$this->nb($shift->through)] = $shift->number; |
||
130 | } |
||
131 | } |
||
132 | foreach ($this->context->states[$i]->reduce as $reduce) { |
||
133 | if ($reduce->symbol->isNilSymbol()) { |
||
134 | break; |
||
135 | } |
||
136 | $this->context->termAction[$i][$reduce->symbol->code] = -$this->encodeRederr($reduce->number); |
||
137 | } |
||
138 | $this->context->stateImageSorted[$i] = $i; |
||
139 | } |
||
140 | |||
141 | foreach ($this->context->states as $key => $state) { |
||
142 | $r = null; |
||
143 | foreach ($state->reduce as $r) { |
||
144 | if ($r->symbol->isNilSymbol()) { |
||
145 | break; |
||
146 | } |
||
147 | } |
||
148 | $this->context->defaultAct[$key] = $this->encodeRederr($r->number); |
||
149 | } |
||
150 | |||
151 | for ($j = 0; $j < $this->context->countNonTerminals; $j++) { |
||
152 | $max = 0; |
||
153 | $maxst = self::VACANT; |
||
154 | $this->resetFrequency(); |
||
155 | |||
156 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
157 | $st = $this->context->nonTermGoto[$i][$j]; |
||
158 | if ($st > 0) { |
||
159 | $this->context->frequency[$st]++; |
||
160 | if ($this->context->frequency[$st] > $max) { |
||
161 | $max = $this->context->frequency[$st]; |
||
162 | $maxst = $st; |
||
163 | } |
||
164 | } |
||
165 | } |
||
166 | $this->context->defaultGoto[$j] = $maxst; |
||
167 | } |
||
168 | // 847 |
||
169 | |||
170 | Utils::stableSort($this->context->stateImageSorted, [$this, 'cmpStates']); |
||
171 | |||
172 | $j = 0; |
||
173 | |||
174 | for ($i = 0; $i < $this->context->countNonLeafStates;) { |
||
175 | $k = $this->context->stateImageSorted[$i]; |
||
176 | $this->context->classAction[$j] = $this->context->termAction[$k]; |
||
177 | for (; $i < $this->context->countNonLeafStates && $this->cmpStates($this->context->stateImageSorted[$i], $k) === 0; $i++) { |
||
178 | $this->context->classOf[$this->context->stateImageSorted[$i]] = $j; |
||
179 | } |
||
180 | $j++; |
||
181 | } |
||
182 | $this->context->countClasses = $j; |
||
183 | |||
184 | if ($this->context->debug) { |
||
185 | $this->context->debug("State=>class:\n"); |
||
186 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
187 | if ($i % 10 === 0) { |
||
188 | $this->context->debug("\n"); |
||
189 | } |
||
190 | $this->context->debug(\sprintf('%3d=>%-3d ', $i, $this->context->classOf[$i])); |
||
191 | } |
||
192 | $this->context->debug("\n"); |
||
193 | } |
||
194 | |||
195 | $this->computePreImages(); |
||
196 | |||
197 | if ($this->context->debug) { |
||
198 | $this->printTable(); |
||
199 | } |
||
200 | |||
201 | $this->extractCommon(); |
||
202 | |||
203 | $this->authodoxTable(); |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @return void |
||
208 | */ |
||
209 | private function printTable() |
||
210 | { |
||
211 | $this->context->debug("\nTerminal action:\n"); |
||
212 | $this->context->debug(\sprintf('%8.8s', 'T\\S')); |
||
213 | for ($i = 0; $i < $this->context->countClasses; $i++) { |
||
214 | $this->context->debug(\sprintf('%4d', $i)); |
||
215 | } |
||
216 | $this->context->debug("\n"); |
||
217 | for ($j = 0; $j < $this->context->countTerminals; $j++) { |
||
218 | $symbol = $this->context->symbol($j); |
||
219 | |||
220 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
221 | if ($this->context->termAction[$i][$j] !== self::VACANT) { |
||
222 | break; |
||
223 | } |
||
224 | } |
||
225 | View Code Duplication | if ($i < $this->context->countNonLeafStates) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
226 | $this->context->debug(\sprintf('%8.8s', $symbol->name)); |
||
227 | for ($i = 0; $i < $this->context->countClasses; $i++) { |
||
228 | $this->context->debug(Utils::printAction($this->context->classAction[$i][$j])); |
||
229 | } |
||
230 | $this->context->debug("\n"); |
||
231 | } |
||
232 | } |
||
233 | |||
234 | $this->context->debug("\nNonterminal GOTO table:\n"); |
||
235 | $this->context->debug(\sprintf('%8.8s', 'T\\S')); |
||
236 | View Code Duplication | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
237 | $this->context->debug(\sprintf('%4d', $i)); |
||
238 | } |
||
239 | $this->context->debug("\n"); |
||
240 | foreach ($this->context->nonterminals as $symbol) { |
||
241 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
242 | if ($this->context->nonTermGoto[$i][$this->nb($symbol)] > 0) { |
||
243 | break; |
||
244 | } |
||
245 | } |
||
246 | View Code Duplication | if ($i < $this->context->countNonLeafStates) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
247 | $this->context->debug(\sprintf('%8.8s', $symbol->name)); |
||
248 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
249 | $this->context->debug(Utils::printAction($this->context->nonTermGoto[$i][$this->nb($symbol)])); |
||
250 | } |
||
251 | $this->context->debug("\n"); |
||
252 | } |
||
253 | } |
||
254 | |||
255 | $this->context->debug("\nNonterminal GOTO table:\n"); |
||
256 | $this->context->debug(\sprintf('%8.8s default', 'T\\S')); |
||
257 | |||
258 | View Code Duplication | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
259 | $this->context->debug(\sprintf('%4d', $i)); |
||
260 | } |
||
261 | |||
262 | $this->context->debug("\n"); |
||
263 | |||
264 | foreach ($this->context->nonterminals as $symbol) { |
||
265 | $nb = $this->nb($symbol); |
||
266 | |||
267 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
268 | if ($this->context->nonTermGoto[$i][$nb] > 0) { |
||
269 | break; |
||
270 | } |
||
271 | } |
||
272 | |||
273 | if ($i < $this->context->countNonLeafStates) { |
||
274 | $this->context->debug(\sprintf('%8.8s', $symbol->name)); |
||
275 | $this->context->debug(\sprintf('%8d', $this->context->defaultGoto[$nb])); |
||
276 | |||
277 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
278 | if ($this->context->nonTermGoto[$i][$nb] === $this->context->defaultGoto[$nb]) { |
||
279 | $this->context->debug(' = '); |
||
280 | } else { |
||
281 | $this->context->debug(Utils::printAction($this->context->nonTermGoto[$i][$nb])); |
||
282 | } |
||
283 | } |
||
284 | $this->context->debug("\n"); |
||
285 | } |
||
286 | } |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * @return void |
||
291 | */ |
||
292 | private function extractCommon() |
||
293 | { |
||
294 | $this->context->class2nd = \array_fill(0, $this->context->countClasses, -1); |
||
295 | |||
296 | $auxList = null; |
||
297 | $n = 0; |
||
298 | |||
299 | for ($i = 0; $i < $this->context->countPrims; $i++) { |
||
300 | $preImage = $this->context->prims[$i]; |
||
301 | if ($preImage->length < 2) { |
||
302 | continue; |
||
303 | } |
||
304 | $p = new Auxiliary(); |
||
305 | $this->bestCovering($p, $preImage); |
||
306 | if ($p->gain < 1) { |
||
307 | continue; |
||
308 | } |
||
309 | $p->preImage = $preImage; |
||
310 | $p->next = $auxList; |
||
311 | $auxList = $p; |
||
312 | $n++; |
||
313 | } |
||
314 | |||
315 | if ($this->context->debug) { |
||
316 | $this->context->debug("\nNumber of prims: {$this->context->countPrims}\n"); |
||
317 | $this->context->debug("\nCandidates of aux table:\n"); |
||
318 | for ($p = $auxList; $p !== null; $p = $p->next) { |
||
319 | $this->context->debug(\sprintf('Aux = (%d) ', $p->gain)); |
||
320 | $f = 0; |
||
321 | View Code Duplication | for ($j = 0; $j < $this->context->countTerminals; $j++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
322 | if (self::VACANT !== $p->table[$j]) { |
||
323 | $this->context->debug(\sprintf($f++ ? ',%d' : '%d', $p->table[$j])); |
||
324 | } |
||
325 | } |
||
326 | $this->context->debug(' * '); |
||
327 | for ($j = 0; $j < $p->preImage->length; $j++) { |
||
328 | $this->context->debug(\sprintf($j ? ',%d' : '%d', $p->preImage->classes[$j])); |
||
329 | } |
||
330 | $this->context->debug("\n"); |
||
331 | } |
||
332 | $this->context->debug("Used aux table:\n"); |
||
333 | } |
||
334 | $this->context->countAux = $this->context->countClasses; |
||
335 | for (; ;) { |
||
336 | $maxGain = 0; |
||
337 | $maxAux = null; |
||
338 | $pre = null; |
||
339 | $maxPreImage = null; |
||
340 | for ($p = $auxList; $p != null; $p = $p->next) { |
||
341 | if ($p->gain > $maxGain) { |
||
342 | $maxGain = $p->gain; |
||
343 | $maxAux = $p; |
||
344 | $maxPreImage = $pre; |
||
345 | } |
||
346 | /** @var Auxiliary $pre */ |
||
347 | $pre = $p; |
||
348 | } |
||
349 | |||
350 | if ($maxAux === null) { |
||
351 | break; |
||
352 | } |
||
353 | |||
354 | if ($maxPreImage) { |
||
355 | $maxPreImage->next = $maxAux->next; |
||
356 | } else { |
||
357 | $auxList = $maxAux->next; |
||
358 | } |
||
359 | |||
360 | $maxAux->index = $this->context->countAux; |
||
361 | |||
362 | View Code Duplication | for ($j = 0; $j < $maxAux->preImage->length; $j++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
363 | $cl = $maxAux->preImage->classes[$j]; |
||
364 | if (Utils::eqRow($this->context->classAction[$cl], $maxAux->table, $this->context->countTerminals)) { |
||
365 | $maxAux->index = $cl; |
||
366 | } |
||
367 | } |
||
368 | |||
369 | if ($maxAux->index >= $this->context->countAux) { |
||
370 | $this->context->classAction[$this->context->countAux++] = $maxAux->table; |
||
371 | } |
||
372 | |||
373 | View Code Duplication | for ($j = 0; $j < $maxAux->preImage->length; $j++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
374 | $cl = $maxAux->preImage->classes[$j]; |
||
375 | if ($this->context->class2nd[$cl] < 0) { |
||
376 | $this->context->class2nd[$cl] = $maxAux->index; |
||
377 | } |
||
378 | } |
||
379 | |||
380 | if ($this->context->debug) { |
||
381 | $this->context->debug(\sprintf('Selected aux[%d]: (%d) ', $maxAux->index, $maxAux->gain)); |
||
382 | $f = 0; |
||
383 | View Code Duplication | for ($j = 0; $j < $this->context->countTerminals; $j++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
384 | if (self::VACANT !== $maxAux->table[$j]) { |
||
385 | $this->context->debug(\sprintf($f++ ? ',%d' : '%d', $maxAux->table[$j])); |
||
386 | } |
||
387 | } |
||
388 | $this->context->debug(' * '); |
||
389 | $f = 0; |
||
390 | for ($j = 0; $j < $maxAux->preImage->length; $j++) { |
||
391 | $cl = $maxAux->preImage->classes[$j]; |
||
392 | if ($this->context->class2nd[$cl] === $maxAux->index) { |
||
393 | $this->context->debug(\sprintf($f++ ? ',%d' : '%d', $cl)); |
||
394 | } |
||
395 | } |
||
396 | $this->context->debug("\n"); |
||
397 | } |
||
398 | |||
399 | for ($p = $auxList; $p != null; $p = $p->next) { |
||
400 | $this->bestCovering($p, $p->preImage); |
||
401 | } |
||
402 | } |
||
403 | |||
404 | if ($this->context->debug) { |
||
405 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
406 | if ($this->context->class2nd[$this->context->classOf[$i]] >= 0 && $this->context->class2nd[$this->context->classOf[$i]] !== $this->context->classOf[$i]) { |
||
407 | $this->context->debug(\sprintf("state %d (class %d): aux[%d]\n", $i, $this->context->classOf[$i], $this->context->class2nd[$this->context->classOf[$i]])); |
||
408 | } else { |
||
409 | $this->context->debug(\sprintf("state %d (class %d)\n", $i, $this->context->classOf[$i])); |
||
410 | } |
||
411 | } |
||
412 | } |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * @param Auxiliary $aux |
||
417 | * @param PreImage $prim |
||
418 | */ |
||
419 | private function bestCovering(Auxiliary $aux, PreImage $prim) |
||
420 | { |
||
421 | $this->resetFrequency(); |
||
422 | $gain = 0; |
||
423 | for ($i = 0; $i < $this->context->countTerminals; $i++) { |
||
424 | $max = 0; |
||
425 | $maxAction = -1; |
||
426 | $countVacant = 0; |
||
427 | |||
428 | for ($j = 0; $j < $prim->length; $j++) { |
||
429 | if ($this->context->class2nd[$prim->classes[$j]] < 0) { |
||
430 | $c = $this->context->classAction[$prim->classes[$j]][$i]; |
||
431 | if ($c > 0 && ++$this->context->frequency[$c] > $max) { |
||
432 | $maxAction = $c; |
||
433 | $max = $this->context->frequency[$c]; |
||
434 | } elseif (self::VACANT === $c) { |
||
435 | $countVacant++; |
||
436 | } |
||
437 | } |
||
438 | } |
||
439 | |||
440 | $n = $max - 1 - $countVacant; |
||
441 | |||
442 | if ($n > 0) { |
||
443 | $aux->table[$i] = $maxAction; |
||
444 | $gain += $n; |
||
445 | } else { |
||
446 | $aux->table[$i] = self::VACANT; |
||
447 | } |
||
448 | } |
||
449 | $aux->gain = $gain; |
||
0 ignored issues
–
show
It seems like
$gain can also be of type double . However, the property $gain is declared as type integer . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||
450 | } |
||
451 | |||
452 | /** |
||
453 | * @return void |
||
454 | */ |
||
455 | private function authodoxTable() |
||
456 | { |
||
457 | // TODO |
||
458 | $this->context->cTermIndex = \array_fill(0, $this->context->countTerminals, -1); |
||
459 | $this->context->oTermIndex = \array_fill(0, $this->context->countTerminals, 0); |
||
460 | |||
461 | $countCTerms = 0; |
||
462 | for ($j = 0; $j < $this->context->countTerminals; $j++) { |
||
463 | if ($j === $this->context->errorToken->code) { |
||
464 | $this->context->cTermIndex[$j] = $countCTerms; |
||
465 | $this->context->oTermIndex[$countCTerms++] = $j; |
||
466 | continue; |
||
467 | } |
||
468 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
469 | if ($this->context->termAction[$i][$j] !== self::VACANT) { |
||
470 | $this->context->cTermIndex[$j] = $countCTerms; |
||
471 | $this->context->oTermIndex[$countCTerms++] = $j; |
||
472 | break; |
||
473 | } |
||
474 | } |
||
475 | } |
||
476 | |||
477 | $cTermAction = \array_fill( |
||
478 | 0, $this->context->countAux, \array_fill(0, $countCTerms, 0) |
||
479 | ); |
||
480 | |||
481 | View Code Duplication | for ($i = 0; $i < $this->context->countClasses; $i++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
482 | for ($j = 0; $j < $countCTerms; $j++) { |
||
483 | $cTermAction[$i][$j] = $this->context->classAction[$i][$this->context->oTermIndex[$j]]; |
||
484 | } |
||
485 | } |
||
486 | |||
487 | //582 |
||
488 | |||
489 | for ($i = 0; $i < $this->context->countClasses; $i++) { |
||
490 | if ($this->context->class2nd[$i] >= 0 && $this->context->class2nd[$i] != $i) { |
||
491 | $table = $this->context->classAction[$this->context->class2nd[$i]]; |
||
492 | for ($j = 0; $j < $countCTerms; $j++) { |
||
493 | if (self::VACANT !== $table[$this->context->oTermIndex[$j]]) { |
||
494 | if ($cTermAction[$i][$j] === $table[$this->context->oTermIndex[$j]]) { |
||
495 | $cTermAction[$i][$j] = self::VACANT; |
||
496 | } elseif ($cTermAction[$i][$j] === self::VACANT) { |
||
497 | $cTermAction[$i][$j] = self::DEFAULT; |
||
498 | } |
||
499 | } |
||
500 | } |
||
501 | } |
||
502 | } |
||
503 | |||
504 | View Code Duplication | for ($i = $this->context->countClasses; $i < $this->context->countAux; $i++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
505 | for ($j = 0; $j < $countCTerms; $j++) { |
||
506 | $cTermAction[$i][$j] = $this->context->classAction[$i][$this->context->oTermIndex[$j]]; |
||
507 | } |
||
508 | } |
||
509 | $base = []; |
||
510 | $this->packTable( |
||
511 | $cTermAction, $this->context->countAux, $countCTerms, false, false, |
||
512 | $this->result->yyaction, $this->result->yycheck, $base |
||
513 | ); |
||
514 | $this->result->yydefault = $this->context->defaultAct; |
||
515 | |||
516 | $this->result->yybase = \array_fill(0, $this->context->countNonLeafStates * 2, 0); |
||
517 | $this->result->yybasesize = $this->context->countNonLeafStates; |
||
518 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
519 | $cl = $this->context->classOf[$i]; |
||
520 | $this->result->yybase[$i] = $base[$cl]; |
||
521 | if ($this->context->class2nd[$cl] >= 0 && $this->context->class2nd[$cl] != $cl) { |
||
522 | $this->result->yybase[$i + $this->context->countNonLeafStates] = $base[$this->context->class2nd[$cl]]; |
||
523 | if ($i + $this->context->countNonLeafStates + 1 > $this->result->yybasesize) { |
||
524 | $this->result->yybasesize = $i + $this->context->countNonLeafStates + 1; |
||
525 | } |
||
526 | } |
||
527 | } |
||
528 | |||
529 | $this->result->yybase = \array_slice($this->result->yybase, 0, $this->result->yybasesize); |
||
530 | |||
531 | //642 |
||
532 | $nonTermTransposed = \array_fill(0, $this->context->countNonTerminals, array_fill(0, $this->context->countNonLeafStates, 0)); |
||
533 | foreach ($nonTermTransposed as $j => $_dump) { |
||
534 | for ($i = 0; $i < $this->context->countNonLeafStates; $i++) { |
||
535 | $nonTermTransposed[$j][$i] = $this->context->nonTermGoto[$i][$j]; |
||
536 | if ($this->context->nonTermGoto[$i][$j] === $this->context->defaultGoto[$j]) { |
||
537 | $nonTermTransposed[$j][$i] = self::VACANT; |
||
538 | } |
||
539 | } |
||
540 | } |
||
541 | |||
542 | $this->packTable( |
||
543 | $nonTermTransposed, $this->context->countNonTerminals, $this->context->countNonLeafStates, |
||
544 | false, true, $this->result->yygoto, $this->result->yygcheck, $this->result->yygbase |
||
545 | ); |
||
546 | |||
547 | $this->result->yygdefault = $this->context->defaultGoto; |
||
548 | |||
549 | $this->result->yylhs = []; |
||
550 | $this->result->yylen = []; |
||
551 | foreach ($this->context->grams as $gram) { |
||
552 | $this->result->yylhs[] = $this->nb($gram->body[0]); |
||
553 | $this->result->yylen[] = \count($gram->body) - 1; |
||
554 | } |
||
555 | |||
556 | $this->result->yytranslatesize = 0; |
||
557 | |||
558 | foreach ($this->context->terminals as $term) { |
||
559 | $value = $term->value; |
||
560 | if ($value + 1 > $this->result->yytranslatesize) { |
||
561 | $this->result->yytranslatesize = $value + 1; |
||
562 | } |
||
563 | } |
||
564 | |||
565 | $this->result->yytranslate = \array_fill(0, $this->result->yytranslatesize, $countCTerms); |
||
566 | $this->result->yyncterms = $countCTerms; |
||
567 | |||
568 | for ($i = 0; $i < $this->context->countTerminals; $i++) { |
||
569 | if ($this->context->cTermIndex[$i] >= 0) { |
||
570 | $symbol = $this->context->symbol($i); |
||
571 | $this->result->yytranslate[$symbol->value] = $this->context->cTermIndex[$i]; |
||
572 | } |
||
573 | } |
||
574 | |||
575 | $this->result->yyaction = $this->encodeShiftReduce($this->result->yyaction, \count($this->result->yyaction)); |
||
576 | $this->result->yygoto = $this->encodeShiftReduce($this->result->yygoto, \count($this->result->yygoto)); |
||
577 | $this->result->yygdefault = $this->encodeShiftReduce($this->result->yygdefault, $this->context->countNonTerminals); |
||
578 | } |
||
579 | |||
580 | /** |
||
581 | * @param array $transit |
||
582 | * @param int $nrows |
||
583 | * @param int $ncols |
||
584 | * @param bool $dontcare |
||
585 | * @param bool $checkrow |
||
586 | * @param array $outtable |
||
587 | * @param array $outcheck |
||
588 | * @param array $outbase |
||
589 | */ |
||
590 | private function packTable(array $transit, int $nrows, int $ncols, bool $dontcare, bool $checkrow, array &$outtable, array &$outcheck, array &$outbase) |
||
591 | { |
||
592 | $trow = []; |
||
593 | for ($i = 0; $i < $nrows; $i++) { |
||
594 | $trow[] = $p = new TRow($i); |
||
595 | for ($j = 0; $j < $ncols; $j++) { |
||
596 | if (self::VACANT !== $transit[$i][$j]) { |
||
597 | if ($p->mini < 0) { |
||
598 | $p->mini = $j; |
||
599 | } |
||
600 | $p->maxi = $j + 1; |
||
601 | $p->nent++; |
||
602 | } |
||
603 | } |
||
604 | if ($p->mini < 0) { |
||
605 | $p->mini = 0; |
||
606 | } |
||
607 | } |
||
608 | |||
609 | Utils::stableSort($trow, [TRow::class, 'compare']); |
||
610 | |||
611 | if ($this->context->debug) { |
||
612 | $this->context->debug("Order:\n"); |
||
613 | for ($i = 0; $i < $nrows; $i++) { |
||
614 | $this->context->debug(sprintf('%d,', $trow[$i]->index)); |
||
615 | } |
||
616 | $this->context->debug("\n"); |
||
617 | } |
||
618 | |||
619 | $poolsize = $nrows * $ncols; |
||
620 | $actpool = \array_fill(0, $poolsize, 0); |
||
621 | $check = \array_fill(0, $poolsize, -1); |
||
622 | $base = \array_fill(0, $nrows, 0); |
||
623 | $handledBases = []; |
||
624 | $actpoolmax = 0; |
||
625 | |||
626 | for ($ii = 0; $ii < $nrows; $ii++) { |
||
627 | $i = $trow[$ii]->index; |
||
628 | if (Utils::vacantRow($transit[$i], $ncols)) { |
||
629 | $base[$i] = 0; |
||
630 | goto ok; |
||
631 | } |
||
632 | for ($h = 0; $h < $ii; $h++) { |
||
633 | if (Utils::eqRow($transit[$trow[$h]->index], $transit[$i], $ncols)) { |
||
634 | $base[$i] = $base[$trow[$h]->index]; |
||
635 | goto ok; |
||
636 | } |
||
637 | } |
||
638 | for ($j = 0; $j < $poolsize; $j++) { |
||
639 | $jj = $j; |
||
640 | $base[$i] = $j - $trow[$ii]->mini; |
||
641 | if (!$dontcare) { |
||
642 | if ($base[$i] === 0) { |
||
643 | continue; |
||
644 | } |
||
645 | if (isset($handledBases[$base[$i]])) { |
||
646 | continue; |
||
647 | } |
||
648 | } |
||
649 | |||
650 | for ($k = $trow[$ii]->mini; $k < $trow[$ii]->maxi; $k++) { |
||
651 | if (self::VACANT !== $transit[$i][$k]) { |
||
652 | if ($jj >= $poolsize) { |
||
653 | die("Can't happen"); |
||
654 | } |
||
655 | if ($check[$jj] >= 0 && !($dontcare && $actpool[$jj] === $transit[$i][$k])) { |
||
656 | goto next; |
||
657 | } |
||
658 | } |
||
659 | $jj++; |
||
660 | } |
||
661 | break; |
||
662 | next:; |
||
663 | } |
||
664 | |||
665 | $handledBases[$base[$i]] = true; |
||
666 | $jj = $j; |
||
667 | for ($k = $trow[$ii]->mini; $k < $trow[$ii]->maxi; $k++) { |
||
668 | if (self::VACANT !== $transit[$i][$k]) { |
||
669 | $actpool[$jj] = $transit[$i][$k]; |
||
670 | $check[$jj] = $checkrow ? $i : $k; |
||
671 | } |
||
672 | $jj++; |
||
673 | } |
||
674 | if ($jj >= $actpoolmax) { |
||
675 | $actpoolmax = $jj; |
||
676 | } |
||
677 | ok:; |
||
678 | } |
||
679 | |||
680 | $outtable = \array_slice($actpool, 0, $actpoolmax); |
||
681 | $outcheck = \array_slice($check, 0, $actpoolmax); |
||
682 | $outbase = $base; |
||
683 | } |
||
684 | |||
685 | /** |
||
686 | * @param int $code |
||
687 | * |
||
688 | * @return int |
||
689 | */ |
||
690 | public function encodeRederr(int $code): int |
||
691 | { |
||
692 | return $code < 0 ? self::UNEXPECTED : $code; |
||
693 | } |
||
694 | |||
695 | /** |
||
696 | * @return void |
||
697 | */ |
||
698 | public function resetFrequency() |
||
699 | { |
||
700 | $this->context->frequency = \array_fill(0, $this->context->countStates, 0); |
||
701 | } |
||
702 | |||
703 | /** |
||
704 | * @param int $x |
||
705 | * @param int $y |
||
706 | * |
||
707 | * @return int |
||
708 | */ |
||
709 | public function cmpStates(int $x, int $y): int |
||
710 | { |
||
711 | for ($i = 0; $i < $this->context->countTerminals; $i++) { |
||
712 | if ($this->context->termAction[$x][$i] != $this->context->termAction[$y][$i]) { |
||
713 | return $this->context->termAction[$x][$i] - $this->context->termAction[$y][$i]; |
||
714 | } |
||
715 | } |
||
716 | |||
717 | return 0; |
||
718 | } |
||
719 | |||
720 | /** |
||
721 | * @param Symbol $symbol |
||
722 | * |
||
723 | * @return int |
||
724 | */ |
||
725 | private function nb(Symbol $symbol) |
||
726 | { |
||
727 | if ($symbol->isTerminal) { |
||
728 | return $symbol->code; |
||
729 | } else { |
||
730 | return $symbol->code - $this->context->countTerminals; |
||
731 | } |
||
732 | } |
||
733 | } |
||
734 |