packages/bison-parser/src/Printer/SymbolPrinter.php
1<?php
2
3declare(strict_types=1);
4
5namespace BisonParser\Printer;
6
7use BisonParser\Ast\Symbol;
8use BisonParser\Ast\SymbolKind;
9use BisonParser\Ast\Tag;
10use BisonParser\Scanner\Escapes;
11
12/**
13 * Writes symbols, tags and literals the way Bison spells them.
14 *
15 * @visibility root
16 */
17final class SymbolPrinter
18{
19 /**
20 * @param Escapes $escapes Writes the bytes of a literal
21 */
22 public function __construct(private readonly Escapes $escapes = new Escapes())
23 {
24 }
25
26 /**
27 * Writes a symbol.
28 *
29 * @param Symbol $symbol The symbol
30 *
31 * @return string The identifier, or the quoted literal
32 */
33 public function symbol(Symbol $symbol): string
34 {
35 if ($symbol->spelling !== null) {
36 return $symbol->spelling;
37 }
38
39 return match ($symbol->kind) {
40 SymbolKind::Identifier => $symbol->value,
41 SymbolKind::CharLiteral => "'" . $this->escapes->encode($symbol->value, "'") . "'",
42 SymbolKind::String => $this->string($symbol->value),
43 };
44 }
45
46 /**
47 * Writes a string literal.
48 *
49 * @param string $text The decoded text
50 *
51 * @return string The quoted literal
52 */
53 public function string(string $text): string
54 {
55 return '"' . $this->escapes->encode($text, '"') . '"';
56 }
57
58 /**
59 * Writes a tag between angle brackets.
60 *
61 * @param Tag $tag The tag
62 *
63 * @return string The tag as written in a grammar
64 */
65 public function tag(Tag $tag): string
66 {
67 return '<' . $tag->name . '>';
68 }
69
70 /**
71 * Writes braced code.
72 *
73 * @param string $code The code without its braces
74 *
75 * @return string The code between braces
76 */
77 public function code(string $code): string
78 {
79 return '{' . $code . '}';
80 }
81}
82