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