1<?php
2
3declare(strict_types=1);
4
5namespace Antlr\Antlr4\Runtime\Atn;
6
7use Antlr\Antlr4\Runtime\Atn\States\ATNState;
8use Antlr\Antlr4\Runtime\Atn\States\DecisionState;
9use Antlr\Antlr4\Runtime\Comparison\Equality;
10use Antlr\Antlr4\Runtime\Comparison\Hasher;
11use Antlr\Antlr4\Runtime\PredictionContexts\PredictionContext;
12
13final class LexerATNConfig extends ATNConfig
14{
15    /** @var LexerActionExecutor|null */
16    private $lexerActionExecutor;
17
18    /** @var bool */
19    private $passedThroughNonGreedyDecision;
20
21    public function __construct(
22        ?self $oldConfig,
23        ?ATNState $state,
24        ?PredictionContext $context = null,
25        ?LexerActionExecutor $executor = null,
26        ?int $alt = null
27    ) {
28        parent::__construct($oldConfig, $state, $context, null, $alt);
29
30        $this->lexerActionExecutor = $executor ?? ($oldConfig->lexerActionExecutor ?? null);
31        $this->passedThroughNonGreedyDecision = $oldConfig ?
32            self::checkNonGreedyDecision($oldConfig, $this->state) :
33            false;
34    }
35
36    public function getLexerActionExecutor() : ?LexerActionExecutor
37    {
38        return $this->lexerActionExecutor;
39    }
40
41    public function isPassedThroughNonGreedyDecision() : bool
42    {
43        return $this->passedThroughNonGreedyDecision;
44    }
45
46    public function hashCode() : int
47    {
48        return Hasher::hash(
49            $this->state->stateNumber,
50            $this->alt,
51            $this->context,
52            $this->semanticContext,
53            $this->passedThroughNonGreedyDecision,
54            $this->lexerActionExecutor
55        );
56    }
57
58    public function equals(object $other) : bool
59    {
60        if ($this === $other) {
61            return true;
62        }
63
64        if (!$other instanceof self) {
65            return false;
66        }
67
68        if (!parent::equals($other)) {
69            return false;
70        }
71
72        if ($this->passedThroughNonGreedyDecision !== $other->passedThroughNonGreedyDecision) {
73            return false;
74        }
75
76        return Equality::equals($this->lexerActionExecutor, $other->lexerActionExecutor);
77    }
78
79    private static function checkNonGreedyDecision(LexerATNConfig $source, ATNState $target) : bool
80    {
81        return $source->passedThroughNonGreedyDecision || ($target instanceof DecisionState && $target->nonGreedy);
82    }
83}
84