class_docstr: Parser engine.
  
  The proper usage sequence is:
  
  p = Parser(grammar, [converter])  # create instance
  p.setup([start])                  # prepare for parsing
  <for each input token>:
      if p.addtoken(...):           # parse a token; may raise ParseError
          break
  root = p.rootnode                 # root of abstract syntax tree
  
  A Parser instance may be reused by calling setup() repeatedly.
  
  A Parser instance contains state pertaining to the current token
  sequence, and should not be used concurrently by different threads
  to parse separate token sequences.
  
  See driver.py for how to get input tokens by tokenizing a file or
  string.
  
  Parsing is complete when addtoken() returns True; the root of the
  abstract syntax tree can then be retrieved from the rootnode
  instance variable.  When a syntax error occurs, addtoken() raises
  the ParseError exception.  There is no error recovery; the parser
  cannot be used after a syntax error was reported (but it can be
  reinitialized by calling setup()).
class_docstr_tok: ["Parser","engine",".","The","proper","usage","sequence","is",":","p","=","Parser","(","grammar",",","[","converter","]",")","#","create","instance","p.setup","(","[","start","]",")","#","prepare","for","parsing","<","for","each","input","token",">",":","if","p.addtoken","(","...",")",":","#","parse","a","token",";","may","raise","ParseError","break","root","=","p.rootnode","#","root","of","abstract","syntax","tree","A","Parser","instance","may","be","reused","by","calling","setup","(",")","repeatedly",".","A","Parser","instance","contains","state","pertaining","to","the","current","token","sequence",",","and","should","not","be","used","concurrently","by","different","threads","to","parse","separate","token","sequences",".","See","driver.py","for","how","to","get","input","tokens","by","tokenizing","a","file","or","string",".","Parsing","is","complete","when","addtoken","(",")","returns","True",";","the","root","of","the","abstract","syntax","tree","can","then","be","retrieved","from","the","rootnode","instance","variable",".","When","a","syntax","error","occurs",",","addtoken","(",")","raises","the","ParseError","exception",".","There","is","no","error","recovery",";","the","parser","can","not","be","used","after","a","syntax","error","was","reported","(","but","it","can","be","reinitialized","by","calling","setup","(",")",")","."]
code: def _addtoken(
      self, ilabel: int, type: int, value: str, context: Context
  ) -> bool:
      # Loop until the token is shifted; may raise exceptions
      while True:
          dfa, state, node = self.stack[-1]
          states, first = dfa
          arcs = states[state]
          # Look for a state with this label
          for i, newstate in arcs:
              t = self.grammar.labels[i][0]
              if t >= 256:
                  # See if it's a symbol and if we're in its first set
                  itsdfa = self.grammar.dfas[t]
                  itsstates, itsfirst = itsdfa
                  if ilabel in itsfirst:
                      # Push a symbol
                      self.push(t, itsdfa, newstate, context)
                      break  # To continue the outer while loop
  
              elif ilabel == i:
                  # Look it up in the list of labels
                  # Shift a token; we're done with it
                  self.shift(type, value, newstate, context)
                  # Pop while we are in an accept-only state
                  state = newstate
                  while states[state] == [(0, state)]:
                      self.pop()
                      if not self.stack:
                          # Done parsing!
                          return True
                      dfa, state, node = self.stack[-1]
                      states, first = dfa
                  # Done with this token
                  self.last_token = type
                  return False
  
          else:
              if (0, state) in arcs:
                  # An accepting state, pop it and try something else
                  self.pop()
                  if not self.stack:
                      # Done parsing, but another token is input
                      raise ParseError(
                          "too much input", type, value, context
                      )
              else:
                  # No success finding a transition
                  raise ParseError("bad input", type, value, context)
  
imports: from contextlib import contextmanager
  from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Union, cast
  from blib2to3.pgen2.grammar import Grammar
  from blib2to3.pytree import NL, Context, Leaf, Node, RawNode, convert
  from .None import grammar, token, tokenize
label_desc: Use image node_id 4 for calling the Parser obj's underlying member method code with example usage: obj._addtoken(ilabel, type, value, context) and returns: False, True