packages/sql-parser/tests/Unit/Automaton/ClosureIndexTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Automaton;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\Small;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlParser\Automaton\ClosureIndex;
12use SqlParser\Grammar\Grammar;
13use SqlParser\Grammar\GrammarBuilder;
14use SqlParser\Grammar\Rule;
15use SqlParser\Grammar\SymbolTable;
16
17#[CoversClass(ClosureIndex::class)]
18#[UsesClass(Grammar::class)]
19#[UsesClass(GrammarBuilder::class)]
20#[UsesClass(Rule::class)]
21#[UsesClass(SymbolTable::class)]
22#[Small]
23final class ClosureIndexTest extends TestCase
24{
25 public function testReachable(): void
26 {
27 $builder = new GrammarBuilder();
28 $builder->terminal('NUM');
29 $builder->terminal('(');
30 $builder->terminal(')');
31 $builder->rule('expr', ['term']);
32 $builder->rule('term', ['factor']);
33 $builder->rule('factor', ['NUM']);
34 $builder->rule('factor', ['(', 'expr', ')']);
35 $grammar = $builder->build();
36 $index = new ClosureIndex($grammar);
37 $symbols = $grammar->symbols;
38 $reached = $index->reachable($grammar, $symbols->id('expr') ?? -1);
39 sort($reached);
40
41 self::assertSame([$symbols->id('expr'), $symbols->id('term'), $symbols->id('factor')], $reached);
42 self::assertSame([$symbols->id('factor')], $index->reachable($grammar, $symbols->id('factor') ?? -1));
43 }
44
45 public function testStartsWith(): void
46 {
47 $builder = new GrammarBuilder();
48 $builder->terminal('NUM');
49 $builder->terminal('(');
50 $builder->terminal(')');
51 $builder->rule('expr', ['term']);
52 $builder->rule('term', ['NUM']);
53 $builder->rule('term', ['(', 'expr', ')']);
54 $grammar = $builder->build();
55 $index = new ClosureIndex($grammar);
56 $symbols = $grammar->symbols;
57 $width = $index->itemWidth;
58
59 self::assertSame(4, $width);
60 self::assertSame([$symbols->id('term') => [1 * $width + 1], $symbols->id('NUM') => [2 * $width + 1], $symbols->id('(') => [3 * $width + 1]], $index->startsWith($symbols->id('expr') ?? -1));
61 self::assertSame([], $index->startsWith(99));
62 }
63
64 public function testEmptyRules(): void
65 {
66 $builder = new GrammarBuilder();
67 $builder->terminal('A');
68 $builder->rule('s', ['opt', 'A']);
69 $builder->rule('opt', []);
70 $builder->rule('opt', ['A']);
71 $grammar = $builder->build();
72 $index = new ClosureIndex($grammar);
73
74 self::assertSame([2], $index->emptyRules($grammar->symbols->id('s') ?? -1));
75 self::assertSame([2], $index->emptyRules($grammar->symbols->id('opt') ?? -1));
76 self::assertSame([], $index->emptyRules(99));
77 }
78}
79