packages/sql-faker/tests/Unit/Grammar/Model/TerminalInventoryTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Grammar\Model;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Grammar\Model\Grammar;
11use SqlFaker\Grammar\Model\NonTerminal;
12use SqlFaker\Grammar\Model\Production;
13use SqlFaker\Grammar\Model\ProductionRule;
14use SqlFaker\Grammar\Model\Terminal;
15use SqlFaker\Grammar\Model\TerminalInventory;
16
17#[CoversClass(TerminalInventory::class)]
18#[UsesClass(Grammar::class)]
19#[UsesClass(NonTerminal::class)]
20#[UsesClass(Production::class)]
21#[UsesClass(ProductionRule::class)]
22#[UsesClass(Terminal::class)]
23final class TerminalInventoryTest extends TestCase
24{
25    public function testIncludesDeclaredTerminalsAndUnknownLexerSymbols(): void
26    {
27        $grammar = new Grammar('start', [
28            'start' => new ProductionRule('start', [
29                new Production([new Terminal('SELECT'), new NonTerminal('value')]),
30            ]),
31        ]);
32
33        self::assertSame(['SELECT', 'value'], TerminalInventory::fromGrammar($grammar));
34    }
35
36    public function testDeduplicatesAndSortsWithoutIncludingDefinedRules(): void
37    {
38        $grammar = new Grammar('start', [
39            'start' => new ProductionRule('start', [
40                new Production([
41                    new Terminal('Z_TOKEN'),
42                    new NonTerminal('nested'),
43                    new Terminal('A_TOKEN'),
44                    new Terminal('Z_TOKEN'),
45                ]),
46            ]),
47            'nested' => new ProductionRule('nested', [new Production([])]),
48        ]);
49
50        self::assertSame(['A_TOKEN', 'Z_TOKEN'], TerminalInventory::fromGrammar($grammar));
51    }
52
53    public function testFromGrammarNamesEveryTerminalTheRulesReach(): void
54    {
55        $grammar = new Grammar('stmt', [
56            'stmt' => new ProductionRule('stmt', [new Production([new Terminal('SELECT'), new NonTerminal('nm')])]),
57            'nm' => new ProductionRule('nm', [new Production([new Terminal('IDENT')])]),
58        ]);
59
60        self::assertSame(['IDENT', 'SELECT'], TerminalInventory::fromGrammar($grammar));
61    }
62}
63