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