docstr: Parse a series of tokens and return the syntax tree.
docstr_tok: ["Parse","a","series","of","tokens","and","return","the","syntax","tree","."]
code: def parse_tokens(
      self, tokens: Iterable[GoodTokenInfo], debug: bool = False
  ) -> NL:
      """Parse a series of tokens and return the syntax tree."""
      # XXX Move the prefix computation into a wrapper around tokenize.
      proxy = TokenProxy(tokens)
  
      p = parse.Parser(self.grammar)
      p.setup(proxy=proxy)
  
      lineno = 1
      column = 0
      indent_columns: List[int] = []
      type = value = start = end = line_text = None
      prefix = ""
  
      for quintuple in proxy:
          type, value, start, end, line_text = quintuple
          if start != (lineno, column):
              assert (lineno, column) <= start, (
                  (lineno, column),
                  start,
              )
              s_lineno, s_column = start
              if lineno < s_lineno:
                  prefix += "\n" * (s_lineno - lineno)
                  lineno = s_lineno
                  column = 0
              if column < s_column:
                  prefix += line_text[column:s_column]
                  column = s_column
          if type in (tokenize.COMMENT, tokenize.NL):
              prefix += value
              lineno, column = end
              if value.endswith("\n"):
                  lineno += 1
                  column = 0
              continue
          if type == token.OP:
              type = grammar.opmap[value]
          if debug:
              assert type is not None
              self.logger.debug(
                  "%s %r (prefix=%r)",
                  token.tok_name[type],
                  value,
                  prefix,
              )
          if type == token.INDENT:
              indent_columns.append(len(value))
              _prefix = prefix + value
              prefix = ""
              value = ""
          elif type == token.DEDENT:
              _indent_col = indent_columns.pop()
              prefix, _prefix = self._partially_consume_prefix(
                  prefix, _indent_col
              )
          if p.addtoken(cast(int, type), value, (prefix, start)):
              if debug:
                  self.logger.debug("Stop.")
              break
          prefix = ""
          if type in {token.INDENT, token.DEDENT}:
              prefix = _prefix
          lineno, column = end
          if value.endswith("\n"):
              lineno += 1
              column = 0
      else:
          # We never broke out -- EOF is too soon (how can this happen???)
          assert start is not None
          raise parse.ParseError(
              "incomplete input", type, value, (prefix, start)
          )
      assert p.rootnode is not None
      return p.rootnode
  
imports: import io
  import logging
  import os
  import pkgutil
  import sys
  from contextlib import contextmanager
  from dataclasses import dataclass, field
  from logging import Logger
  from typing import IO, Any, Iterable, Iterator, List, Optional, Tuple, Union, cast
  from blib2to3.pgen2.grammar import Grammar
  from blib2to3.pgen2.tokenize import GoodTokenInfo
  from blib2to3.pytree import NL
  from .None import grammar, parse, pgen, token, tokenize
label_desc: Use image node_id 2 for calling the Driver obj's underlying member method code with example usage: obj.parse_tokens(tokens, debug) and returns: p