text: //
  // [The "BSD license"]
  //  Copyright (c) 2012 Terence Parr
  //  Copyright (c) 2012 Sam Harwell
  //  Copyright (c) 2014 Eric Vergnaud
  //  All rights reserved.
  //
  //  Redistribution and use in source and binary forms, with or without
  //  modification, are permitted provided that the following conditions
  //  are met:
  //
  //  1. Redistributions of source code must retain the above copyright
  //     notice, this list of conditions and the following disclaimer.
  //  2. Redistributions in binary form must reproduce the above copyright
  //     notice, this list of conditions and the following disclaimer in the
  //     documentation and/or other materials provided with the distribution.
  //  3. The name of the author may not be used to endorse or promote products
  //     derived from this software without specific prior written permission.
  //
  //  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  //  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  //  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  //  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  //  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  //  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  //  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  //  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  //  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  ///
  
  // When we hit an accept state in either the DFA or the ATN, we
  //  have to notify the character stream to start buffering characters
  //  via {@link IntStream//mark} and record the current state. The current sim state
  //  includes the current index into the input, the current line,
  //  and current character position in that line. Note that the Lexer is
  //  tracking the starting line and characterization of the token. These
  //  variables track the "state" of the simulator when it hits an accept state.
  //
  //  <p>We track these variables separately for the DFA and ATN simulation
  //  because the DFA simulation often has to fail over to the ATN
  //  simulation. If the ATN simulation fails, we need the DFA to fall
  //  back to its previously accepted state, if any. If the ATN succeeds,
  //  then the ATN does the accept and the DFA simulator that invoked it
  //  can simply return the predicted token type.</p>
  ///
  
  var Token = require('./../Token').Token;
  var Lexer = require('./../Lexer').Lexer;
  var ATN = require('./ATN').ATN;
  var ATNSimulator = require('./ATNSimulator').ATNSimulator;
  var DFAState = require('./../dfa/DFAState').DFAState;
  var ATNConfigSet = require('./ATNConfigSet').ATNConfigSet;
  var OrderedATNConfigSet = require('./ATNConfigSet').OrderedATNConfigSet;
  var PredictionContext = require('./../PredictionContext').PredictionContext;
  var SingletonPredictionContext = require('./../PredictionContext').SingletonPredictionContext;
  var RuleStopState = require('./ATNState').RuleStopState;
  var LexerATNConfig = require('./ATNConfig').LexerATNConfig;
  var Transition = require('./Transition').Transition;
  var LexerActionExecutor = require('./LexerActionExecutor').LexerActionExecutor;
  var LexerNoViableAltException = require('./../error/Errors').LexerNoViableAltException;
  
  function resetSimState(sim) {
  	sim.index = -1;
  	sim.line = 0;
  	sim.column = -1;
  	sim.dfaState = null;
  }
  
  function SimState() {
  	resetSimState(this);
  	return this;
  }
  
  SimState.prototype.reset = function() {
  	resetSimState(this);
  };
  
  function LexerATNSimulator(recog, atn, decisionToDFA, sharedContextCache) {
  	ATNSimulator.call(this, atn, sharedContextCache);
  	this.decisionToDFA = decisionToDFA;
  	this.recog = recog;
  	// The current token's starting index into the character stream.
  	// Shared across DFA to ATN simulation in case the ATN fails and the
  	// DFA did not have a previous accept state. In this case, we use the
  	// ATN-generated exception object.
  	this.startIndex = -1;
  	// line number 1..n within the input///
  	this.line = 1;
  	// The index of the character relative to the beginning of the line
  	// 0..n-1///
  	this.column = 0;
  	this.mode = Lexer.DEFAULT_MODE;
  	// Used during DFA/ATN exec to record the most recent accept configuration
  	// info
  	this.prevAccept = new SimState();
  	// done
  	return this;
  }
  
  LexerATNSimulator.prototype = Object.create(ATNSimulator.prototype);
  LexerATNSimulator.prototype.constructor = LexerATNSimulator;
  
  LexerATNSimulator.debug = false;
  LexerATNSimulator.dfa_debug = false;
  
  LexerATNSimulator.MIN_DFA_EDGE = 0;
  LexerATNSimulator.MAX_DFA_EDGE = 127; // forces unicode to stay in ATN
  
  LexerATNSimulator.match_calls = 0;
  
  LexerATNSimulator.prototype.copyState = function(simulator) {
  	this.column = simulator.column;
  	this.line = simulator.line;
  	this.mode = simulator.mode;
  	this.startIndex = simulator.startIndex;
  };
  
  LexerATNSimulator.prototype.match = function(input, mode) {
  	this.match_calls += 1;
  	this.mode = mode;
  	var mark = input.mark();
  	try {
  		this.startIndex = input.index;
  		this.prevAccept.reset();
  		var dfa = this.decisionToDFA[mode];
  		if (dfa.s0 === null) {
  			return this.matchATN(input);
  		} else {
  			return this.execATN(input, dfa.s0);
  		}
  	} finally {
  		input.release(mark);
  	}
  };
  
  LexerATNSimulator.prototype.reset = function() {
  	this.prevAccept.reset();
  	this.startIndex = -1;
  	this.line = 1;
  	this.column = 0;
  	this.mode = Lexer.DEFAULT_MODE;
  };
  
  LexerATNSimulator.prototype.matchATN = function(input) {
  	var startState = this.atn.modeToStartState[this.mode];
  
  	if (this.debug) {
  		console.log("matchATN mode " + this.mode + " start: " + startState);
  	}
  	var old_mode = this.mode;
  	var s0_closure = this.computeStartState(input, startState);
  	var suppressEdge = s0_closure.hasSemanticContext;
  	s0_closure.hasSemanticContext = false;
  
  	var next = this.addDFAState(s0_closure);
  	if (!suppressEdge) {
  		this.decisionToDFA[this.mode].s0 = next;
  	}
  
  	var predict = this.execATN(input, next);
  
  	if (this.debug) {
  		console.log("DFA after matchATN: " + this.decisionToDFA[old_mode].toLexerString());
  	}
  	return predict;
  };
  
  LexerATNSimulator.prototype.execATN = function(input, ds0) {
  	if (this.debug) {
  		console.log("start state closure=" + ds0.configs);
  	}
  	if (ds0.isAcceptState) {
  		// allow zero-length tokens
  		this.captureSimState(this.prevAccept, input, ds0);
  	}
  	var t = input.LA(1);
  	var s = ds0; // s is current/from DFA state
  
  	while (true) { // while more work
  		if (this.debug) {
  			console.log("execATN loop starting closure: " + s.configs);
  		}
  
  		// As we move src->trg, src->trg, we keep track of the previous trg to
  		// avoid looking up the DFA state again, which is expensive.
  		// If the previous target was already part of the DFA, we might
  		// be able to avoid doing a reach operation upon t. If s!=null,
  		// it means that semantic predicates didn't prevent us from
  		// creating a DFA state. Once we know s!=null, we check to see if
  		// the DFA state has an edge already for t. If so, we can just reuse
  		// it's configuration set; there's no point in re-computing it.
  		// This is kind of like doing DFA simulation within the ATN
  		// simulation because DFA simulation is really just a way to avoid
  		// computing reach/closure sets. Technically, once we know that
  		// we have a previously added DFA state, we could jump over to
  		// the DFA simulator. But, that would mean popping back and forth
  		// a lot and making things more complicated algorithmically.
  		// This optimization makes a lot of sense for loops within DFA.
  		// A character will take us back to an existing DFA state
  		// that already has lots of edges out of it. e.g., .* in comments.
  		// print("Target for:" + str(s) + " and:" + str(t))
  		var target = this.getExistingTargetState(s, t);
  		// print("Existing:" + str(target))
  		if (target === null) {
  			target = this.computeTargetState(input, s, t);
  			// print("Computed:" + str(target))
  		}
  		if (target === ATNSimulator.ERROR) {
  			break;
  		}
  		// If this is a consumable input element, make sure to consume before
  		// capturing the accept state so the input index, line, and char
  		// position accurately reflect the state of the interpreter at the
  		// end of the token.
  		if (t !== Token.EOF) {
  			this.consume(input);
  		}
  		if (target.isAcceptState) {
  			this.captureSimState(this.prevAccept, input, target);
  			if (t === Token.EOF) {
  				break;
  			}
  		}
  		t = input.LA(1);
  		s = target; // flip; current DFA target becomes new src/from state
  	}
  	return this.failOrAccept(this.prevAccept, input, s.configs, t);
  };
  
  // Get an existing target state for an edge in the DFA. If the target state
  // for the edge has not yet been computed or is otherwise not available,
  // this method returns {@code null}.
  //
  // @param s The current DFA state
  // @param t The next input symbol
  // @return The existing target DFA state for the given input symbol
  // {@code t}, or {@code null} if the target state for this edge is not
  // already cached
  LexerATNSimulator.prototype.getExistingTargetState = function(s, t) {
  	if (s.edges === null || t < LexerATNSimulator.MIN_DFA_EDGE || t > LexerATNSimulator.MAX_DFA_EDGE) {
  		return null;
  	}
  
  	var target = s.edges[t - LexerATNSimulator.MIN_DFA_EDGE];
  	if(target===undefined) {
  		target = null;
  	}
  	if (this.debug && target !== null) {
  		console.log("reuse state " + s.stateNumber + " edge to " + target.stateNumber);
  	}
  	return target;
  };
  
  // Compute a target state for an edge in the DFA, and attempt to add the
  // computed state and corresponding edge to the DFA.
  //
  // @param input The input stream
  // @param s The current DFA state
  // @param t The next input symbol
  //
  // @return The computed target DFA state for the given input symbol
  // {@code t}. If {@code t} does not lead to a valid DFA state, this method
  // returns {@link //ERROR}.
  LexerATNSimulator.prototype.computeTargetState = function(input, s, t) {
  	var reach = new OrderedATNConfigSet();
  	// if we don't find an existing DFA state
  	// Fill reach starting from closure, following t transitions
  	this.getReachableConfigSet(input, s.configs, reach, t);
  
  	if (reach.items.length === 0) { // we got nowhere on t from s
  		if (!reach.hasSemanticContext) {
  			// we got nowhere on t, don't throw out this knowledge; it'd
  			// cause a failover from DFA later.
  			this.addDFAEdge(s, t, ATNSimulator.ERROR);
  		}
  		// stop when we can't match any more char
  		return ATNSimulator.ERROR;
  	}
  	// Add an edge from s to target DFA found/created for reach
  	return this.addDFAEdge(s, t, null, reach);
  };
  
  LexerATNSimulator.prototype.failOrAccept = function(prevAccept, input, reach, t) {
  	if (this.prevAccept.dfaState !== null) {
  		var lexerActionExecutor = prevAccept.dfaState.lexerActionExecutor;
  		this.accept(input, lexerActionExecutor, this.startIndex,
  				prevAccept.index, prevAccept.line, prevAccept.column);
  		return prevAccept.dfaState.prediction;
  	} else {
  		// if no accept and EOF is first char, return EOF
  		if (t === Token.EOF && input.index === this.startIndex) {
  			return Token.EOF;
  		}
  		throw new LexerNoViableAltException(this.recog, input, this.startIndex, reach);
  	}
  };
  
  // Given a starting configuration set, figure out all ATN configurations
  // we can reach upon input {@code t}. Parameter {@code reach} is a return
  // parameter.
  LexerATNSimulator.prototype.getReachableConfigSet = function(input, closure,
  		reach, t) {
  	// this is used to skip processing for configs which have a lower priority
  	// than a config that already reached an accept state for the same rule
  	var skipAlt = ATN.INVALID_ALT_NUMBER;
  	for (var i = 0; i < closure.items.length; i++) {
  		var cfg = closure.items[i];
  		var currentAltReachedAcceptState = (cfg.alt === skipAlt);
  		if (currentAltReachedAcceptState && cfg.passedThroughNonGreedyDecision) {
  			continue;
  		}
  		if (this.debug) {
  			console.log("testing %s at %s\n", this.getTokenName(t), cfg
  					.toString(this.recog, true));
  		}
  		for (var j = 0; j < cfg.state.transitions.length; j++) {
  			var trans = cfg.state.transitions[j]; // for each transition
  			var target = this.getReachableTarget(trans, t);
  			if (target !== null) {
  				var lexerActionExecutor = cfg.lexerActionExecutor;
  				if (lexerActionExecutor !== null) {
  					lexerActionExecutor = lexerActionExecutor.fixOffsetBeforeMatch(input.index - this.startIndex);
  				}
  				var treatEofAsEpsilon = (t === Token.EOF);
  				var config = new LexerATNConfig({state:target, lexerActionExecutor:lexerActionExecutor}, cfg);
  				if (this.closure(input, config, reach,
  						currentAltReachedAcceptState, true, treatEofAsEpsilon)) {
  					// any remaining configs for this alt have a lower priority
  					// than the one that just reached an accept state.
  					skipAlt = cfg.alt;
  				}
  			}
  		}
  	}
  };
  
  LexerATNSimulator.prototype.accept = function(input, lexerActionExecutor,
  		startIndex, index, line, charPos) {
  	if (this.debug) {
  		console.log("ACTION %s\n", lexerActionExecutor);
  	}
  	// seek to after last char in token
  	input.seek(index);
  	this.line = line;
  	this.column = charPos;
  	if (lexerActionExecutor !== null && this.recog !== null) {
  		lexerActionExecutor.execute(this.recog, input, startIndex);
  	}
  };
  
  LexerATNSimulator.prototype.getReachableTarget = function(trans, t) {
  	if (trans.matches(t, 0, 0xFFFE)) {
  		return trans.target;
  	} else {
  		return null;
  	}
  };
  
  LexerATNSimulator.prototype.computeStartState = function(input, p) {
  	var initialContext = PredictionContext.EMPTY;
  	var configs = new OrderedATNConfigSet();
  	for (var i = 0; i < p.transitions.length; i++) {
  		var target = p.transitions[i].target;
          var cfg = new LexerATNConfig({state:target, alt:i+1, context:initialContext}, null);
  		this.closure(input, cfg, configs, false, false, false);
  	}
  	return configs;
  };
  
  // Since the alternatives within any lexer decision are ordered by
  // preference, this method stops pursuing the closure as soon as an accept
  // state is reached. After the first accept state is reached by depth-first
  // search from {@code config}, all other (potentially reachable) states for
  // this rule would have a lower priority.
  //
  // @return {@code true} if an accept state is reached, otherwise
  // {@code false}.
  LexerATNSimulator.prototype.closure = function(input, config, configs,
  		currentAltReachedAcceptState, speculative, treatEofAsEpsilon) {
  	var cfg = null;
  	if (this.debug) {
  		console.log("closure(" + config.toString(this.recog, true) + ")");
  	}
  	if (config.state instanceof RuleStopState) {
  		if (this.debug) {
  			if (this.recog !== null) {
  				console.log("closure at %s rule stop %s\n", this.recog.getRuleNames()[config.state.ruleIndex], config);
  			} else {
  				console.log("closure at rule stop %s\n", config);
  			}
  		}
  		if (config.context === null || config.context.hasEmptyPath()) {
  			if (config.context === null || config.context.isEmpty()) {
  				configs.add(config);
  				return true;
  			} else {
  				configs.add(new LexerATNConfig({ state:config.state, context:PredictionContext.EMPTY}, config));
  				currentAltReachedAcceptState = true;
  			}
  		}
  		if (config.context !== null && !config.context.isEmpty()) {
  			for (var i = 0; i < config.context.length; i++) {
  				if (config.context.getReturnState(i) !== PredictionContext.EMPTY_RETURN_STATE) {
  					var newContext = config.context.getParent(i); // "pop" return state
  					var returnState = this.atn.states[config.context.getReturnState(i)];
  					cfg = new LexerATNConfig({ state:returnState, context:newContext }, config);
  					currentAltReachedAcceptState = this.closure(input, cfg,
  							configs, currentAltReachedAcceptState, speculative,
  							treatEofAsEpsilon);
  				}
  			}
  		}
  		return currentAltReachedAcceptState;
  	}
  	// optimization
  	if (!config.state.epsilonOnlyTransitions) {
  		if (!currentAltReachedAcceptState || !config.passedThroughNonGreedyDecision) {
  			configs.add(config);
  		}
  	}
  	for (var j = 0; j < config.state.transitions.length; j++) {
  		var trans = config.state.transitions[j];
  		cfg = this.getEpsilonTarget(input, config, trans, configs, speculative, treatEofAsEpsilon);
  		if (cfg !== null) {
  			currentAltReachedAcceptState = this.closure(input, cfg, configs,
  					currentAltReachedAcceptState, speculative, treatEofAsEpsilon);
  		}
  	}
  	return currentAltReachedAcceptState;
  };
  
  // side-effect: can alter configs.hasSemanticContext
  LexerATNSimulator.prototype.getEpsilonTarget = function(input, config, trans,
  		configs, speculative, treatEofAsEpsilon) {
  	var cfg = null;
  	if (trans.serializationType === Transition.RULE) {
  		var newContext = SingletonPredictionContext.create(config.context, trans.followState.stateNumber);
  		cfg = new LexerATNConfig( { state:trans.target, context:newContext}, config);
  	} else if (trans.serializationType === Transition.PRECEDENCE) {
  		throw "Precedence predicates are not supported in lexers.";
  	} else if (trans.serializationType === Transition.PREDICATE) {
  		// Track traversing semantic predicates. If we traverse,
  		// we cannot add a DFA state for this "reach" computation
  		// because the DFA would not test the predicate again in the
  		// future. Rather than creating collections of semantic predicates
  		// like v3 and testing them on prediction, v4 will test them on the
  		// fly all the time using the ATN not the DFA. This is slower but
  		// semantically it's not used that often. One of the key elements to
  		// this predicate mechanism is not adding DFA states that see
  		// predicates immediately afterwards in the ATN. For example,
  
  		// a : ID {p1}? | ID {p2}? ;
  
  		// should create the start state for rule 'a' (to save start state
  		// competition), but should not create target of ID state. The
  		// collection of ATN states the following ID references includes
  		// states reached by traversing predicates. Since this is when we
  		// test them, we cannot cash the DFA state target of ID.
  
  		if (this.debug) {
  			console.log("EVAL rule " + trans.ruleIndex + ":" + trans.predIndex);
  		}
  		configs.hasSemanticContext = true;
  		if (this.evaluatePredicate(input, trans.ruleIndex, trans.predIndex, speculative)) {
  			cfg = new LexerATNConfig({ state:trans.target}, config);
  		}
  	} else if (trans.serializationType === Transition.ACTION) {
  		if (config.context === null || config.context.hasEmptyPath()) {
  			// execute actions anywhere in the start rule for a token.
  			//
  			// TODO: if the entry rule is invoked recursively, some
  			// actions may be executed during the recursive call. The
  			// problem can appear when hasEmptyPath() is true but
  			// isEmpty() is false. In this case, the config needs to be
  			// split into two contexts - one with just the empty path
  			// and another with everything but the empty path.
  			// Unfortunately, the current algorithm does not allow
  			// getEpsilonTarget to return two configurations, so
  			// additional modifications are needed before we can support
  			// the split operation.
  			var lexerActionExecutor = LexerActionExecutor.append(config.lexerActionExecutor,
  					this.atn.lexerActions[trans.actionIndex]);
  			cfg = new LexerATNConfig({ state:trans.target, lexerActionExecutor:lexerActionExecutor }, config);
  		} else {
  			// ignore actions in referenced rules
  			cfg = new LexerATNConfig( { state:trans.target}, config);
  		}
  	} else if (trans.serializationType === Transition.EPSILON) {
  		cfg = new LexerATNConfig({ state:trans.target}, config);
  	} else if (trans.serializationType === Transition.ATOM ||
  				trans.serializationType === Transition.RANGE ||
  				trans.serializationType === Transition.SET) {
  		if (treatEofAsEpsilon) {
  			if (trans.matches(Token.EOF, 0, 0xFFFF)) {
  				cfg = new LexerATNConfig( { state:trans.target }, config);
  			}
  		}
  	}
  	return cfg;
  };
  
  // Evaluate a predicate specified in the lexer.
  //
  // <p>If {@code speculative} is {@code true}, this method was called before
  // {@link //consume} for the matched character. This method should call
  // {@link //consume} before evaluating the predicate to ensure position
  // sensitive values, including {@link Lexer//getText}, {@link Lexer//getLine},
  // and {@link Lexer//getcolumn}, properly reflect the current
  // lexer state. This method should restore {@code input} and the simulator
  // to the original state before returning (i.e. undo the actions made by the
  // call to {@link //consume}.</p>
  //
  // @param input The input stream.
  // @param ruleIndex The rule containing the predicate.
  // @param predIndex The index of the predicate within the rule.
  // @param speculative {@code true} if the current index in {@code input} is
  // one character before the predicate's location.
  //
  // @return {@code true} if the specified predicate evaluates to
  // {@code true}.
  // /
  LexerATNSimulator.prototype.evaluatePredicate = function(input, ruleIndex,
  		predIndex, speculative) {
  	// assume true if no recognizer was provided
  	if (this.recog === null) {
  		return true;
  	}
  	if (!speculative) {
  		return this.recog.sempred(null, ruleIndex, predIndex);
  	}
  	var savedcolumn = this.column;
  	var savedLine = this.line;
  	var index = input.index;
  	var marker = input.mark();
  	try {
  		this.consume(input);
  		return this.recog.sempred(null, ruleIndex, predIndex);
  	} finally {
  		this.column = savedcolumn;
  		this.line = savedLine;
  		input.seek(index);
  		input.release(marker);
  	}
  };
  
  LexerATNSimulator.prototype.captureSimState = function(settings, input, dfaState) {
  	settings.index = input.index;
  	settings.line = this.line;
  	settings.column = this.column;
  	settings.dfaState = dfaState;
  };
  
  LexerATNSimulator.prototype.addDFAEdge = function(from_, tk, to, cfgs) {
  	if (to === undefined) {
  		to = null;
  	}
  	if (cfgs === undefined) {
  		cfgs = null;
  	}
  	if (to === null && cfgs !== null) {
  		// leading to this call, ATNConfigSet.hasSemanticContext is used as a
  		// marker indicating dynamic predicate evaluation makes this edge
  		// dependent on the specific input sequence, so the static edge in the
  		// DFA should be omitted. The target DFAState is still created since
  		// execATN has the ability to resynchronize with the DFA state cache
  		// following the predicate evaluation step.
  		//
  		// TJP notes: next time through the DFA, we see a pred again and eval.
  		// If that gets us to a previously created (but dangling) DFA
  		// state, we can continue in pure DFA mode from there.
  		// /
  		var suppressEdge = cfgs.hasSemanticContext;
  		cfgs.hasSemanticContext = false;
  
  		to = this.addDFAState(cfgs);
  
  		if (suppressEdge) {
  			return to;
  		}
  	}
  	// add the edge
  	if (tk < LexerATNSimulator.MIN_DFA_EDGE || tk > LexerATNSimulator.MAX_DFA_EDGE) {
  		// Only track edges within the DFA bounds
  		return to;
  	}
  	if (this.debug) {
  		console.log("EDGE " + from_ + " -> " + to + " upon " + tk);
  	}
  	if (from_.edges === null) {
  		// make room for tokens 1..n and -1 masquerading as index 0
  		from_.edges = [];
  	}
  	from_.edges[tk - LexerATNSimulator.MIN_DFA_EDGE] = to; // connect
  
  	return to;
  };
  
  // Add a new DFA state if there isn't one with this set of
  // configurations already. This method also detects the first
  // configuration containing an ATN rule stop state. Later, when
  // traversing the DFA, we will know which rule to accept.
  LexerATNSimulator.prototype.addDFAState = function(configs) {
  	var proposed = new DFAState(null, configs);
  	var firstConfigWithRuleStopState = null;
  	for (var i = 0; i < configs.items.length; i++) {
  		var cfg = configs.items[i];
  		if (cfg.state instanceof RuleStopState) {
  			firstConfigWithRuleStopState = cfg;
  			break;
  		}
  	}
  	if (firstConfigWithRuleStopState !== null) {
  		proposed.isAcceptState = true;
  		proposed.lexerActionExecutor = firstConfigWithRuleStopState.lexerActionExecutor;
  		proposed.prediction = this.atn.ruleToTokenType[firstConfigWithRuleStopState.state.ruleIndex];
  	}
  	var hash = proposed.hashString();
  	var dfa = this.decisionToDFA[this.mode];
  	var existing = dfa.states[hash] || null;
  	if (existing!==null) {
  		return existing;
  	}
  	var newState = proposed;
  	newState.stateNumber = dfa.states.length;
  	configs.setReadonly(true);
  	newState.configs = configs;
  	dfa.states[hash] = newState;
  	return newState;
  };
  
  LexerATNSimulator.prototype.getDFA = function(mode) {
  	return this.decisionToDFA[mode];
  };
  
  // Get the text matched so far for the current token.
  LexerATNSimulator.prototype.getText = function(input) {
  	// index is first lookahead char, don't include.
  	return input.getText(this.startIndex, input.index - 1);
  };
  
  LexerATNSimulator.prototype.consume = function(input) {
  	var curChar = input.LA(1);
  	if (curChar === "\n".charCodeAt(0)) {
  		this.line += 1;
  		this.column = 0;
  	} else {
  		this.column += 1;
  	}
  	input.consume();
  };
  
  LexerATNSimulator.prototype.getTokenName = function(tt) {
  	if (tt === -1) {
  		return "EOF";
  	} else {
  		return "'" + String.fromCharCode(tt) + "'";
  	}
  };
  
  exports.LexerATNSimulator = LexerATNSimulator;
  