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