xref: /template/strap/vendor/antlr/antlr4-php-runtime/src/VocabularyImpl.php (revision 37748cd8654635afbeca80942126742f0f4cc346)
1*37748cd8SNickeau<?php
2*37748cd8SNickeau
3*37748cd8SNickeaudeclare(strict_types=1);
4*37748cd8SNickeau
5*37748cd8SNickeaunamespace Antlr\Antlr4\Runtime;
6*37748cd8SNickeau
7*37748cd8SNickeau/**
8*37748cd8SNickeau * This class provides a default implementation of the {@see Vocabulary}
9*37748cd8SNickeau * interface.
10*37748cd8SNickeau *
11*37748cd8SNickeau * @author Sam Harwell
12*37748cd8SNickeau */
13*37748cd8SNickeaufinal class VocabularyImpl implements Vocabulary
14*37748cd8SNickeau{
15*37748cd8SNickeau    /** @var array<string|null> */
16*37748cd8SNickeau    private $literalNames;
17*37748cd8SNickeau
18*37748cd8SNickeau    /** @var array<string|null> */
19*37748cd8SNickeau    private $symbolicNames;
20*37748cd8SNickeau
21*37748cd8SNickeau    /** @var array<string|null> */
22*37748cd8SNickeau    private $displayNames;
23*37748cd8SNickeau
24*37748cd8SNickeau    /** @var int */
25*37748cd8SNickeau    private $maxTokenType;
26*37748cd8SNickeau
27*37748cd8SNickeau    /**
28*37748cd8SNickeau     * Constructs a new instance from the specified literal, symbolic
29*37748cd8SNickeau     * and display token names.
30*37748cd8SNickeau     *
31*37748cd8SNickeau     * @param array<string|null> $literalNames  The literal names assigned
32*37748cd8SNickeau     *                                          to tokens, or `null` if no
33*37748cd8SNickeau     *                                          literal names are assigned.
34*37748cd8SNickeau     * @param array<string|null> $symbolicNames The symbolic names assigned
35*37748cd8SNickeau     *                                          to tokens, or `null` if
36*37748cd8SNickeau     *                                          no symbolic names are assigned.
37*37748cd8SNickeau     * @param array<string|null> $displayNames  The display names assigned
38*37748cd8SNickeau     *                                          to tokens, or `null` to use
39*37748cd8SNickeau     *                                          the values in literalNames` and
40*37748cd8SNickeau     *                                          `symbolicNames` as the source
41*37748cd8SNickeau     *                                          of display names, as described
42*37748cd8SNickeau     *                                          in {@see VocabularyImpl::getDisplayName()}.
43*37748cd8SNickeau     */
44*37748cd8SNickeau    public function __construct(array $literalNames = [], array $symbolicNames = [], array $displayNames = [])
45*37748cd8SNickeau    {
46*37748cd8SNickeau        $this->literalNames = $literalNames;
47*37748cd8SNickeau        $this->symbolicNames = $symbolicNames;
48*37748cd8SNickeau        $this->displayNames = $displayNames;
49*37748cd8SNickeau
50*37748cd8SNickeau        // See note here on -1 part: https://github.com/antlr/antlr4/pull/1146
51*37748cd8SNickeau        $this->maxTokenType = \max(
52*37748cd8SNickeau            \count($this->displayNames),
53*37748cd8SNickeau            \count($this->literalNames),
54*37748cd8SNickeau            \count($this->symbolicNames)
55*37748cd8SNickeau        ) - 1;
56*37748cd8SNickeau    }
57*37748cd8SNickeau
58*37748cd8SNickeau    /**
59*37748cd8SNickeau     * Gets an empty {@see Vocabulary} instance.
60*37748cd8SNickeau     *
61*37748cd8SNickeau     * No literal or symbol names are assigned to token types, so
62*37748cd8SNickeau     * {@see Vocabulary::getDisplayName()} returns the numeric value for
63*37748cd8SNickeau     * all tokens except {@see Token::EOF}.
64*37748cd8SNickeau     */
65*37748cd8SNickeau    public static function emptyVocabulary() : self
66*37748cd8SNickeau    {
67*37748cd8SNickeau        static $empty;
68*37748cd8SNickeau
69*37748cd8SNickeau        return $empty ?? ($empty = new self());
70*37748cd8SNickeau    }
71*37748cd8SNickeau
72*37748cd8SNickeau    /**
73*37748cd8SNickeau     * Returns a {@see VocabularyImpl} instance from the specified set
74*37748cd8SNickeau     * of token names. This method acts as a compatibility layer for the single
75*37748cd8SNickeau     * `tokenNames` array generated by previous releases of ANTLR.
76*37748cd8SNickeau     *
77*37748cd8SNickeau     * The resulting vocabulary instance returns `null` for
78*37748cd8SNickeau     * {@see VocabularyImpl::getLiteralName()} and {@see VocabularyImpl::getSymbolicName()},
79*37748cd8SNickeau     * and the value from `tokenNames` for the display names.
80*37748cd8SNickeau     *
81*37748cd8SNickeau     * @param array<string|null> $tokenNames The token names, or `null` if
82*37748cd8SNickeau     *                                       no token names are available.
83*37748cd8SNickeau     *
84*37748cd8SNickeau     * @return Vocabulary A {@see Vocabulary} instance which uses `tokenNames`
85*37748cd8SNickeau     *                    for the display names of tokens.
86*37748cd8SNickeau     */
87*37748cd8SNickeau    public static function fromTokenNames(array $tokenNames = []) : Vocabulary
88*37748cd8SNickeau    {
89*37748cd8SNickeau        if (\count($tokenNames) === 0) {
90*37748cd8SNickeau            return self::emptyVocabulary();
91*37748cd8SNickeau        }
92*37748cd8SNickeau
93*37748cd8SNickeau        $literalNames = $tokenNames; // copy array
94*37748cd8SNickeau        $symbolicNames = $tokenNames; // copy array
95*37748cd8SNickeau
96*37748cd8SNickeau        foreach ($tokenNames as $i => $tokenName) {
97*37748cd8SNickeau            if ($tokenName === null) {
98*37748cd8SNickeau                continue;
99*37748cd8SNickeau            }
100*37748cd8SNickeau
101*37748cd8SNickeau            if ($tokenName !== '') {
102*37748cd8SNickeau                $firstChar = $tokenName[0];
103*37748cd8SNickeau
104*37748cd8SNickeau                if ($firstChar === '\'') {
105*37748cd8SNickeau                    $symbolicNames[$i] = null;
106*37748cd8SNickeau
107*37748cd8SNickeau                    continue;
108*37748cd8SNickeau                }
109*37748cd8SNickeau
110*37748cd8SNickeau                if (\ctype_upper($firstChar)) {
111*37748cd8SNickeau                    $literalNames[$i] = null;
112*37748cd8SNickeau
113*37748cd8SNickeau                    continue;
114*37748cd8SNickeau                }
115*37748cd8SNickeau            }
116*37748cd8SNickeau
117*37748cd8SNickeau            // wasn't a literal or symbolic name
118*37748cd8SNickeau            $literalNames[$i] = null;
119*37748cd8SNickeau            $symbolicNames[$i] = null;
120*37748cd8SNickeau        }
121*37748cd8SNickeau
122*37748cd8SNickeau        return new VocabularyImpl($literalNames, $symbolicNames, $tokenNames);
123*37748cd8SNickeau    }
124*37748cd8SNickeau
125*37748cd8SNickeau    public function getMaxTokenType() : int
126*37748cd8SNickeau    {
127*37748cd8SNickeau        return $this->maxTokenType;
128*37748cd8SNickeau    }
129*37748cd8SNickeau
130*37748cd8SNickeau    public function getLiteralName(int $tokenType) : ?string
131*37748cd8SNickeau    {
132*37748cd8SNickeau        if ($tokenType >= 0 && $tokenType < \count($this->literalNames)) {
133*37748cd8SNickeau            return $this->literalNames[$tokenType];
134*37748cd8SNickeau        }
135*37748cd8SNickeau
136*37748cd8SNickeau        return null;
137*37748cd8SNickeau    }
138*37748cd8SNickeau
139*37748cd8SNickeau    public function getSymbolicName(int $tokenType) : ?string
140*37748cd8SNickeau    {
141*37748cd8SNickeau        if ($tokenType >= 0 && $tokenType < \count($this->symbolicNames)) {
142*37748cd8SNickeau            return $this->symbolicNames[$tokenType];
143*37748cd8SNickeau        }
144*37748cd8SNickeau
145*37748cd8SNickeau        if ($tokenType === Token::EOF) {
146*37748cd8SNickeau            return 'EOF';
147*37748cd8SNickeau        }
148*37748cd8SNickeau
149*37748cd8SNickeau        return null;
150*37748cd8SNickeau    }
151*37748cd8SNickeau
152*37748cd8SNickeau    public function getDisplayName(int $tokenType) : string
153*37748cd8SNickeau    {
154*37748cd8SNickeau        if ($tokenType >= 0 && $tokenType < \count($this->displayNames)) {
155*37748cd8SNickeau            $displayName = $this->displayNames[$tokenType];
156*37748cd8SNickeau
157*37748cd8SNickeau            if ($displayName !== null) {
158*37748cd8SNickeau                return $displayName;
159*37748cd8SNickeau            }
160*37748cd8SNickeau        }
161*37748cd8SNickeau
162*37748cd8SNickeau        $literalName = $this->getLiteralName($tokenType);
163*37748cd8SNickeau
164*37748cd8SNickeau        if ($literalName !== null) {
165*37748cd8SNickeau            return $literalName;
166*37748cd8SNickeau        }
167*37748cd8SNickeau
168*37748cd8SNickeau        $symbolicName = $this->getSymbolicName($tokenType);
169*37748cd8SNickeau
170*37748cd8SNickeau        if ($symbolicName !== null) {
171*37748cd8SNickeau            return $symbolicName;
172*37748cd8SNickeau        }
173*37748cd8SNickeau
174*37748cd8SNickeau        return (string) $tokenType;
175*37748cd8SNickeau    }
176*37748cd8SNickeau}
177