1<?php
2
3declare(strict_types=1);
4
5namespace Antlr\Antlr4\Runtime\Atn\Actions;
6
7use Antlr\Antlr4\Runtime\Comparison\Hasher;
8use Antlr\Antlr4\Runtime\Lexer;
9
10/**
11 * Executes a custom lexer action by calling {@see Recognizer::action()} with the
12 * rule and action indexes assigned to the custom action. The implementation of
13 * a custom action is added to the generated code for the lexer in an override
14 * of {@see Recognizer::action()} when the grammar is compiled.
15 *
16 * This class may represent embedded actions created with the `{...}`
17 * syntax in ANTLR 4, as well as actions created for lexer commands where the
18 * command argument could not be evaluated when the grammar was compiled.
19 *
20 * @author Sam Harwell
21 */
22final class LexerCustomAction implements LexerAction
23{
24    /** @var int */
25    private $ruleIndex;
26
27    /** @var int */
28    private $actionIndex;
29
30    /**
31     * Constructs a custom lexer action with the specified rule and action
32     * indexes.
33     *
34     * @param int $ruleIndex   The rule index to use for calls to
35     *                         {@see Recognizer::action()}.
36     * @param int $actionIndex The action index to use for calls to
37     *                         {@see Recognizer::action()}.
38     */
39    public function __construct(int $ruleIndex, int $actionIndex)
40    {
41        $this->ruleIndex = $ruleIndex;
42        $this->actionIndex = $actionIndex;
43    }
44
45    /**
46     * Gets the rule index to use for calls to {@see Recognizer::action()}.
47     *
48     * @return int The rule index for the custom action.
49     */
50    public function getRuleIndex() : int
51    {
52        return $this->ruleIndex;
53    }
54
55    /**
56     * Gets the action index to use for calls to {@see Recognizer::action()}.
57     *
58     * @return int The action index for the custom action.
59     */
60    public function getActionIndex() : int
61    {
62        return $this->actionIndex;
63    }
64
65    /**
66     * {@inheritdoc}
67     *
68     * @return int This method returns {@see LexerActionType::CUSTOM()}.
69     */
70    public function getActionType() : int
71    {
72        return LexerActionType::CUSTOM;
73    }
74
75    /**
76     * Gets whether the lexer action is position-dependent. Position-dependent
77     * actions may have different semantics depending on the {@see CharStream}
78     * index at the time the action is executed.
79     *
80     * Custom actions are position-dependent since they may represent a
81     * user-defined embedded action which makes calls to methods like
82     * {@see Lexer::getText()}.
83     *
84     * @return bool This method returns `true`.
85     */
86    public function isPositionDependent() : bool
87    {
88        return true;
89    }
90
91    /**
92     * {@inheritdoc}
93     *
94     * Custom actions are implemented by calling {@see Lexer::action()} with the
95     * appropriate rule and action indexes.
96     */
97    public function execute(Lexer $lexer) : void
98    {
99        $lexer->action(null, $this->ruleIndex, $this->actionIndex);
100    }
101
102    public function hashCode() : int
103    {
104        return Hasher::hash($this->getActionType(), $this->ruleIndex, $this->actionIndex);
105    }
106
107    public function equals(object $other) : bool
108    {
109        if ($this === $other) {
110            return true;
111        }
112
113        if (!$other instanceof self) {
114            return false;
115        }
116
117        return $this->ruleIndex === $other->ruleIndex
118            && $this->actionIndex === $other->actionIndex;
119    }
120}
121