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 * This implementation of {@see LexerAction} is used for tracking input offsets 12 * for position-dependent actions within a {@see LexerActionExecutor}. 13 * 14 * This action is not serialized as part of the ATN, and is only required for 15 * position-dependent lexer actions which appear at a location other than the 16 * end of a rule. For more information about DFA optimizations employed for 17 * lexer actions, see {@see LexerActionExecutor::append()} and 18 * {@see LexerActionExecutor::fixOffsetBeforeMatch()}. 19 * 20 * @author Sam Harwell 21 */ 22final class LexerIndexedCustomAction implements LexerAction 23{ 24 /** @var int */ 25 private $offset; 26 27 /** @var LexerAction */ 28 private $action; 29 30 /** 31 * Constructs a new indexed custom action by associating a character offset 32 * with a {@see LexerAction}. 33 * 34 * Note: This class is only required for lexer actions for which 35 * {@see LexerAction::isPositionDependent()} returns `true`. 36 * 37 * @param int $offset The offset into the input {@see CharStream}, 38 * relative to the token start index, at which 39 * the specified lexer action should be executed. 40 * @param LexerAction $action The lexer action to execute at a particular 41 * offset in the input {@see CharStream}. 42 */ 43 public function __construct(int $offset, LexerAction $action) 44 { 45 $this->offset = $offset; 46 $this->action = $action; 47 } 48 49 /** 50 * Gets the location in the input {@see CharStream} at which the lexer 51 * action should be executed. The value is interpreted as an offset relative 52 * to the token start index. 53 * 54 * @return int The location in the input {@see CharStream} at which the lexer 55 * action should be executed. 56 */ 57 public function getOffset() : int 58 { 59 return $this->offset; 60 } 61 62 /** 63 * Gets the lexer action to execute. 64 * 65 * @return LexerAction A {@see LexerAction} object which executes the lexer action. 66 */ 67 public function getAction() : LexerAction 68 { 69 return $this->action; 70 } 71 72 /** 73 * {@inheritdoc} 74 * 75 * @return int This method returns the result of calling 76 * {@see LexerIndexedCustomAction::getActionType()} on the 77 * {@see LexerAction} returned by 78 * {@see LexerIndexedCustomAction::getAction()}. 79 */ 80 public function getActionType() : int 81 { 82 return $this->action->getActionType(); 83 } 84 85 /** 86 * {@inheritdoc} 87 * 88 * @return bool This method returns `true`. 89 */ 90 public function isPositionDependent() : bool 91 { 92 return true; 93 } 94 95 /** 96 * {@inheritdoc} 97 * 98 * This method calls {@see LexerIndexedCustomAction::execute()} on the result 99 * of {@see LexerIndexedCustomAction::getAction()} using the provided `lexer`. 100 */ 101 public function execute(Lexer $lexer) : void 102 { 103 // assume the input stream position was properly set by the calling code 104 $this->action->execute($lexer); 105 } 106 107 public function hashCode() : int 108 { 109 return Hasher::hash($this->getActionType(), $this->offset, $this->action); 110 } 111 112 public function equals(object $other) : bool 113 { 114 if ($this === $other) { 115 return true; 116 } 117 118 if (!$other instanceof self) { 119 return false; 120 } 121 122 return $this->offset === $other->offset 123 && $this->action->equals($other->action); 124 } 125} 126