packages/lemon-parser/tests/Unit/Ast/RuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Ast;
6
7use LemonParser\Ast\CodeBlock;
8use LemonParser\Ast\Location;
9use LemonParser\Ast\RhsItem;
10use LemonParser\Ast\Rule;
11use LemonParser\Ast\Symbol;
12use PHPUnit\Framework\Attributes\CoversClass;
13use PHPUnit\Framework\Attributes\Small;
14use PHPUnit\Framework\Attributes\UsesClass;
15use PHPUnit\Framework\TestCase;
16
17#[CoversClass(Rule::class)]
18#[UsesClass(CodeBlock::class)]
19#[UsesClass(Location::class)]
20#[UsesClass(RhsItem::class)]
21#[UsesClass(Symbol::class)]
22#[Small]
23final class RuleTest extends TestCase
24{
25 public function testWithPrecedence(): void
26 {
27 $rule = new Rule(new Symbol('expr', new Location(1, 1)), 'A', [], null, null, false, new Location(1, 1));
28
29 $marked = $rule->withPrecedence(new Symbol('PLUS', new Location(1, 20)));
30
31 self::assertSame('PLUS', $marked->precedence?->name);
32 self::assertNull($rule->precedence);
33 self::assertSame(['expr', 'A', '1:1'], [$marked->lhs->name, $marked->lhsAlias, (string) $marked->location]);
34 }
35
36 public function testWithCode(): void
37 {
38 $rule = new Rule(new Symbol('expr', new Location(1, 1)), null, [], null, null, false, new Location(1, 1));
39
40 $withCode = $rule->withCode(new CodeBlock(' x ', new Location(1, 20)));
41
42 self::assertSame(' x ', $withCode->code?->code);
43 self::assertNull($rule->code);
44 }
45
46 public function testWithNeverReduce(): void
47 {
48 $rule = new Rule(new Symbol('expr', new Location(1, 1)), null, [], null, null, false, new Location(1, 1));
49
50 self::assertTrue($rule->withNeverReduce()->neverReduce);
51 self::assertFalse($rule->neverReduce);
52 }
53
54 public function testSymbols(): void
55 {
56 $items = [
57 new RhsItem([new Symbol('expr', new Location(1, 10))], 'B'),
58 new RhsItem([new Symbol('PLUS', new Location(1, 15)), new Symbol('MINUS', new Location(1, 20))], null),
59 new RhsItem([new Symbol('NUM', new Location(1, 26))], 'C'),
60 ];
61 $rule = new Rule(new Symbol('expr', new Location(1, 1)), null, $items, null, null, false, new Location(1, 1));
62
63 self::assertSame(['expr', 'PLUS', 'MINUS', 'NUM'], array_map(static fn (Symbol $symbol): string => $symbol->name, $rule->symbols()));
64 }
65}
66