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.Token;
10 import org.antlr.v4.runtime.misc.IntervalSet;
11 import org.antlr.v4.runtime.misc.Pair;
12 
13 import java.io.InvalidClassException;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Locale;
17 import java.util.UUID;
18 
19 /**
20  *
21  * @author Sam Harwell
22  */
23 public class ATNDeserializer {
24 	public static final int SERIALIZED_VERSION;
25 	static {
26 		/* This value should never change. Updates following this version are
27 		 * reflected as change in the unique ID SERIALIZED_UUID.
28 		 */
29 		SERIALIZED_VERSION = 3;
30 	}
31 
32 	/**
33 	 * This is the earliest supported serialized UUID.
34 	 */
35 	private static final UUID BASE_SERIALIZED_UUID;
36 	/**
37 	 * This UUID indicates an extension of {@link BASE_SERIALIZED_UUID} for the
38 	 * addition of precedence predicates.
39 	 */
40 	private static final UUID ADDED_PRECEDENCE_TRANSITIONS;
41 	/**
42 	 * This UUID indicates an extension of {@link #ADDED_PRECEDENCE_TRANSITIONS}
43 	 * for the addition of lexer actions encoded as a sequence of
44 	 * {@link LexerAction} instances.
45 	 */
46 	private static final UUID ADDED_LEXER_ACTIONS;
47 	/**
48 	 * This UUID indicates the serialized ATN contains two sets of
49 	 * IntervalSets, where the second set's values are encoded as
50 	 * 32-bit integers to support the full Unicode SMP range up to U+10FFFF.
51 	 */
52 	private static final UUID ADDED_UNICODE_SMP;
53 	/**
54 	 * This list contains all of the currently supported UUIDs, ordered by when
55 	 * the feature first appeared in this branch.
56 	 */
57 	private static final List<UUID> SUPPORTED_UUIDS;
58 
59 	/**
60 	 * This is the current serialized UUID.
61 	 */
62 	public static final UUID SERIALIZED_UUID;
63 	static {
64 		/* WARNING: DO NOT MERGE THESE LINES. If UUIDs differ during a merge,
65 		 * resolve the conflict by generating a new ID!
66 		 */
67 		BASE_SERIALIZED_UUID = UUID.fromString("33761B2D-78BB-4A43-8B0B-4F5BEE8AACF3");
68 		ADDED_PRECEDENCE_TRANSITIONS = UUID.fromString("1DA0C57D-6C06-438A-9B27-10BCB3CE0F61");
69 		ADDED_LEXER_ACTIONS = UUID.fromString("AADB8D7E-AEEF-4415-AD2B-8204D6CF042E");
70 		ADDED_UNICODE_SMP = UUID.fromString("59627784-3BE5-417A-B9EB-8131A7286089");
71 
72 		SUPPORTED_UUIDS = new ArrayList<UUID>();
73 		SUPPORTED_UUIDS.add(BASE_SERIALIZED_UUID);
74 		SUPPORTED_UUIDS.add(ADDED_PRECEDENCE_TRANSITIONS);
75 		SUPPORTED_UUIDS.add(ADDED_LEXER_ACTIONS);
76 		SUPPORTED_UUIDS.add(ADDED_UNICODE_SMP);
77 
78 		SERIALIZED_UUID = ADDED_UNICODE_SMP;
79 	}
80 
81 	interface UnicodeDeserializer {
82 		// Wrapper for readInt() or readInt32()
readUnicode(char[] data, int p)83 		int readUnicode(char[] data, int p);
84 
85 		// Work around Java not allowing mutation of captured variables
86 		// by returning amount by which to increment p after each read
size()87 		int size();
88 	}
89 
90 	enum UnicodeDeserializingMode {
91 		UNICODE_BMP,
92 		UNICODE_SMP
93 	}
94 
getUnicodeDeserializer(UnicodeDeserializingMode mode)95 	static UnicodeDeserializer getUnicodeDeserializer(UnicodeDeserializingMode mode) {
96 		if (mode == UnicodeDeserializingMode.UNICODE_BMP) {
97 			return new UnicodeDeserializer() {
98 				@Override
99 				public int readUnicode(char[] data, int p) {
100 					return toInt(data[p]);
101 				}
102 
103 				@Override
104 				public int size() {
105 					return 1;
106 				}
107 			};
108 		}
109 		else {
110 			return new UnicodeDeserializer() {
111 				@Override
112 				public int readUnicode(char[] data, int p) {
113 					return toInt32(data, p);
114 				}
115 
116 				@Override
117 				public int size() {
118 					return 2;
119 				}
120 			};
121 		}
122 	}
123 
124 	private final ATNDeserializationOptions deserializationOptions;
125 
126 	public ATNDeserializer() {
127 		this(ATNDeserializationOptions.getDefaultOptions());
128 	}
129 
130 	public ATNDeserializer(ATNDeserializationOptions deserializationOptions) {
131 		if (deserializationOptions == null) {
132 			deserializationOptions = ATNDeserializationOptions.getDefaultOptions();
133 		}
134 
135 		this.deserializationOptions = deserializationOptions;
136 	}
137 
138 	/**
139 	 * Determines if a particular serialized representation of an ATN supports
140 	 * a particular feature, identified by the {@link UUID} used for serializing
141 	 * the ATN at the time the feature was first introduced.
142 	 *
143 	 * @param feature The {@link UUID} marking the first time the feature was
144 	 * supported in the serialized ATN.
145 	 * @param actualUuid The {@link UUID} of the actual serialized ATN which is
146 	 * currently being deserialized.
147 	 * @return {@code true} if the {@code actualUuid} value represents a
148 	 * serialized ATN at or after the feature identified by {@code feature} was
149 	 * introduced; otherwise, {@code false}.
150 	 */
151 	static protected boolean isFeatureSupported(UUID feature, UUID actualUuid) {
152 		int featureIndex = SUPPORTED_UUIDS.indexOf(feature);
153 		if (featureIndex < 0) {
154 			return false;
155 		}
156 
157 		return SUPPORTED_UUIDS.indexOf(actualUuid) >= featureIndex;
158 	}
159 
160 	@SuppressWarnings("deprecation")
161 	public ATN deserialize(char[] data) {
162 		data = data.clone();
163 
164 		// Each char value in data is shifted by +2 at the entry to this method.
165 		// This is an encoding optimization targeting the serialized values 0
166 		// and -1 (serialized to 0xFFFF), each of which are very common in the
167 		// serialized form of the ATN. In the modified UTF-8 that Java uses for
168 		// compiled string literals, these two character values have multi-byte
169 		// forms. By shifting each value by +2, they become characters 2 and 1
170 		// prior to writing the string, each of which have single-byte
171 		// representations. Since the shift occurs in the tool during ATN
172 		// serialization, each target is responsible for adjusting the values
173 		// during deserialization.
174 		//
175 		// As a special case, note that the first element of data is not
176 		// adjusted because it contains the major version number of the
177 		// serialized ATN, which was fixed at 3 at the time the value shifting
178 		// was implemented.
179 		for (int i = 1; i < data.length; i++) {
180 			data[i] = (char)(data[i] - 2);
181 		}
182 
183 		int p = 0;
184 		int version = toInt(data[p++]);
185 		if (version != SERIALIZED_VERSION) {
186 			String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with version %d (expected %d).", version, SERIALIZED_VERSION);
187 			throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
188 		}
189 
190 		UUID uuid = toUUID(data, p);
191 		p += 8;
192 		if (!SUPPORTED_UUIDS.contains(uuid)) {
193 			String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with UUID %s (expected %s or a legacy UUID).", uuid, SERIALIZED_UUID);
194 			throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
195 		}
196 
197 		boolean supportsPrecedencePredicates = isFeatureSupported(ADDED_PRECEDENCE_TRANSITIONS, uuid);
198 		boolean supportsLexerActions = isFeatureSupported(ADDED_LEXER_ACTIONS, uuid);
199 
200 		ATNType grammarType = ATNType.values()[toInt(data[p++])];
201 		int maxTokenType = toInt(data[p++]);
202 		ATN atn = new ATN(grammarType, maxTokenType);
203 
204 		//
205 		// STATES
206 		//
207 		List<Pair<LoopEndState, Integer>> loopBackStateNumbers = new ArrayList<Pair<LoopEndState, Integer>>();
208 		List<Pair<BlockStartState, Integer>> endStateNumbers = new ArrayList<Pair<BlockStartState, Integer>>();
209 		int nstates = toInt(data[p++]);
210 		for (int i=0; i<nstates; i++) {
211 			int stype = toInt(data[p++]);
212 			// ignore bad type of states
213 			if ( stype==ATNState.INVALID_TYPE ) {
214 				atn.addState(null);
215 				continue;
216 			}
217 
218 			int ruleIndex = toInt(data[p++]);
219 			if (ruleIndex == Character.MAX_VALUE) {
220 				ruleIndex = -1;
221 			}
222 
223 			ATNState s = stateFactory(stype, ruleIndex);
224 			if ( stype == ATNState.LOOP_END ) { // special case
225 				int loopBackStateNumber = toInt(data[p++]);
226 				loopBackStateNumbers.add(new Pair<LoopEndState, Integer>((LoopEndState)s, loopBackStateNumber));
227 			}
228 			else if (s instanceof BlockStartState) {
229 				int endStateNumber = toInt(data[p++]);
230 				endStateNumbers.add(new Pair<BlockStartState, Integer>((BlockStartState)s, endStateNumber));
231 			}
232 			atn.addState(s);
233 		}
234 
235 		// delay the assignment of loop back and end states until we know all the state instances have been initialized
236 		for (Pair<LoopEndState, Integer> pair : loopBackStateNumbers) {
237 			pair.a.loopBackState = atn.states.get(pair.b);
238 		}
239 
240 		for (Pair<BlockStartState, Integer> pair : endStateNumbers) {
241 			pair.a.endState = (BlockEndState)atn.states.get(pair.b);
242 		}
243 
244 		int numNonGreedyStates = toInt(data[p++]);
245 		for (int i = 0; i < numNonGreedyStates; i++) {
246 			int stateNumber = toInt(data[p++]);
247 			((DecisionState)atn.states.get(stateNumber)).nonGreedy = true;
248 		}
249 
250 		if (supportsPrecedencePredicates) {
251 			int numPrecedenceStates = toInt(data[p++]);
252 			for (int i = 0; i < numPrecedenceStates; i++) {
253 				int stateNumber = toInt(data[p++]);
254 				((RuleStartState)atn.states.get(stateNumber)).isLeftRecursiveRule = true;
255 			}
256 		}
257 
258 		//
259 		// RULES
260 		//
261 		int nrules = toInt(data[p++]);
262 		if ( atn.grammarType == ATNType.LEXER ) {
263 			atn.ruleToTokenType = new int[nrules];
264 		}
265 
266 		atn.ruleToStartState = new RuleStartState[nrules];
267 		for (int i=0; i<nrules; i++) {
268 			int s = toInt(data[p++]);
269 			RuleStartState startState = (RuleStartState)atn.states.get(s);
270 			atn.ruleToStartState[i] = startState;
271 			if ( atn.grammarType == ATNType.LEXER ) {
272 				int tokenType = toInt(data[p++]);
273 				if (tokenType == 0xFFFF) {
274 					tokenType = Token.EOF;
275 				}
276 
277 				atn.ruleToTokenType[i] = tokenType;
278 
279 				if (!isFeatureSupported(ADDED_LEXER_ACTIONS, uuid)) {
280 					// this piece of unused metadata was serialized prior to the
281 					// addition of LexerAction
282 					int actionIndexIgnored = toInt(data[p++]);
283 				}
284 			}
285 		}
286 
287 		atn.ruleToStopState = new RuleStopState[nrules];
288 		for (ATNState state : atn.states) {
289 			if (!(state instanceof RuleStopState)) {
290 				continue;
291 			}
292 
293 			RuleStopState stopState = (RuleStopState)state;
294 			atn.ruleToStopState[state.ruleIndex] = stopState;
295 			atn.ruleToStartState[state.ruleIndex].stopState = stopState;
296 		}
297 
298 		//
299 		// MODES
300 		//
301 		int nmodes = toInt(data[p++]);
302 		for (int i=0; i<nmodes; i++) {
303 			int s = toInt(data[p++]);
304 			atn.modeToStartState.add((TokensStartState)atn.states.get(s));
305 		}
306 
307 		//
308 		// SETS
309 		//
310 		List<IntervalSet> sets = new ArrayList<IntervalSet>();
311 
312 		// First, read all sets with 16-bit Unicode code points <= U+FFFF.
313 		p = deserializeSets(data, p, sets, getUnicodeDeserializer(UnicodeDeserializingMode.UNICODE_BMP));
314 
315 		// Next, if the ATN was serialized with the Unicode SMP feature,
316 		// deserialize sets with 32-bit arguments <= U+10FFFF.
317 		if (isFeatureSupported(ADDED_UNICODE_SMP, uuid)) {
318 			p = deserializeSets(data, p, sets, getUnicodeDeserializer(UnicodeDeserializingMode.UNICODE_SMP));
319 		}
320 
321 		//
322 		// EDGES
323 		//
324 		int nedges = toInt(data[p++]);
325 		for (int i=0; i<nedges; i++) {
326 			int src = toInt(data[p]);
327 			int trg = toInt(data[p+1]);
328 			int ttype = toInt(data[p+2]);
329 			int arg1 = toInt(data[p+3]);
330 			int arg2 = toInt(data[p+4]);
331 			int arg3 = toInt(data[p+5]);
332 			Transition trans = edgeFactory(atn, ttype, src, trg, arg1, arg2, arg3, sets);
333 //			System.out.println("EDGE "+trans.getClass().getSimpleName()+" "+
334 //							   src+"->"+trg+
335 //					   " "+Transition.serializationNames[ttype]+
336 //					   " "+arg1+","+arg2+","+arg3);
337 			ATNState srcState = atn.states.get(src);
338 			srcState.addTransition(trans);
339 			p += 6;
340 		}
341 
342 		// edges for rule stop states can be derived, so they aren't serialized
343 		for (ATNState state : atn.states) {
344 			for (int i = 0; i < state.getNumberOfTransitions(); i++) {
345 				Transition t = state.transition(i);
346 				if (!(t instanceof RuleTransition)) {
347 					continue;
348 				}
349 
350 				RuleTransition ruleTransition = (RuleTransition)t;
351 				int outermostPrecedenceReturn = -1;
352 				if (atn.ruleToStartState[ruleTransition.target.ruleIndex].isLeftRecursiveRule) {
353 					if (ruleTransition.precedence == 0) {
354 						outermostPrecedenceReturn = ruleTransition.target.ruleIndex;
355 					}
356 				}
357 
358 				EpsilonTransition returnTransition = new EpsilonTransition(ruleTransition.followState, outermostPrecedenceReturn);
359 				atn.ruleToStopState[ruleTransition.target.ruleIndex].addTransition(returnTransition);
360 			}
361 		}
362 
363 		for (ATNState state : atn.states) {
364 			if (state instanceof BlockStartState) {
365 				// we need to know the end state to set its start state
366 				if (((BlockStartState)state).endState == null) {
367 					throw new IllegalStateException();
368 				}
369 
370 				// block end states can only be associated to a single block start state
371 				if (((BlockStartState)state).endState.startState != null) {
372 					throw new IllegalStateException();
373 				}
374 
375 				((BlockStartState)state).endState.startState = (BlockStartState)state;
376 			}
377 
378 			if (state instanceof PlusLoopbackState) {
379 				PlusLoopbackState loopbackState = (PlusLoopbackState)state;
380 				for (int i = 0; i < loopbackState.getNumberOfTransitions(); i++) {
381 					ATNState target = loopbackState.transition(i).target;
382 					if (target instanceof PlusBlockStartState) {
383 						((PlusBlockStartState)target).loopBackState = loopbackState;
384 					}
385 				}
386 			}
387 			else if (state instanceof StarLoopbackState) {
388 				StarLoopbackState loopbackState = (StarLoopbackState)state;
389 				for (int i = 0; i < loopbackState.getNumberOfTransitions(); i++) {
390 					ATNState target = loopbackState.transition(i).target;
391 					if (target instanceof StarLoopEntryState) {
392 						((StarLoopEntryState)target).loopBackState = loopbackState;
393 					}
394 				}
395 			}
396 		}
397 
398 		//
399 		// DECISIONS
400 		//
401 		int ndecisions = toInt(data[p++]);
402 		for (int i=1; i<=ndecisions; i++) {
403 			int s = toInt(data[p++]);
404 			DecisionState decState = (DecisionState)atn.states.get(s);
405 			atn.decisionToState.add(decState);
406 			decState.decision = i-1;
407 		}
408 
409 		//
410 		// LEXER ACTIONS
411 		//
412 		if (atn.grammarType == ATNType.LEXER) {
413 			if (supportsLexerActions) {
414 				atn.lexerActions = new LexerAction[toInt(data[p++])];
415 				for (int i = 0; i < atn.lexerActions.length; i++) {
416 					LexerActionType actionType = LexerActionType.values()[toInt(data[p++])];
417 					int data1 = toInt(data[p++]);
418 					if (data1 == 0xFFFF) {
419 						data1 = -1;
420 					}
421 
422 					int data2 = toInt(data[p++]);
423 					if (data2 == 0xFFFF) {
424 						data2 = -1;
425 					}
426 
427 					LexerAction lexerAction = lexerActionFactory(actionType, data1, data2);
428 
429 					atn.lexerActions[i] = lexerAction;
430 				}
431 			}
432 			else {
433 				// for compatibility with older serialized ATNs, convert the old
434 				// serialized action index for action transitions to the new
435 				// form, which is the index of a LexerCustomAction
436 				List<LexerAction> legacyLexerActions = new ArrayList<LexerAction>();
437 				for (ATNState state : atn.states) {
438 					for (int i = 0; i < state.getNumberOfTransitions(); i++) {
439 						Transition transition = state.transition(i);
440 						if (!(transition instanceof ActionTransition)) {
441 							continue;
442 						}
443 
444 						int ruleIndex = ((ActionTransition)transition).ruleIndex;
445 						int actionIndex = ((ActionTransition)transition).actionIndex;
446 						LexerCustomAction lexerAction = new LexerCustomAction(ruleIndex, actionIndex);
447 						state.setTransition(i, new ActionTransition(transition.target, ruleIndex, legacyLexerActions.size(), false));
448 						legacyLexerActions.add(lexerAction);
449 					}
450 				}
451 
452 				atn.lexerActions = legacyLexerActions.toArray(new LexerAction[legacyLexerActions.size()]);
453 			}
454 		}
455 
456 		markPrecedenceDecisions(atn);
457 
458 		if (deserializationOptions.isVerifyATN()) {
459 			verifyATN(atn);
460 		}
461 
462 		if (deserializationOptions.isGenerateRuleBypassTransitions() && atn.grammarType == ATNType.PARSER) {
463 			atn.ruleToTokenType = new int[atn.ruleToStartState.length];
464 			for (int i = 0; i < atn.ruleToStartState.length; i++) {
465 				atn.ruleToTokenType[i] = atn.maxTokenType + i + 1;
466 			}
467 
468 			for (int i = 0; i < atn.ruleToStartState.length; i++) {
469 				BasicBlockStartState bypassStart = new BasicBlockStartState();
470 				bypassStart.ruleIndex = i;
471 				atn.addState(bypassStart);
472 
473 				BlockEndState bypassStop = new BlockEndState();
474 				bypassStop.ruleIndex = i;
475 				atn.addState(bypassStop);
476 
477 				bypassStart.endState = bypassStop;
478 				atn.defineDecisionState(bypassStart);
479 
480 				bypassStop.startState = bypassStart;
481 
482 				ATNState endState;
483 				Transition excludeTransition = null;
484 				if (atn.ruleToStartState[i].isLeftRecursiveRule) {
485 					// wrap from the beginning of the rule to the StarLoopEntryState
486 					endState = null;
487 					for (ATNState state : atn.states) {
488 						if (state.ruleIndex != i) {
489 							continue;
490 						}
491 
492 						if (!(state instanceof StarLoopEntryState)) {
493 							continue;
494 						}
495 
496 						ATNState maybeLoopEndState = state.transition(state.getNumberOfTransitions() - 1).target;
497 						if (!(maybeLoopEndState instanceof LoopEndState)) {
498 							continue;
499 						}
500 
501 						if (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transition(0).target instanceof RuleStopState) {
502 							endState = state;
503 							break;
504 						}
505 					}
506 
507 					if (endState == null) {
508 						throw new UnsupportedOperationException("Couldn't identify final state of the precedence rule prefix section.");
509 					}
510 
511 					excludeTransition = ((StarLoopEntryState)endState).loopBackState.transition(0);
512 				}
513 				else {
514 					endState = atn.ruleToStopState[i];
515 				}
516 
517 				// all non-excluded transitions that currently target end state need to target blockEnd instead
518 				for (ATNState state : atn.states) {
519 					for (Transition transition : state.transitions) {
520 						if (transition == excludeTransition) {
521 							continue;
522 						}
523 
524 						if (transition.target == endState) {
525 							transition.target = bypassStop;
526 						}
527 					}
528 				}
529 
530 				// all transitions leaving the rule start state need to leave blockStart instead
531 				while (atn.ruleToStartState[i].getNumberOfTransitions() > 0) {
532 					Transition transition = atn.ruleToStartState[i].removeTransition(atn.ruleToStartState[i].getNumberOfTransitions() - 1);
533 					bypassStart.addTransition(transition);
534 				}
535 
536 				// link the new states
537 				atn.ruleToStartState[i].addTransition(new EpsilonTransition(bypassStart));
538 				bypassStop.addTransition(new EpsilonTransition(endState));
539 
540 				ATNState matchState = new BasicState();
541 				atn.addState(matchState);
542 				matchState.addTransition(new AtomTransition(bypassStop, atn.ruleToTokenType[i]));
543 				bypassStart.addTransition(new EpsilonTransition(matchState));
544 			}
545 
546 			if (deserializationOptions.isVerifyATN()) {
547 				// reverify after modification
548 				verifyATN(atn);
549 			}
550 		}
551 
552 		return atn;
553 	}
554 
555 	private int deserializeSets(char[] data, int p, List<IntervalSet> sets, UnicodeDeserializer unicodeDeserializer) {
556 		int nsets = toInt(data[p++]);
557 		for (int i=0; i<nsets; i++) {
558 			int nintervals = toInt(data[p]);
559 			p++;
560 			IntervalSet set = new IntervalSet();
561 			sets.add(set);
562 
563 			boolean containsEof = toInt(data[p++]) != 0;
564 			if (containsEof) {
565 				set.add(-1);
566 			}
567 
568 			for (int j=0; j<nintervals; j++) {
569 				int a = unicodeDeserializer.readUnicode(data, p);
570 				p += unicodeDeserializer.size();
571 				int b = unicodeDeserializer.readUnicode(data, p);
572 				p += unicodeDeserializer.size();
573 				set.add(a, b);
574 			}
575 		}
576 		return p;
577 	}
578 
579 	/**
580 	 * Analyze the {@link StarLoopEntryState} states in the specified ATN to set
581 	 * the {@link StarLoopEntryState#isPrecedenceDecision} field to the
582 	 * correct value.
583 	 *
584 	 * @param atn The ATN.
585 	 */
586 	protected void markPrecedenceDecisions(ATN atn) {
587 		for (ATNState state : atn.states) {
588 			if (!(state instanceof StarLoopEntryState)) {
589 				continue;
590 			}
591 
592 			/* We analyze the ATN to determine if this ATN decision state is the
593 			 * decision for the closure block that determines whether a
594 			 * precedence rule should continue or complete.
595 			 */
596 			if (atn.ruleToStartState[state.ruleIndex].isLeftRecursiveRule) {
597 				ATNState maybeLoopEndState = state.transition(state.getNumberOfTransitions() - 1).target;
598 				if (maybeLoopEndState instanceof LoopEndState) {
599 					if (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transition(0).target instanceof RuleStopState) {
600 						((StarLoopEntryState)state).isPrecedenceDecision = true;
601 					}
602 				}
603 			}
604 		}
605 	}
606 
607 	protected void verifyATN(ATN atn) {
608 		// verify assumptions
609 		for (ATNState state : atn.states) {
610 			if (state == null) {
611 				continue;
612 			}
613 
614 			checkCondition(state.onlyHasEpsilonTransitions() || state.getNumberOfTransitions() <= 1);
615 
616 			if (state instanceof PlusBlockStartState) {
617 				checkCondition(((PlusBlockStartState)state).loopBackState != null);
618 			}
619 
620 			if (state instanceof StarLoopEntryState) {
621 				StarLoopEntryState starLoopEntryState = (StarLoopEntryState)state;
622 				checkCondition(starLoopEntryState.loopBackState != null);
623 				checkCondition(starLoopEntryState.getNumberOfTransitions() == 2);
624 
625 				if (starLoopEntryState.transition(0).target instanceof StarBlockStartState) {
626 					checkCondition(starLoopEntryState.transition(1).target instanceof LoopEndState);
627 					checkCondition(!starLoopEntryState.nonGreedy);
628 				}
629 				else if (starLoopEntryState.transition(0).target instanceof LoopEndState) {
630 					checkCondition(starLoopEntryState.transition(1).target instanceof StarBlockStartState);
631 					checkCondition(starLoopEntryState.nonGreedy);
632 				}
633 				else {
634 					throw new IllegalStateException();
635 				}
636 			}
637 
638 			if (state instanceof StarLoopbackState) {
639 				checkCondition(state.getNumberOfTransitions() == 1);
640 				checkCondition(state.transition(0).target instanceof StarLoopEntryState);
641 			}
642 
643 			if (state instanceof LoopEndState) {
644 				checkCondition(((LoopEndState)state).loopBackState != null);
645 			}
646 
647 			if (state instanceof RuleStartState) {
648 				checkCondition(((RuleStartState)state).stopState != null);
649 			}
650 
651 			if (state instanceof BlockStartState) {
652 				checkCondition(((BlockStartState)state).endState != null);
653 			}
654 
655 			if (state instanceof BlockEndState) {
656 				checkCondition(((BlockEndState)state).startState != null);
657 			}
658 
659 			if (state instanceof DecisionState) {
660 				DecisionState decisionState = (DecisionState)state;
661 				checkCondition(decisionState.getNumberOfTransitions() <= 1 || decisionState.decision >= 0);
662 			}
663 			else {
664 				checkCondition(state.getNumberOfTransitions() <= 1 || state instanceof RuleStopState);
665 			}
666 		}
667 	}
668 
669 	protected void checkCondition(boolean condition) {
670 		checkCondition(condition, null);
671 	}
672 
673 	protected void checkCondition(boolean condition, String message) {
674 		if (!condition) {
675 			throw new IllegalStateException(message);
676 		}
677 	}
678 
679 	protected static int toInt(char c) {
680 		return c;
681 	}
682 
683 	protected static int toInt32(char[] data, int offset) {
684 		return (int)data[offset] | ((int)data[offset + 1] << 16);
685 	}
686 
687 	protected static long toLong(char[] data, int offset) {
688 		long lowOrder = toInt32(data, offset) & 0x00000000FFFFFFFFL;
689 		return lowOrder | ((long)toInt32(data, offset + 2) << 32);
690 	}
691 
692 	protected static UUID toUUID(char[] data, int offset) {
693 		long leastSigBits = toLong(data, offset);
694 		long mostSigBits = toLong(data, offset + 4);
695 		return new UUID(mostSigBits, leastSigBits);
696 	}
697 
698 
699 	protected Transition edgeFactory(ATN atn,
700 										 int type, int src, int trg,
701 										 int arg1, int arg2, int arg3,
702 										 List<IntervalSet> sets)
703 	{
704 		ATNState target = atn.states.get(trg);
705 		switch (type) {
706 			case Transition.EPSILON : return new EpsilonTransition(target);
707 			case Transition.RANGE :
708 				if (arg3 != 0) {
709 					return new RangeTransition(target, Token.EOF, arg2);
710 				}
711 				else {
712 					return new RangeTransition(target, arg1, arg2);
713 				}
714 			case Transition.RULE :
715 				RuleTransition rt = new RuleTransition((RuleStartState)atn.states.get(arg1), arg2, arg3, target);
716 				return rt;
717 			case Transition.PREDICATE :
718 				PredicateTransition pt = new PredicateTransition(target, arg1, arg2, arg3 != 0);
719 				return pt;
720 			case Transition.PRECEDENCE:
721 				return new PrecedencePredicateTransition(target, arg1);
722 			case Transition.ATOM :
723 				if (arg3 != 0) {
724 					return new AtomTransition(target, Token.EOF);
725 				}
726 				else {
727 					return new AtomTransition(target, arg1);
728 				}
729 			case Transition.ACTION :
730 				ActionTransition a = new ActionTransition(target, arg1, arg2, arg3 != 0);
731 				return a;
732 			case Transition.SET : return new SetTransition(target, sets.get(arg1));
733 			case Transition.NOT_SET : return new NotSetTransition(target, sets.get(arg1));
734 			case Transition.WILDCARD : return new WildcardTransition(target);
735 		}
736 
737 		throw new IllegalArgumentException("The specified transition type is not valid.");
738 	}
739 
740 	protected ATNState stateFactory(int type, int ruleIndex) {
741 		ATNState s;
742 		switch (type) {
743 			case ATNState.INVALID_TYPE: return null;
744 			case ATNState.BASIC : s = new BasicState(); break;
745 			case ATNState.RULE_START : s = new RuleStartState(); break;
746 			case ATNState.BLOCK_START : s = new BasicBlockStartState(); break;
747 			case ATNState.PLUS_BLOCK_START : s = new PlusBlockStartState(); break;
748 			case ATNState.STAR_BLOCK_START : s = new StarBlockStartState(); break;
749 			case ATNState.TOKEN_START : s = new TokensStartState(); break;
750 			case ATNState.RULE_STOP : s = new RuleStopState(); break;
751 			case ATNState.BLOCK_END : s = new BlockEndState(); break;
752 			case ATNState.STAR_LOOP_BACK : s = new StarLoopbackState(); break;
753 			case ATNState.STAR_LOOP_ENTRY : s = new StarLoopEntryState(); break;
754 			case ATNState.PLUS_LOOP_BACK : s = new PlusLoopbackState(); break;
755 			case ATNState.LOOP_END : s = new LoopEndState(); break;
756 			default :
757 				String message = String.format(Locale.getDefault(), "The specified state type %d is not valid.", type);
758 				throw new IllegalArgumentException(message);
759 		}
760 
761 		s.ruleIndex = ruleIndex;
762 		return s;
763 	}
764 
765 	protected LexerAction lexerActionFactory(LexerActionType type, int data1, int data2) {
766 		switch (type) {
767 		case CHANNEL:
768 			return new LexerChannelAction(data1);
769 
770 		case CUSTOM:
771 			return new LexerCustomAction(data1, data2);
772 
773 		case MODE:
774 			return new LexerModeAction(data1);
775 
776 		case MORE:
777 			return LexerMoreAction.INSTANCE;
778 
779 		case POP_MODE:
780 			return LexerPopModeAction.INSTANCE;
781 
782 		case PUSH_MODE:
783 			return new LexerPushModeAction(data1);
784 
785 		case SKIP:
786 			return LexerSkipAction.INSTANCE;
787 
788 		case TYPE:
789 			return new LexerTypeAction(data1);
790 
791 		default:
792 			String message = String.format(Locale.getDefault(), "The specified lexer action type %d is not valid.", type);
793 			throw new IllegalArgumentException(message);
794 		}
795 	}
796 }
797