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 /** 43 * The following images show the relation of states and 44 * {@link ATNState#transitions} for various grammar constructs. 45 */ 46 abstract class ATNState 47 { 48 49 enum int INITIAL_NUM_TRANSITIONS = 4; 50 51 enum int INVALID_STATE_NUMBER = -1; 52 53 /** 54 * @uml 55 * Which ATN are we in? 56 */ 57 public ATN atn = null; 58 59 public int stateNumber = INVALID_STATE_NUMBER; 60 61 /** 62 * @uml 63 * at runtime, we don't have Rule objects 64 */ 65 public int ruleIndex; 66 67 public bool epsilonOnlyTransitions = false; 68 69 /** 70 * @uml 71 * Track the transitions emanating from this ATN state. 72 */ 73 public Transition[] transitions; 74 75 /** 76 * @uml 77 * Used to cache lookahead during parsing, not used during construction 78 */ 79 public IntervalSet nextTokenWithinRule; 80 81 /** 82 * @uml 83 * @read 84 * @write 85 */ 86 private Transition[] optimizedTransitions_; 87 88 /** 89 * @uml 90 * @pure 91 * @safe 92 */ 93 public int hashCode() @safe pure 94 { 95 return stateNumber; 96 } 97 98 /** 99 * @uml 100 * @pure 101 * @safe 102 */ 103 public bool equals(Object o) @safe pure 104 { 105 return stateNumber==(cast(ATNState)o).stateNumber; 106 } 107 108 /** 109 * @uml 110 * @pure 111 * @safe 112 */ 113 public bool isNonGreedyExitState() @safe pure 114 { 115 return false; 116 } 117 118 /** 119 * @uml 120 * @pure 121 * @safe 122 * @override 123 */ 124 public override string toString() @safe pure 125 { 126 return to!string(stateNumber); 127 } 128 129 /** 130 * @uml 131 * @pure 132 * @safe 133 */ 134 public Transition[] getTransitions() @safe pure 135 { 136 return transitions.dup; 137 } 138 139 /** 140 * @uml 141 * @pure 142 * @safe 143 */ 144 public int getNumberOfTransitions() @safe pure 145 { 146 return to!int(transitions.length); 147 } 148 149 public void addTransition(Transition e) 150 { 151 if (transitions.length == 0) { 152 epsilonOnlyTransitions = e.isEpsilon; 153 } 154 else 155 if (epsilonOnlyTransitions != e.isEpsilon()) { 156 stderr.writefln("ATN state %1$s has both epsilon and non-epsilon transitions.\n", stateNumber); 157 epsilonOnlyTransitions = false; 158 } 159 transitions ~= e; 160 } 161 162 public Transition transition(int i) 163 { 164 return transitions[i]; 165 } 166 167 public void setTransition(int i, Transition e) 168 { 169 transitions[i] = e; 170 } 171 172 public Transition removeTransition(int index) 173 { 174 auto t = transitions[index]; 175 transitions = transitions[0..index] ~ transitions[index+1..$]; 176 return t; 177 } 178 179 abstract public int getStateType(); 180 181 public bool onlyHasEpsilonTransitions() 182 { 183 return epsilonOnlyTransitions; 184 } 185 186 public void setRuleIndex(int ruleIndex) 187 { 188 this.ruleIndex = ruleIndex; 189 } 190 191 public bool isOptimized() 192 { 193 return optimizedTransitions != transitions; 194 } 195 196 public size_t numberOfOptimizedTransitions() 197 { 198 return optimizedTransitions.length; 199 } 200 201 public Transition getOptimizedTransition(size_t i) 202 { 203 return optimizedTransitions[i]; 204 } 205 206 public void addOptimizedTransition(Transition e) 207 { 208 if (!isOptimized) 209 { 210 optimizedTransitions_.length = 0; 211 } 212 optimizedTransitions_ ~= e; 213 } 214 215 public void setOptimizedTransition(size_t i, Transition e) 216 { 217 if (!isOptimized) 218 { 219 assert(false, "InvalidOperationException"); 220 } 221 optimizedTransitions_[i] = e; 222 } 223 224 public void removeOptimizedTransition(size_t i) 225 { 226 if (!isOptimized) 227 { 228 assert(false, "InvalidOperationException"); 229 } 230 optimizedTransitions_ = optimizedTransitions_.remove(i); 231 } 232 233 public this() 234 { 235 optimizedTransitions = transitions.dup; 236 } 237 238 public final Transition[] optimizedTransitions() 239 { 240 return this.optimizedTransitions_.dup; 241 } 242 243 public final void optimizedTransitions(Transition[] optimizedTransitions) 244 { 245 this.optimizedTransitions_ = optimizedTransitions.dup; 246 } 247 248 }