1 /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
2 * Use of this file is governed by the BSD 3-clause license that
3 * can be found in the LICENSE.txt file in the project root.
4 */
5
6 #include "IntStream.h"
7 #include "atn/OrderedATNConfigSet.h"
8 #include "Token.h"
9 #include "LexerNoViableAltException.h"
10 #include "atn/RuleStopState.h"
11 #include "atn/RuleTransition.h"
12 #include "atn/SingletonPredictionContext.h"
13 #include "atn/PredicateTransition.h"
14 #include "atn/ActionTransition.h"
15 #include "atn/TokensStartState.h"
16 #include "misc/Interval.h"
17 #include "dfa/DFA.h"
18 #include "Lexer.h"
19
20 #include "dfa/DFAState.h"
21 #include "atn/LexerATNConfig.h"
22 #include "atn/LexerActionExecutor.h"
23 #include "atn/EmptyPredictionContext.h"
24
25 #include "atn/LexerATNSimulator.h"
26
27 #define DEBUG_ATN 0
28 #define DEBUG_DFA 0
29
30 using namespace antlr4;
31 using namespace antlr4::atn;
32 using namespace antlrcpp;
33
~SimState()34 LexerATNSimulator::SimState::~SimState() {
35 }
36
reset()37 void LexerATNSimulator::SimState::reset() {
38 index = INVALID_INDEX;
39 line = 0;
40 charPos = INVALID_INDEX;
41 dfaState = nullptr; // Don't delete. It's just a reference.
42 }
43
InitializeInstanceFields()44 void LexerATNSimulator::SimState::InitializeInstanceFields() {
45 index = INVALID_INDEX;
46 line = 0;
47 charPos = INVALID_INDEX;
48 }
49
50 std::atomic<int> LexerATNSimulator::match_calls(0);
51
52
LexerATNSimulator(const ATN & atn,std::vector<dfa::DFA> & decisionToDFA,PredictionContextCache & sharedContextCache)53 LexerATNSimulator::LexerATNSimulator(const ATN &atn, std::vector<dfa::DFA> &decisionToDFA,
54 PredictionContextCache &sharedContextCache)
55 : LexerATNSimulator(nullptr, atn, decisionToDFA, sharedContextCache) {
56 }
57
LexerATNSimulator(Lexer * recog,const ATN & atn,std::vector<dfa::DFA> & decisionToDFA,PredictionContextCache & sharedContextCache)58 LexerATNSimulator::LexerATNSimulator(Lexer *recog, const ATN &atn, std::vector<dfa::DFA> &decisionToDFA,
59 PredictionContextCache &sharedContextCache)
60 : ATNSimulator(atn, sharedContextCache), _recog(recog), _decisionToDFA(decisionToDFA) {
61 InitializeInstanceFields();
62 }
63
copyState(LexerATNSimulator * simulator)64 void LexerATNSimulator::copyState(LexerATNSimulator *simulator) {
65 _charPositionInLine = simulator->_charPositionInLine;
66 _line = simulator->_line;
67 _mode = simulator->_mode;
68 _startIndex = simulator->_startIndex;
69 }
70
match(CharStream * input,size_t mode)71 size_t LexerATNSimulator::match(CharStream *input, size_t mode) {
72 match_calls.fetch_add(1, std::memory_order_relaxed);
73 _mode = mode;
74 ssize_t mark = input->mark();
75
76 auto onExit = finally([input, mark] {
77 input->release(mark);
78 });
79
80 _startIndex = input->index();
81 _prevAccept.reset();
82 const dfa::DFA &dfa = _decisionToDFA[mode];
83 if (dfa.s0 == nullptr) {
84 return matchATN(input);
85 } else {
86 return execATN(input, dfa.s0);
87 }
88 }
89
reset()90 void LexerATNSimulator::reset() {
91 _prevAccept.reset();
92 _startIndex = 0;
93 _line = 1;
94 _charPositionInLine = 0;
95 _mode = Lexer::DEFAULT_MODE;
96 }
97
clearDFA()98 void LexerATNSimulator::clearDFA() {
99 size_t size = _decisionToDFA.size();
100 _decisionToDFA.clear();
101 for (size_t d = 0; d < size; ++d) {
102 _decisionToDFA.emplace_back(atn.getDecisionState(d), d);
103 }
104 }
105
matchATN(CharStream * input)106 size_t LexerATNSimulator::matchATN(CharStream *input) {
107 ATNState *startState = atn.modeToStartState[_mode];
108
109 std::unique_ptr<ATNConfigSet> s0_closure = computeStartState(input, startState);
110
111 bool suppressEdge = s0_closure->hasSemanticContext;
112 s0_closure->hasSemanticContext = false;
113
114 dfa::DFAState *next = addDFAState(s0_closure.release());
115 if (!suppressEdge) {
116 _decisionToDFA[_mode].s0 = next;
117 }
118
119 size_t predict = execATN(input, next);
120
121 return predict;
122 }
123
execATN(CharStream * input,dfa::DFAState * ds0)124 size_t LexerATNSimulator::execATN(CharStream *input, dfa::DFAState *ds0) {
125 if (ds0->isAcceptState) {
126 // allow zero-length tokens
127 // ml: in Java code this method uses 3 params. The first is a member var of the class anyway (_prevAccept), so why pass it here?
128 captureSimState(input, ds0);
129 }
130
131 size_t t = input->LA(1);
132 dfa::DFAState *s = ds0; // s is current/from DFA state
133
134 while (true) { // while more work
135 // As we move src->trg, src->trg, we keep track of the previous trg to
136 // avoid looking up the DFA state again, which is expensive.
137 // If the previous target was already part of the DFA, we might
138 // be able to avoid doing a reach operation upon t. If s!=null,
139 // it means that semantic predicates didn't prevent us from
140 // creating a DFA state. Once we know s!=null, we check to see if
141 // the DFA state has an edge already for t. If so, we can just reuse
142 // it's configuration set; there's no point in re-computing it.
143 // This is kind of like doing DFA simulation within the ATN
144 // simulation because DFA simulation is really just a way to avoid
145 // computing reach/closure sets. Technically, once we know that
146 // we have a previously added DFA state, we could jump over to
147 // the DFA simulator. But, that would mean popping back and forth
148 // a lot and making things more complicated algorithmically.
149 // This optimization makes a lot of sense for loops within DFA.
150 // A character will take us back to an existing DFA state
151 // that already has lots of edges out of it. e.g., .* in comments.
152 dfa::DFAState *target = getExistingTargetState(s, t);
153 if (target == nullptr) {
154 target = computeTargetState(input, s, t);
155 }
156
157 if (target == ERROR.get()) {
158 break;
159 }
160
161 // If this is a consumable input element, make sure to consume before
162 // capturing the accept state so the input index, line, and char
163 // position accurately reflect the state of the interpreter at the
164 // end of the token.
165 if (t != Token::EOF) {
166 consume(input);
167 }
168
169 if (target->isAcceptState) {
170 captureSimState(input, target);
171 if (t == Token::EOF) {
172 break;
173 }
174 }
175
176 t = input->LA(1);
177 s = target; // flip; current DFA target becomes new src/from state
178 }
179
180 return failOrAccept(input, s->configs.get(), t);
181 }
182
getExistingTargetState(dfa::DFAState * s,size_t t)183 dfa::DFAState *LexerATNSimulator::getExistingTargetState(dfa::DFAState *s, size_t t) {
184 dfa::DFAState* retval = nullptr;
185 _edgeLock.readLock();
186 if (t <= MAX_DFA_EDGE) {
187 auto iterator = s->edges.find(t - MIN_DFA_EDGE);
188 #if DEBUG_ATN == 1
189 if (iterator != s->edges.end()) {
190 std::cout << std::string("reuse state ") << s->stateNumber << std::string(" edge to ") << iterator->second->stateNumber << std::endl;
191 }
192 #endif
193
194 if (iterator != s->edges.end())
195 retval = iterator->second;
196 }
197 _edgeLock.readUnlock();
198 return retval;
199 }
200
computeTargetState(CharStream * input,dfa::DFAState * s,size_t t)201 dfa::DFAState *LexerATNSimulator::computeTargetState(CharStream *input, dfa::DFAState *s, size_t t) {
202 OrderedATNConfigSet *reach = new OrderedATNConfigSet(); /* mem-check: deleted on error or managed by new DFA state. */
203
204 // if we don't find an existing DFA state
205 // Fill reach starting from closure, following t transitions
206 getReachableConfigSet(input, s->configs.get(), reach, t);
207
208 if (reach->isEmpty()) { // we got nowhere on t from s
209 if (!reach->hasSemanticContext) {
210 // we got nowhere on t, don't throw out this knowledge; it'd
211 // cause a failover from DFA later.
212 delete reach;
213 addDFAEdge(s, t, ERROR.get());
214 }
215
216 // stop when we can't match any more char
217 return ERROR.get();
218 }
219
220 // Add an edge from s to target DFA found/created for reach
221 return addDFAEdge(s, t, reach);
222 }
223
failOrAccept(CharStream * input,ATNConfigSet * reach,size_t t)224 size_t LexerATNSimulator::failOrAccept(CharStream *input, ATNConfigSet *reach, size_t t) {
225 if (_prevAccept.dfaState != nullptr) {
226 Ref<LexerActionExecutor> lexerActionExecutor = _prevAccept.dfaState->lexerActionExecutor;
227 accept(input, lexerActionExecutor, _startIndex, _prevAccept.index, _prevAccept.line, _prevAccept.charPos);
228 return _prevAccept.dfaState->prediction;
229 } else {
230 // if no accept and EOF is first char, return EOF
231 if (t == Token::EOF && input->index() == _startIndex) {
232 return Token::EOF;
233 }
234
235 throw LexerNoViableAltException(_recog, input, _startIndex, reach);
236 }
237 }
238
getReachableConfigSet(CharStream * input,ATNConfigSet * closure_,ATNConfigSet * reach,size_t t)239 void LexerATNSimulator::getReachableConfigSet(CharStream *input, ATNConfigSet *closure_, ATNConfigSet *reach, size_t t) {
240 // this is used to skip processing for configs which have a lower priority
241 // than a config that already reached an accept state for the same rule
242 size_t skipAlt = ATN::INVALID_ALT_NUMBER;
243
244 for (auto c : closure_->configs) {
245 bool currentAltReachedAcceptState = c->alt == skipAlt;
246 if (currentAltReachedAcceptState && (std::static_pointer_cast<LexerATNConfig>(c))->hasPassedThroughNonGreedyDecision()) {
247 continue;
248 }
249
250 #if DEBUG_ATN == 1
251 std::cout << "testing " << getTokenName((int)t) << " at " << c->toString(true) << std::endl;
252 #endif
253
254 size_t n = c->state->transitions.size();
255 for (size_t ti = 0; ti < n; ti++) { // for each transition
256 Transition *trans = c->state->transitions[ti];
257 ATNState *target = getReachableTarget(trans, (int)t);
258 if (target != nullptr) {
259 Ref<LexerActionExecutor> lexerActionExecutor = std::static_pointer_cast<LexerATNConfig>(c)->getLexerActionExecutor();
260 if (lexerActionExecutor != nullptr) {
261 lexerActionExecutor = lexerActionExecutor->fixOffsetBeforeMatch((int)input->index() - (int)_startIndex);
262 }
263
264 bool treatEofAsEpsilon = t == Token::EOF;
265 Ref<LexerATNConfig> config = std::make_shared<LexerATNConfig>(std::static_pointer_cast<LexerATNConfig>(c),
266 target, lexerActionExecutor);
267
268 if (closure(input, config, reach, currentAltReachedAcceptState, true, treatEofAsEpsilon)) {
269 // any remaining configs for this alt have a lower priority than
270 // the one that just reached an accept state.
271 skipAlt = c->alt;
272 break;
273 }
274 }
275 }
276 }
277 }
278
accept(CharStream * input,const Ref<LexerActionExecutor> & lexerActionExecutor,size_t,size_t index,size_t line,size_t charPos)279 void LexerATNSimulator::accept(CharStream *input, const Ref<LexerActionExecutor> &lexerActionExecutor, size_t /*startIndex*/,
280 size_t index, size_t line, size_t charPos) {
281 #if DEBUG_ATN == 1
282 std::cout << "ACTION ";
283 std::cout << toString(lexerActionExecutor) << std::endl;
284 #endif
285
286 // seek to after last char in token
287 input->seek(index);
288 _line = line;
289 _charPositionInLine = (int)charPos;
290
291 if (lexerActionExecutor != nullptr && _recog != nullptr) {
292 lexerActionExecutor->execute(_recog, input, _startIndex);
293 }
294 }
295
getReachableTarget(Transition * trans,size_t t)296 atn::ATNState *LexerATNSimulator::getReachableTarget(Transition *trans, size_t t) {
297 if (trans->matches(t, Lexer::MIN_CHAR_VALUE, Lexer::MAX_CHAR_VALUE)) {
298 return trans->target;
299 }
300
301 return nullptr;
302 }
303
computeStartState(CharStream * input,ATNState * p)304 std::unique_ptr<ATNConfigSet> LexerATNSimulator::computeStartState(CharStream *input, ATNState *p) {
305 Ref<PredictionContext> initialContext = PredictionContext::EMPTY; // ml: the purpose of this assignment is unclear
306 std::unique_ptr<ATNConfigSet> configs(new OrderedATNConfigSet());
307 for (size_t i = 0; i < p->transitions.size(); i++) {
308 ATNState *target = p->transitions[i]->target;
309 Ref<LexerATNConfig> c = std::make_shared<LexerATNConfig>(target, (int)(i + 1), initialContext);
310 closure(input, c, configs.get(), false, false, false);
311 }
312
313 return configs;
314 }
315
closure(CharStream * input,const Ref<LexerATNConfig> & config,ATNConfigSet * configs,bool currentAltReachedAcceptState,bool speculative,bool treatEofAsEpsilon)316 bool LexerATNSimulator::closure(CharStream *input, const Ref<LexerATNConfig> &config, ATNConfigSet *configs,
317 bool currentAltReachedAcceptState, bool speculative, bool treatEofAsEpsilon) {
318 #if DEBUG_ATN == 1
319 std::cout << "closure(" << config->toString(true) << ")" << std::endl;
320 #endif
321
322 if (is<RuleStopState *>(config->state)) {
323 #if DEBUG_ATN == 1
324 if (_recog != nullptr) {
325 std::cout << "closure at " << _recog->getRuleNames()[config->state->ruleIndex] << " rule stop " << config << std::endl;
326 } else {
327 std::cout << "closure at rule stop " << config << std::endl;
328 }
329 #endif
330
331 if (config->context == nullptr || config->context->hasEmptyPath()) {
332 if (config->context == nullptr || config->context->isEmpty()) {
333 configs->add(config);
334 return true;
335 } else {
336 configs->add(std::make_shared<LexerATNConfig>(config, config->state, PredictionContext::EMPTY));
337 currentAltReachedAcceptState = true;
338 }
339 }
340
341 if (config->context != nullptr && !config->context->isEmpty()) {
342 for (size_t i = 0; i < config->context->size(); i++) {
343 if (config->context->getReturnState(i) != PredictionContext::EMPTY_RETURN_STATE) {
344 std::weak_ptr<PredictionContext> newContext = config->context->getParent(i); // "pop" return state
345 ATNState *returnState = atn.states[config->context->getReturnState(i)];
346 Ref<LexerATNConfig> c = std::make_shared<LexerATNConfig>(config, returnState, newContext.lock());
347 currentAltReachedAcceptState = closure(input, c, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon);
348 }
349 }
350 }
351
352 return currentAltReachedAcceptState;
353 }
354
355 // optimization
356 if (!config->state->epsilonOnlyTransitions) {
357 if (!currentAltReachedAcceptState || !config->hasPassedThroughNonGreedyDecision()) {
358 configs->add(config);
359 }
360 }
361
362 ATNState *p = config->state;
363 for (size_t i = 0; i < p->transitions.size(); i++) {
364 Transition *t = p->transitions[i];
365 Ref<LexerATNConfig> c = getEpsilonTarget(input, config, t, configs, speculative, treatEofAsEpsilon);
366 if (c != nullptr) {
367 currentAltReachedAcceptState = closure(input, c, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon);
368 }
369 }
370
371 return currentAltReachedAcceptState;
372 }
373
getEpsilonTarget(CharStream * input,const Ref<LexerATNConfig> & config,Transition * t,ATNConfigSet * configs,bool speculative,bool treatEofAsEpsilon)374 Ref<LexerATNConfig> LexerATNSimulator::getEpsilonTarget(CharStream *input, const Ref<LexerATNConfig> &config, Transition *t,
375 ATNConfigSet *configs, bool speculative, bool treatEofAsEpsilon) {
376
377 Ref<LexerATNConfig> c = nullptr;
378 switch (t->getSerializationType()) {
379 case Transition::RULE: {
380 RuleTransition *ruleTransition = static_cast<RuleTransition*>(t);
381 Ref<PredictionContext> newContext = SingletonPredictionContext::create(config->context, ruleTransition->followState->stateNumber);
382 c = std::make_shared<LexerATNConfig>(config, t->target, newContext);
383 break;
384 }
385
386 case Transition::PRECEDENCE:
387 throw UnsupportedOperationException("Precedence predicates are not supported in lexers.");
388
389 case Transition::PREDICATE: {
390 /* Track traversing semantic predicates. If we traverse,
391 we cannot add a DFA state for this "reach" computation
392 because the DFA would not test the predicate again in the
393 future. Rather than creating collections of semantic predicates
394 like v3 and testing them on prediction, v4 will test them on the
395 fly all the time using the ATN not the DFA. This is slower but
396 semantically it's not used that often. One of the key elements to
397 this predicate mechanism is not adding DFA states that see
398 predicates immediately afterwards in the ATN. For example,
399
400 a : ID {p1}? | ID {p2}? ;
401
402 should create the start state for rule 'a' (to save start state
403 competition), but should not create target of ID state. The
404 collection of ATN states the following ID references includes
405 states reached by traversing predicates. Since this is when we
406 test them, we cannot cash the DFA state target of ID.
407 */
408 PredicateTransition *pt = static_cast<PredicateTransition*>(t);
409
410 #if DEBUG_ATN == 1
411 std::cout << "EVAL rule " << pt->ruleIndex << ":" << pt->predIndex << std::endl;
412 #endif
413
414 configs->hasSemanticContext = true;
415 if (evaluatePredicate(input, pt->ruleIndex, pt->predIndex, speculative)) {
416 c = std::make_shared<LexerATNConfig>(config, t->target);
417 }
418 break;
419 }
420
421 case Transition::ACTION:
422 if (config->context == nullptr|| config->context->hasEmptyPath()) {
423 // execute actions anywhere in the start rule for a token.
424 //
425 // TODO: if the entry rule is invoked recursively, some
426 // actions may be executed during the recursive call. The
427 // problem can appear when hasEmptyPath() is true but
428 // isEmpty() is false. In this case, the config needs to be
429 // split into two contexts - one with just the empty path
430 // and another with everything but the empty path.
431 // Unfortunately, the current algorithm does not allow
432 // getEpsilonTarget to return two configurations, so
433 // additional modifications are needed before we can support
434 // the split operation.
435 Ref<LexerActionExecutor> lexerActionExecutor = LexerActionExecutor::append(config->getLexerActionExecutor(),
436 atn.lexerActions[static_cast<ActionTransition *>(t)->actionIndex]);
437 c = std::make_shared<LexerATNConfig>(config, t->target, lexerActionExecutor);
438 break;
439 }
440 else {
441 // ignore actions in referenced rules
442 c = std::make_shared<LexerATNConfig>(config, t->target);
443 break;
444 }
445
446 case Transition::EPSILON:
447 c = std::make_shared<LexerATNConfig>(config, t->target);
448 break;
449
450 case Transition::ATOM:
451 case Transition::RANGE:
452 case Transition::SET:
453 if (treatEofAsEpsilon) {
454 if (t->matches(Token::EOF, Lexer::MIN_CHAR_VALUE, Lexer::MAX_CHAR_VALUE)) {
455 c = std::make_shared<LexerATNConfig>(config, t->target);
456 break;
457 }
458 }
459
460 break;
461
462 default: // To silence the compiler. Other transition types are not used here.
463 break;
464 }
465
466 return c;
467 }
468
evaluatePredicate(CharStream * input,size_t ruleIndex,size_t predIndex,bool speculative)469 bool LexerATNSimulator::evaluatePredicate(CharStream *input, size_t ruleIndex, size_t predIndex, bool speculative) {
470 // assume true if no recognizer was provided
471 if (_recog == nullptr) {
472 return true;
473 }
474
475 if (!speculative) {
476 return _recog->sempred(nullptr, ruleIndex, predIndex);
477 }
478
479 size_t savedCharPositionInLine = _charPositionInLine;
480 size_t savedLine = _line;
481 size_t index = input->index();
482 ssize_t marker = input->mark();
483
484 auto onExit = finally([this, input, savedCharPositionInLine, savedLine, index, marker] {
485 _charPositionInLine = savedCharPositionInLine;
486 _line = savedLine;
487 input->seek(index);
488 input->release(marker);
489 });
490
491 consume(input);
492 return _recog->sempred(nullptr, ruleIndex, predIndex);
493 }
494
captureSimState(CharStream * input,dfa::DFAState * dfaState)495 void LexerATNSimulator::captureSimState(CharStream *input, dfa::DFAState *dfaState) {
496 _prevAccept.index = input->index();
497 _prevAccept.line = _line;
498 _prevAccept.charPos = _charPositionInLine;
499 _prevAccept.dfaState = dfaState;
500 }
501
addDFAEdge(dfa::DFAState * from,size_t t,ATNConfigSet * q)502 dfa::DFAState *LexerATNSimulator::addDFAEdge(dfa::DFAState *from, size_t t, ATNConfigSet *q) {
503 /* leading to this call, ATNConfigSet.hasSemanticContext is used as a
504 * marker indicating dynamic predicate evaluation makes this edge
505 * dependent on the specific input sequence, so the static edge in the
506 * DFA should be omitted. The target DFAState is still created since
507 * execATN has the ability to resynchronize with the DFA state cache
508 * following the predicate evaluation step.
509 *
510 * TJP notes: next time through the DFA, we see a pred again and eval.
511 * If that gets us to a previously created (but dangling) DFA
512 * state, we can continue in pure DFA mode from there.
513 */
514 bool suppressEdge = q->hasSemanticContext;
515 q->hasSemanticContext = false;
516
517 dfa::DFAState *to = addDFAState(q);
518
519 if (suppressEdge) {
520 return to;
521 }
522
523 addDFAEdge(from, t, to);
524 return to;
525 }
526
addDFAEdge(dfa::DFAState * p,size_t t,dfa::DFAState * q)527 void LexerATNSimulator::addDFAEdge(dfa::DFAState *p, size_t t, dfa::DFAState *q) {
528 if (/*t < MIN_DFA_EDGE ||*/ t > MAX_DFA_EDGE) { // MIN_DFA_EDGE is 0
529 // Only track edges within the DFA bounds
530 return;
531 }
532
533 _edgeLock.writeLock();
534 p->edges[t - MIN_DFA_EDGE] = q; // connect
535 _edgeLock.writeUnlock();
536 }
537
addDFAState(ATNConfigSet * configs)538 dfa::DFAState *LexerATNSimulator::addDFAState(ATNConfigSet *configs) {
539 /* the lexer evaluates predicates on-the-fly; by this point configs
540 * should not contain any configurations with unevaluated predicates.
541 */
542 assert(!configs->hasSemanticContext);
543
544 dfa::DFAState *proposed = new dfa::DFAState(std::unique_ptr<ATNConfigSet>(configs)); /* mem-check: managed by the DFA or deleted below */
545 Ref<ATNConfig> firstConfigWithRuleStopState = nullptr;
546 for (auto &c : configs->configs) {
547 if (is<RuleStopState *>(c->state)) {
548 firstConfigWithRuleStopState = c;
549 break;
550 }
551 }
552
553 if (firstConfigWithRuleStopState != nullptr) {
554 proposed->isAcceptState = true;
555 proposed->lexerActionExecutor = std::dynamic_pointer_cast<LexerATNConfig>(firstConfigWithRuleStopState)->getLexerActionExecutor();
556 proposed->prediction = atn.ruleToTokenType[firstConfigWithRuleStopState->state->ruleIndex];
557 }
558
559 dfa::DFA &dfa = _decisionToDFA[_mode];
560
561 _stateLock.writeLock();
562 if (!dfa.states.empty()) {
563 auto iterator = dfa.states.find(proposed);
564 if (iterator != dfa.states.end()) {
565 delete proposed;
566 _stateLock.writeUnlock();
567 return *iterator;
568 }
569 }
570
571 proposed->stateNumber = (int)dfa.states.size();
572 proposed->configs->setReadonly(true);
573
574 dfa.states.insert(proposed);
575 _stateLock.writeUnlock();
576
577 return proposed;
578 }
579
getDFA(size_t mode)580 dfa::DFA& LexerATNSimulator::getDFA(size_t mode) {
581 return _decisionToDFA[mode];
582 }
583
getText(CharStream * input)584 std::string LexerATNSimulator::getText(CharStream *input) {
585 // index is first lookahead char, don't include.
586 return input->getText(misc::Interval(_startIndex, input->index() - 1));
587 }
588
getLine() const589 size_t LexerATNSimulator::getLine() const {
590 return _line;
591 }
592
setLine(size_t line)593 void LexerATNSimulator::setLine(size_t line) {
594 _line = line;
595 }
596
getCharPositionInLine()597 size_t LexerATNSimulator::getCharPositionInLine() {
598 return _charPositionInLine;
599 }
600
setCharPositionInLine(size_t charPositionInLine)601 void LexerATNSimulator::setCharPositionInLine(size_t charPositionInLine) {
602 _charPositionInLine = charPositionInLine;
603 }
604
consume(CharStream * input)605 void LexerATNSimulator::consume(CharStream *input) {
606 size_t curChar = input->LA(1);
607 if (curChar == '\n') {
608 _line++;
609 _charPositionInLine = 0;
610 } else {
611 _charPositionInLine++;
612 }
613 input->consume();
614 }
615
getTokenName(size_t t)616 std::string LexerATNSimulator::getTokenName(size_t t) {
617 if (t == Token::EOF) {
618 return "EOF";
619 }
620 return std::string("'") + static_cast<char>(t) + std::string("'");
621 }
622
InitializeInstanceFields()623 void LexerATNSimulator::InitializeInstanceFields() {
624 _startIndex = 0;
625 _line = 1;
626 _charPositionInLine = 0;
627 _mode = antlr4::Lexer::DEFAULT_MODE;
628 }
629