xref: /plugin/combo/vendor/antlr/antlr4-php-runtime/src/PredictionContexts/ArrayPredictionContext.php (revision 37748cd8654635afbeca80942126742f0f4cc346)
1*37748cd8SNickeau<?php
2*37748cd8SNickeau
3*37748cd8SNickeaudeclare(strict_types=1);
4*37748cd8SNickeau
5*37748cd8SNickeaunamespace Antlr\Antlr4\Runtime\PredictionContexts;
6*37748cd8SNickeau
7*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Comparison\Equality;
8*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Comparison\Hasher;
9*37748cd8SNickeau
10*37748cd8SNickeaufinal class ArrayPredictionContext extends PredictionContext
11*37748cd8SNickeau{
12*37748cd8SNickeau    /**
13*37748cd8SNickeau     * Parent can be null only if full ctx mode and we make an array from
14*37748cd8SNickeau     * {@see ArrayPredictionContext::empty()} and non-empty. We merge
15*37748cd8SNickeau     * {@see ArrayPredictionContext::empty()} by using null parent and
16*37748cd8SNickeau     * returnState === {@see ArrayPredictionContext::EMPTY_RETURN_STATE}.
17*37748cd8SNickeau     *
18*37748cd8SNickeau     * @var array<PredictionContext|null>
19*37748cd8SNickeau     */
20*37748cd8SNickeau    public $parents;
21*37748cd8SNickeau
22*37748cd8SNickeau    /**
23*37748cd8SNickeau     * Sorted for merge, no duplicates; if present,
24*37748cd8SNickeau     * {@see ArrayPredictionContext::EMPTY_RETURN_STATE} is always last.
25*37748cd8SNickeau     *
26*37748cd8SNickeau     * @var array<int>
27*37748cd8SNickeau     */
28*37748cd8SNickeau    public $returnStates;
29*37748cd8SNickeau
30*37748cd8SNickeau    /**
31*37748cd8SNickeau     * @param array<PredictionContext|null> $parents
32*37748cd8SNickeau     * @param array<int>                    $returnStates
33*37748cd8SNickeau     */
34*37748cd8SNickeau    public function __construct(array $parents, array $returnStates)
35*37748cd8SNickeau    {
36*37748cd8SNickeau        parent::__construct();
37*37748cd8SNickeau
38*37748cd8SNickeau        $this->parents = $parents;
39*37748cd8SNickeau        $this->returnStates = $returnStates;
40*37748cd8SNickeau    }
41*37748cd8SNickeau
42*37748cd8SNickeau    public static function fromOne(SingletonPredictionContext $ctx) : self
43*37748cd8SNickeau    {
44*37748cd8SNickeau        return new ArrayPredictionContext([$ctx->parent], [$ctx->returnState]);
45*37748cd8SNickeau    }
46*37748cd8SNickeau
47*37748cd8SNickeau    /**
48*37748cd8SNickeau     * @param array<PredictionContext|null> $parents
49*37748cd8SNickeau     */
50*37748cd8SNickeau    public function withParents(array $parents) : self
51*37748cd8SNickeau    {
52*37748cd8SNickeau        $clone = clone $this;
53*37748cd8SNickeau        $clone->parents = $parents;
54*37748cd8SNickeau
55*37748cd8SNickeau        return $clone;
56*37748cd8SNickeau    }
57*37748cd8SNickeau
58*37748cd8SNickeau    public function isEmpty() : bool
59*37748cd8SNickeau    {
60*37748cd8SNickeau        // since EMPTY_RETURN_STATE can only appear in the last position, we don't need to verify that size==1
61*37748cd8SNickeau        return $this->returnStates[0] === PredictionContext::EMPTY_RETURN_STATE;
62*37748cd8SNickeau    }
63*37748cd8SNickeau
64*37748cd8SNickeau    public function getLength() : int
65*37748cd8SNickeau    {
66*37748cd8SNickeau        return \count($this->returnStates);
67*37748cd8SNickeau    }
68*37748cd8SNickeau
69*37748cd8SNickeau    public function getParent(int $index) : ?PredictionContext
70*37748cd8SNickeau    {
71*37748cd8SNickeau        return $this->parents[$index];
72*37748cd8SNickeau    }
73*37748cd8SNickeau
74*37748cd8SNickeau    public function getReturnState(int $index) : int
75*37748cd8SNickeau    {
76*37748cd8SNickeau        return $this->returnStates[$index];
77*37748cd8SNickeau    }
78*37748cd8SNickeau
79*37748cd8SNickeau    public function equals(object $other) : bool
80*37748cd8SNickeau    {
81*37748cd8SNickeau        if ($this === $other) {
82*37748cd8SNickeau            return true;
83*37748cd8SNickeau        }
84*37748cd8SNickeau
85*37748cd8SNickeau        if (!$other instanceof self) {
86*37748cd8SNickeau            return false;
87*37748cd8SNickeau        }
88*37748cd8SNickeau
89*37748cd8SNickeau        if ($this->returnStates === $other->returnStates) {
90*37748cd8SNickeau            return false;
91*37748cd8SNickeau        }
92*37748cd8SNickeau
93*37748cd8SNickeau        return Equality::equals($this->parents, $other->parents);
94*37748cd8SNickeau    }
95*37748cd8SNickeau
96*37748cd8SNickeau    public function __toString() : string
97*37748cd8SNickeau    {
98*37748cd8SNickeau        if ($this->isEmpty()) {
99*37748cd8SNickeau            return '[]';
100*37748cd8SNickeau        }
101*37748cd8SNickeau
102*37748cd8SNickeau        $string = '[';
103*37748cd8SNickeau        for ($i = 0, $count = \count($this->returnStates); $i < $count; $i++) {
104*37748cd8SNickeau            if ($i > 0) {
105*37748cd8SNickeau                $string .= ', ';
106*37748cd8SNickeau            }
107*37748cd8SNickeau
108*37748cd8SNickeau            if ($this->returnStates[$i] === PredictionContext::EMPTY_RETURN_STATE) {
109*37748cd8SNickeau                $string .= '$';
110*37748cd8SNickeau                continue;
111*37748cd8SNickeau            }
112*37748cd8SNickeau
113*37748cd8SNickeau            $string .= $this->returnStates[$i];
114*37748cd8SNickeau
115*37748cd8SNickeau            if ($this->parents[$i] !== null) {
116*37748cd8SNickeau                $string .= ' ' . $this->parents[$i];
117*37748cd8SNickeau            } else {
118*37748cd8SNickeau                $string .= 'null';
119*37748cd8SNickeau            }
120*37748cd8SNickeau        }
121*37748cd8SNickeau
122*37748cd8SNickeau        return $string . ']';
123*37748cd8SNickeau    }
124*37748cd8SNickeau
125*37748cd8SNickeau    protected function computeHashCode() : int
126*37748cd8SNickeau    {
127*37748cd8SNickeau        return Hasher::hash($this->parents, $this->returnStates);
128*37748cd8SNickeau    }
129*37748cd8SNickeau}
130