packages/lemon-parser/tests/Unit/Syntax/SymbolRegistryTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Syntax;
6
7use LemonParser\Ast\Location;
8use LemonParser\Syntax\SymbolRegistry;
9use LemonParser\SyntaxException;
10use PHPUnit\Framework\Attributes\CoversClass;
11use PHPUnit\Framework\Attributes\Small;
12use PHPUnit\Framework\Attributes\UsesClass;
13use PHPUnit\Framework\TestCase;
14
15#[CoversClass(SymbolRegistry::class)]
16#[UsesClass(Location::class)]
17#[UsesClass(SyntaxException::class)]
18#[Small]
19final class SymbolRegistryTest extends TestCase
20{
21 public function testSee(): void
22 {
23 $registry = new SymbolRegistry();
24
25 $registry->see('expr');
26
27 self::assertTrue($registry->isKnown('expr'));
28 }
29
30 public function testIsKnown(): void
31 {
32 $registry = new SymbolRegistry();
33
34 self::assertFalse($registry->isKnown('expr'));
35 $registry->rank('PLUS', new Location(1, 1));
36 self::assertTrue($registry->isKnown('PLUS'));
37 }
38
39 public function testRank(): void
40 {
41 $registry = new SymbolRegistry();
42 $registry->rank('PLUS', new Location(1, 7));
43
44 $this->expectException(SyntaxException::class);
45 $this->expectExceptionMessage('Symbol "PLUS" has already be given a precedence. at 2:8');
46
47 $registry->rank('PLUS', new Location(2, 8));
48 }
49
50 public function testType(): void
51 {
52 $registry = new SymbolRegistry();
53 $registry->type('expr', new Location(1, 7));
54
55 self::assertTrue($registry->isKnown('expr'));
56 $this->expectException(SyntaxException::class);
57 $this->expectExceptionMessage('Symbol %type "expr" already defined at 2:7');
58
59 $registry->type('expr', new Location(2, 7));
60 }
61
62 public function testFallBack(): void
63 {
64 $registry = new SymbolRegistry();
65 $registry->fallBack('ABORT', new Location(1, 14));
66
67 self::assertTrue($registry->isKnown('ABORT'));
68 $this->expectException(SyntaxException::class);
69 $this->expectExceptionMessage('More than one fallback assigned to token ABORT at 2:14');
70
71 $registry->fallBack('ABORT', new Location(2, 14));
72 }
73
74 public function testWildcard(): void
75 {
76 $registry = new SymbolRegistry();
77 $registry->wildcard('ANY', new Location(1, 11));
78
79 self::assertTrue($registry->isKnown('ANY'));
80 $this->expectException(SyntaxException::class);
81 $this->expectExceptionMessage('Extra wildcard to token: OTHER at 1:15');
82
83 $registry->wildcard('OTHER', new Location(1, 15));
84 }
85}
86