packages/bison-parser/tests/Unit/Printer/PrinterTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Printer;
6
7use BisonParser\Ast\Declaration\Flag;
8use BisonParser\Ast\Declaration\Start;
9use BisonParser\Ast\Epilogue;
10use BisonParser\Ast\GrammarFile;
11use BisonParser\Ast\Line;
12use BisonParser\Ast\Location;
13use BisonParser\Ast\Rule\Action;
14use BisonParser\Ast\Rule\Alternative;
15use BisonParser\Ast\Rule\Rule;
16use BisonParser\Ast\Rule\SymbolItem;
17use BisonParser\Ast\Symbol;
18use BisonParser\Ast\SymbolKind;
19use BisonParser\Printer\DeclarationPrinter;
20use BisonParser\Printer\Printer;
21use BisonParser\Printer\RhsPrinter;
22use BisonParser\Printer\SymbolPrinter;
23use BisonParser\Scanner\Escapes;
24use PHPUnit\Framework\Attributes\CoversClass;
25use PHPUnit\Framework\Attributes\Small;
26use PHPUnit\Framework\Attributes\UsesClass;
27use PHPUnit\Framework\TestCase;
28
29#[CoversClass(Printer::class)]
30#[UsesClass(Action::class)]
31#[UsesClass(Alternative::class)]
32#[UsesClass(DeclarationPrinter::class)]
33#[UsesClass(Epilogue::class)]
34#[UsesClass(Escapes::class)]
35#[UsesClass(Flag::class)]
36#[UsesClass(GrammarFile::class)]
37#[UsesClass(Line::class)]
38#[UsesClass(Location::class)]
39#[UsesClass(RhsPrinter::class)]
40#[UsesClass(Rule::class)]
41#[UsesClass(Start::class)]
42#[UsesClass(Symbol::class)]
43#[UsesClass(SymbolItem::class)]
44#[UsesClass(SymbolKind::class)]
45#[UsesClass(SymbolPrinter::class)]
46#[Small]
47final class PrinterTest extends TestCase
48{
49    public function testPrint(): void
50    {
51        $at = new Location(1, 1);
52        $expr = new Symbol(SymbolKind::Identifier, 'expr', $at);
53        $rule = new Rule($expr, null, [new Alternative([new SymbolItem($expr, null), new SymbolItem(new Symbol(SymbolKind::CharLiteral, '+', $at), null)], $at), new Alternative([], $at)], $at);
54        $file = new GrammarFile([new Flag('debug', '%debug', $at)], [$rule, new Start([$expr], $at)], new Epilogue("\nint main() {}\n", $at));
55
56        self::assertSame("%debug\n%%\nexpr:\n  expr '+'\n| %empty\n;\n%start expr;\n%%\nint main() {}\n", (new Printer())->print($file));
57        self::assertSame("%%\n", (new Printer())->print(new GrammarFile([], [], null)));
58        self::assertSame("#line 2 \"x.y\"\n%%\n#line 5\n", (new Printer())->print(new GrammarFile([new Line(2, 'x.y', $at)], [new Line(5, null, $at)], null)));
59    }
60
61    public function testRule(): void
62    {
63        $at = new Location(1, 1);
64        $rule = new Rule(new Symbol(SymbolKind::Identifier, 'expr', $at), 'e', [new Alternative([new Action(null, ' a ', null, $at)], $at)], $at);
65
66        self::assertSame("expr[e]:\n  { a }\n;", (new Printer())->rule($rule));
67    }
68
69    public function testAlternative(): void
70    {
71        $at = new Location(1, 1);
72        $printer = new Printer();
73
74        self::assertSame('%empty', $printer->alternative(new Alternative([], $at)));
75        self::assertSame('a { b }', $printer->alternative(new Alternative([new SymbolItem(new Symbol(SymbolKind::Identifier, 'a', $at), null), new Action(null, ' b ', null, $at)], $at)));
76    }
77}
78