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