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