1<?php
2
3declare(strict_types=1);
4
5namespace Antlr\Antlr4\Runtime\PredictionContexts;
6
7use Antlr\Antlr4\Runtime\Comparison\Equality;
8use Antlr\Antlr4\Runtime\Comparison\Hasher;
9
10/**
11 * Used to cache {@see PredictionContext} objects. Its used for
12 * the shared context cash associated with contexts in DFA states.
13 * This cache can be used for both lexers and parsers.
14 */
15class SingletonPredictionContext extends PredictionContext
16{
17    /** @var PredictionContext|null */
18    public $parent;
19
20    /** @var int */
21    public $returnState;
22
23    public function __construct(int $returnState, ?PredictionContext $parent = null)
24    {
25        parent::__construct();
26
27        $this->parent = $parent;
28        $this->returnState = $returnState;
29    }
30
31    public static function create(?PredictionContext $parent, int $returnState) : PredictionContext
32    {
33        // someone can pass in the bits of an array ctx that mean $
34        if ($returnState === PredictionContext::EMPTY_RETURN_STATE && $parent === null) {
35            return PredictionContext::empty();
36        }
37
38        return new SingletonPredictionContext($returnState, $parent);
39    }
40
41    public function getLength() : int
42    {
43        return 1;
44    }
45
46    public function getParent(int $index) : ?PredictionContext
47    {
48        if ($index !== 0) {
49            throw new \InvalidArgumentException('Singleton prediction context has only one parent.');
50        }
51
52        return $this->parent;
53    }
54
55    public function getReturnState(int $index) : int
56    {
57        if ($index !== 0) {
58            throw new \InvalidArgumentException('Singleton prediction context has only one parent.');
59        }
60
61        return $this->returnState;
62    }
63
64    public function equals(object $other) : bool
65    {
66        if ($this === $other) {
67            return true;
68        }
69
70        if (!$other instanceof static) {
71            return false;
72        }
73
74        if ($this->returnState !== $other->returnState) {
75            return false;
76        }
77
78        return Equality::equals($this->parent, $other->parent);
79    }
80
81    public function __toString() : string
82    {
83        $up = $this->parent === null ? '' : (string) $this->parent;
84
85        if ($up === '') {
86            if ($this->returnState === PredictionContext::EMPTY_RETURN_STATE) {
87                return '$';
88            }
89
90            return '' . $this->returnState;
91        }
92
93        return '' . $this->returnState . ' ' . $up;
94    }
95
96    protected function computeHashCode() : int
97    {
98        if ($this->parent === null) {
99            return Hasher::hash(0);
100        }
101
102        return Hasher::hash($this->parent, $this->returnState);
103    }
104}
105