packages/sql-parser/tests/Unit/Automaton/NullableSetTest.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\NullableSet;
12use SqlParser\Grammar\Grammar;
13use SqlParser\Grammar\GrammarBuilder;
14use SqlParser\Grammar\Rule;
15use SqlParser\Grammar\SymbolTable;
16
17#[CoversClass(NullableSet::class)]
18#[UsesClass(Grammar::class)]
19#[UsesClass(GrammarBuilder::class)]
20#[UsesClass(Rule::class)]
21#[UsesClass(SymbolTable::class)]
22#[Small]
23final class NullableSetTest extends TestCase
24{
25 public function testIsNullable(): void
26 {
27 $builder = new GrammarBuilder();
28 $builder->terminal('A');
29 $builder->rule('s', ['opt', 'A']);
30 $builder->rule('opt', ['pair']);
31 $builder->rule('opt', ['A']);
32 $builder->rule('pair', ['empty', 'empty']);
33 $builder->rule('empty', []);
34 $grammar = $builder->build();
35 $nullable = new NullableSet($grammar);
36
37 self::assertTrue($nullable->isNullable($grammar->symbols->id('empty') ?? -1));
38 self::assertTrue($nullable->isNullable($grammar->symbols->id('pair') ?? -1));
39 self::assertTrue($nullable->isNullable($grammar->symbols->id('opt') ?? -1));
40 self::assertFalse($nullable->isNullable($grammar->symbols->id('s') ?? -1));
41 self::assertFalse($nullable->isNullable($grammar->symbols->id('A') ?? -1));
42 }
43
44 public function testTailNullable(): void
45 {
46 $builder = new GrammarBuilder();
47 $builder->terminal('A');
48 $builder->rule('s', ['A', 'empty', 'empty']);
49 $builder->rule('empty', []);
50 $grammar = $builder->build();
51 $nullable = new NullableSet($grammar);
52 $rhs = $grammar->rules[1]->rhs;
53
54 self::assertFalse($nullable->tailNullable($rhs, 0));
55 self::assertTrue($nullable->tailNullable($rhs, 1));
56 self::assertTrue($nullable->tailNullable($rhs, 3));
57 }
58}
59