1 /* 2 * [The "BSD license"] 3 * Copyright (c) 2016 Terence Parr 4 * Copyright (c) 2016 Sam Harwell 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 module antlr.v4.runtime.atn.ATNState; 32 33 import std.stdio; 34 import std.conv; 35 import std.array; 36 import antlr.v4.runtime.atn.StateNames; 37 import antlr.v4.runtime.atn.Transition; 38 import antlr.v4.runtime.atn.ATN; 39 import antlr.v4.runtime.misc.IntervalSet; 40 import std.algorithm.mutation: remove; 41 42 // Class ATNState 43 /** 44 * The following images show the relation of states and 45 * {@link ATNState#transitions} for various grammar constructs. 46 */ 47 abstract class ATNState 48 { 49 50 public static immutable int INITIAL_NUM_TRANSITIONS = 4; 51 52 public static immutable int INVALID_STATE_NUMBER = -1; 53 54 /** 55 * @uml 56 * Which ATN are we in? 57 */ 58 public ATN atn = null; 59 60 public int stateNumber = INVALID_STATE_NUMBER; 61 62 /** 63 * @uml 64 * at runtime, we don't have Rule objects 65 */ 66 public int ruleIndex; 67 68 public bool epsilonOnlyTransitions = false; 69 70 /** 71 * @uml 72 * Track the transitions emanating from this ATN state. 73 */ 74 public Transition[] transitions; 75 76 /** 77 * @uml 78 * Used to cache lookahead during parsing, not used during construction 79 */ 80 public IntervalSet nextTokenWithinRule; 81 82 /** 83 * @uml 84 * @read 85 * @write 86 */ 87 private Transition[] optimizedTransitions_; 88 89 /** 90 * @uml 91 * @pure 92 * @safe 93 */ 94 public int hashCode() @safe pure 95 { 96 return stateNumber; 97 } 98 99 /** 100 * @uml 101 * @pure 102 * @safe 103 */ 104 public bool equals(Object o) @safe pure 105 { 106 return stateNumber==(cast(ATNState)o).stateNumber; 107 } 108 109 /** 110 * @uml 111 * @pure 112 * @safe 113 */ 114 public bool isNonGreedyExitState() @safe pure 115 { 116 return false; 117 } 118 119 /** 120 * @uml 121 * @pure 122 * @safe 123 * @override 124 */ 125 public override string toString() @safe pure 126 { 127 return to!string(stateNumber); 128 } 129 130 /** 131 * @uml 132 * @pure 133 * @safe 134 */ 135 public Transition[] getTransitions() @safe pure 136 { 137 return transitions.dup; 138 } 139 140 /** 141 * @uml 142 * @pure 143 * @safe 144 */ 145 public int getNumberOfTransitions() @safe pure 146 { 147 return to!int(transitions.length); 148 } 149 150 public void addTransition(Transition e) 151 { 152 if (transitions.length == 0) { 153 epsilonOnlyTransitions = e.isEpsilon; 154 } 155 else 156 if (epsilonOnlyTransitions != e.isEpsilon()) { 157 stderr.writefln("ATN state %1$s has both epsilon and non-epsilon transitions.\n", stateNumber); 158 epsilonOnlyTransitions = false; 159 } 160 transitions ~= e; 161 } 162 163 public Transition transition(int i) 164 { 165 return transitions[i]; 166 } 167 168 public void setTransition(int i, Transition e) 169 { 170 transitions[i] = e; 171 } 172 173 public Transition removeTransition(int index) 174 { 175 auto t = transitions[index]; 176 transitions = transitions[0..index] ~ transitions[index+1..$]; 177 return t; 178 } 179 180 abstract public int getStateType(); 181 182 public bool onlyHasEpsilonTransitions() 183 { 184 return epsilonOnlyTransitions; 185 } 186 187 public void setRuleIndex(int ruleIndex) 188 { 189 this.ruleIndex = ruleIndex; 190 } 191 192 public bool isOptimized() 193 { 194 return optimizedTransitions != transitions; 195 } 196 197 public size_t numberOfOptimizedTransitions() 198 { 199 return optimizedTransitions.length; 200 } 201 202 public Transition getOptimizedTransition(size_t i) 203 { 204 return optimizedTransitions[i]; 205 } 206 207 public void addOptimizedTransition(Transition e) 208 { 209 if (!isOptimized) 210 { 211 optimizedTransitions_.length = 0; 212 } 213 optimizedTransitions_ ~= e; 214 } 215 216 public void setOptimizedTransition(size_t i, Transition e) 217 { 218 if (!isOptimized) 219 { 220 assert(false, "InvalidOperationException"); 221 } 222 optimizedTransitions_[i] = e; 223 } 224 225 public void removeOptimizedTransition(size_t i) 226 { 227 if (!isOptimized) 228 { 229 assert(false, "InvalidOperationException"); 230 } 231 optimizedTransitions_ = optimizedTransitions_.remove(i); 232 } 233 234 public this() 235 { 236 optimizedTransitions = transitions.dup; 237 } 238 239 public final Transition[] optimizedTransitions() 240 { 241 return this.optimizedTransitions_.dup; 242 } 243 244 public final void optimizedTransitions(Transition[] optimizedTransitions) 245 { 246 this.optimizedTransitions_ = optimizedTransitions.dup; 247 } 248 249 }