1 /* 2 * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. 3 * Use of this file is governed by the BSD 3-clause license that 4 * can be found in the LICENSE.txt file in the project root. 5 */ 6 7 package org.antlr.v4.runtime.atn; 8 9 import org.antlr.v4.runtime.CharStream; 10 import org.antlr.v4.runtime.Lexer; 11 import org.antlr.v4.runtime.misc.MurmurHash; 12 13 /** 14 * This implementation of {@link LexerAction} is used for tracking input offsets 15 * for position-dependent actions within a {@link LexerActionExecutor}. 16 * 17 * <p>This action is not serialized as part of the ATN, and is only required for 18 * position-dependent lexer actions which appear at a location other than the 19 * end of a rule. For more information about DFA optimizations employed for 20 * lexer actions, see {@link LexerActionExecutor#append} and 21 * {@link LexerActionExecutor#fixOffsetBeforeMatch}.</p> 22 * 23 * @author Sam Harwell 24 * @since 4.2 25 */ 26 public final class LexerIndexedCustomAction implements LexerAction { 27 private final int offset; 28 private final LexerAction action; 29 30 /** 31 * Constructs a new indexed custom action by associating a character offset 32 * with a {@link LexerAction}. 33 * 34 * <p>Note: This class is only required for lexer actions for which 35 * {@link LexerAction#isPositionDependent} returns {@code true}.</p> 36 * 37 * @param offset The offset into the input {@link CharStream}, relative to 38 * the token start index, at which the specified lexer action should be 39 * executed. 40 * @param action The lexer action to execute at a particular offset in the 41 * input {@link CharStream}. 42 */ LexerIndexedCustomAction(int offset, LexerAction action)43 public LexerIndexedCustomAction(int offset, LexerAction action) { 44 this.offset = offset; 45 this.action = action; 46 } 47 48 /** 49 * Gets the location in the input {@link CharStream} at which the lexer 50 * action should be executed. The value is interpreted as an offset relative 51 * to the token start index. 52 * 53 * @return The location in the input {@link CharStream} at which the lexer 54 * action should be executed. 55 */ getOffset()56 public int getOffset() { 57 return offset; 58 } 59 60 /** 61 * Gets the lexer action to execute. 62 * 63 * @return A {@link LexerAction} object which executes the lexer action. 64 */ getAction()65 public LexerAction getAction() { 66 return action; 67 } 68 69 /** 70 * {@inheritDoc} 71 * 72 * @return This method returns the result of calling {@link #getActionType} 73 * on the {@link LexerAction} returned by {@link #getAction}. 74 */ 75 @Override getActionType()76 public LexerActionType getActionType() { 77 return action.getActionType(); 78 } 79 80 /** 81 * {@inheritDoc} 82 * @return This method returns {@code true}. 83 */ 84 @Override isPositionDependent()85 public boolean isPositionDependent() { 86 return true; 87 } 88 89 /** 90 * {@inheritDoc} 91 * 92 * <p>This method calls {@link #execute} on the result of {@link #getAction} 93 * using the provided {@code lexer}.</p> 94 */ 95 @Override execute(Lexer lexer)96 public void execute(Lexer lexer) { 97 // assume the input stream position was properly set by the calling code 98 action.execute(lexer); 99 } 100 101 @Override hashCode()102 public int hashCode() { 103 int hash = MurmurHash.initialize(); 104 hash = MurmurHash.update(hash, offset); 105 hash = MurmurHash.update(hash, action); 106 return MurmurHash.finish(hash, 2); 107 } 108 109 @Override equals(Object obj)110 public boolean equals(Object obj) { 111 if (obj == this) { 112 return true; 113 } 114 else if (!(obj instanceof LexerIndexedCustomAction)) { 115 return false; 116 } 117 118 LexerIndexedCustomAction other = (LexerIndexedCustomAction)obj; 119 return offset == other.offset 120 && action.equals(other.action); 121 } 122 123 } 124