def execATN(self, input: InputStream, ds0: DFAState): if self.debug: print("start state closure=" + str(ds0.configs)) if ds0.isAcceptState: # allow zero-length tokens self.captureSimState(self.prevAccept, input, ds0) t = input.LA(1) s = ds0 # s is current/from DFA state while True: # while more work if self.debug: print("execATN loop starting closure: %s\n", 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)) target = self.getExistingTargetState(s, t) # print("Existing:" + str(target)) if target is None: target = self.computeTargetState(input, s, t) # print("Computed:" + str(target)) if target == self.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: self.consume(input) if target.isAcceptState: self.captureSimState(self.prevAccept, input, target) if t == Token.EOF: break t = input.LA(1) s = target # flip; current DFA target becomes new src/from state return self.failOrAccept(self.prevAccept, input, s.configs, t)
def testStream(self): stream = InputStream("abcde") self.assertEqual(0, stream.index) self.assertEqual(5, stream.size) self.assertEqual(ord("a"), stream.LA(1)) stream.consume() self.assertEqual(1, stream.index) stream.seek(5) self.assertEqual(Token.EOF, stream.LA(1)) self.assertEqual("bcd", stream.getText(1, 3)) stream.reset() self.assertEqual(0, stream.index)
def consume(self, input: InputStream): curChar = input.LA(1) if curChar == ord('\n'): self.line += 1 self.column = 0 else: self.column += 1 input.consume()
def accept(self, input: InputStream, lexerActionExecutor: LexerActionExecutor, startIndex: int, index: int, line: int, charPos: int): if self.debug: print("ACTION %s\n", lexerActionExecutor) # seek to after last char in token input.seek(index) self.line = line self.column = charPos if input.LA(1) != Token.EOF: self.consume(input) if lexerActionExecutor is not None and self.recog is not None: lexerActionExecutor.execute(self.recog, input, startIndex)