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