1<?php
2
3declare(strict_types=1);
4
5namespace Antlr\Antlr4\Runtime;
6
7use Antlr\Antlr4\Runtime\Utils\Pair;
8
9/**
10 * This default implementation of {@see TokenFactory} creates
11 * {@see CommonToken} objects.
12 */
13final class CommonTokenFactory implements TokenFactory
14{
15    /**
16     * Indicates whether {@see CommonToken::setText()} should be called after
17     * constructing tokens to explicitly set the text. This is useful for cases
18     * where the input stream might not be able to provide arbitrary substrings
19     * of text from the input after the lexer creates a token (e.g. the
20     * implementation of {@see CharStream::getText()} in
21     * {@see UnbufferedCharStream} throws an
22     * {@see UnsupportedOperationException}). Explicitly setting the token text
23     * allows {@see Token::getText()} to be called at any time regardless of the
24     * input stream implementation.
25     *
26     * The default value is `false` to avoid the performance and memory
27     * overhead of copying text for every token unless explicitly requested.
28     *
29     * @var bool
30     */
31    protected $copyText;
32
33    /**
34     * Constructs a {@see CommonTokenFactory} with the specified value for
35     * {@see CommonTokenFactory::copyText()}.
36     *
37     * When `copyText` is `false`, the {@see CommonTokenFactory::DEFAULT}
38     * instance should be used instead of constructing a new instance.
39     *
40     * @param bool $copyText The value for {@see CommonTokenFactory::copyText()}.
41     */
42    public function __construct(bool $copyText = false)
43    {
44        $this->copyText = $copyText;
45    }
46
47    /**
48     * The default {@see CommonTokenFactory} instance.
49     *
50     * This token factory does not explicitly copy token text when constructing
51     * tokens.
52     */
53    public static function default() : self
54    {
55        static $default;
56
57        return $default = $default ?? new CommonTokenFactory();
58    }
59
60    public function createEx(
61        Pair $source,
62        int $type,
63        ?string $text,
64        int $channel,
65        int $start,
66        int $stop,
67        int $line,
68        int $column
69    ) : Token {
70        $token = new CommonToken($type, $source, $channel, $start, $stop);
71
72        $token->setLine($line);
73        $token->setCharPositionInLine($column);
74
75        if ($text !== null) {
76            $token->setText($text);
77        } elseif ($this->copyText && $source->b !== null) {
78            if (!$source->b instanceof CharStream) {
79                throw new \RuntimeException('Unexpected stream type.');
80            }
81
82            $token->setText($source->b->getText($start, $stop));
83        }
84
85        return $token;
86    }
87
88    public function create(int $type, string $text) : Token
89    {
90        $token = new CommonToken($type);
91
92        $token->setText($text);
93
94        return $token;
95    }
96}
97