packages/sql-faker/tests/Unit/Compiler/Lemon/LemonRulesTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Compiler\Lemon;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Compiler\Lemon\LemonRules;
11use SqlFaker\Compiler\Lemon\LemonSymbols;
12use SqlFaker\Compiler\Lemon\LemonText;
13
14#[CoversClass(LemonRules::class)]
15#[UsesClass(LemonSymbols::class)]
16#[UsesClass(LemonText::class)]
17final class LemonRulesTest extends TestCase
18{
19    public function testReadFromGathersTheAlternativesOfOneRuleWrittenOnSeveralLines(): void
20    {
21        self::assertSame(
22            ['cmd' => [['SELECT'], ['INSERT']]],
23            (new LemonRules())->readFrom("cmd ::= SELECT.\ncmd ::= INSERT.\n", new LemonSymbols()),
24        );
25    }
26
27    public function testReadFromReadsARuleThatWritesNothing(): void
28    {
29        self::assertSame(['opt' => [[]]], (new LemonRules())->readFrom("opt ::= .\n", new LemonSymbols()));
30    }
31
32    public function testReadFromDropsTheAliasASymbolCarries(): void
33    {
34        self::assertSame(
35            ['cmd' => [['expr']]],
36            (new LemonRules())->readFrom("cmd(A) ::= expr(X).\n", new LemonSymbols()),
37        );
38    }
39
40    public function testReadFromTellsTheSymbolTableWhatEachNameTurnedOutToBe(): void
41    {
42        $symbols = new LemonSymbols();
43        (new LemonRules())->readFrom("cmd ::= SELECT expr.\n", $symbols);
44
45        self::assertTrue($symbols->isTerminal('SELECT'));
46        self::assertFalse($symbols->isTerminal('cmd'));
47    }
48
49    public function testAlternativesMultipliesOutEachAlternationPosition(): void
50    {
51        self::assertSame(
52            [['A', 'C'], ['A', 'D'], ['B', 'C'], ['B', 'D']],
53            (new LemonRules())->alternatives('A|B C|D', new LemonSymbols()),
54        );
55    }
56
57    public function testAlternativesIgnoresAPositionThatConfiguresTheParser(): void
58    {
59        self::assertSame([['expr']], (new LemonRules())->alternatives('expr %prec', new LemonSymbols()));
60    }
61
62    public function testWithoutAliasDropsWhatTheParserNamesTheValue(): void
63    {
64        self::assertSame('expr', (new LemonRules())->withoutAlias('expr(A)'));
65    }
66
67    public function testWithoutAliasLeavesASymbolWithNoAliasAlone(): void
68    {
69        self::assertSame('expr', (new LemonRules())->withoutAlias('expr'));
70    }
71}
72