text: from io import TextIOWrapper
  from typing import Callable, Iterator, Optional
  from typing import Union
  
  from .token import Keyword
  from .token import Token
  from .identifier import Name, Comment
  from .identifier import LiteralKind, Literal
  
  from .capturable import CapturableStream
  
  LexerResult = Union[Keyword, Token, Name, Literal]
  
  def is_cell_binary(cell: str) -> bool:
      return cell == '_' or cell == '0' or cell == '1'
  
  def is_cell_octal(cell: str) -> bool:
      return cell == '_' or cell >= '0' and cell <= '7'
  
  def is_cell_hexadecimal(cell: str) -> bool:
      return cell == '_' or cell >= '0' and cell <= '9' or cell >= 'a' and cell <= 'f' or cell >= 'A' and cell <= 'F'
  
  def is_cell_real(cell: str) -> bool:
      return cell == '_' or cell >= '0' and cell <= '9'
  
  
  def lex(stream: TextIOWrapper) -> Iterator[LexerResult]:
      capturable = CapturableStream(stream)
  
      while cell := capturable.capture():
          if cell == '_' or cell.isalpha():
              accumulator = cell + capturable.capture_each(lambda cell: cell == '_' or cell.isalnum())
              
              if accumulator == 'return':
                  yield Keyword.Return
              elif accumulator == 'fun':
                  yield Keyword.Fun
              elif accumulator == 'if':
                  yield Keyword.If
              elif accumulator == 'import':
                  yield Keyword.Import
              elif accumulator == 'while':
                  yield Keyword.While
              elif accumulator == 'for':
                  yield Keyword.For
              elif accumulator == 'new':
                  yield Keyword.New
              elif accumulator == 'del':
                  yield Keyword.Del
              elif accumulator == 'struct':
                  yield Keyword.Struct
              elif accumulator == 'in':
                  yield Keyword.In
              elif accumulator == 'raise':
                  yield Keyword.Raise
              else:
                  yield Name(accumulator)
          
          elif cell == '0':
              if capturable.capture('b'):
                  yield Literal(LiteralKind.Binary, '0b' + capturable.capture_each(is_cell_binary))
              elif capturable.capture('o'):
                  yield Literal(LiteralKind.Octal, '0o' + capturable.capture_each(is_cell_octal))
              elif capturable.capture('x'):
                  yield Literal(LiteralKind.Hexadecimal, '0x' + capturable.capture_each(is_cell_hexadecimal))
              else:
                  real = cell + capturable.capture_each(is_cell_real)
  
                  if capturable.capture('.'):
                      yield Literal(LiteralKind.Decimal, real + '.' + (capturable.capture_each(is_cell_real) or '0'))
                  else:
                      yield Literal(LiteralKind.Real, real)
          
          elif is_cell_real(cell):
              real = cell + capturable.capture_each(is_cell_real)
  
              if capturable.capture('.'):
                  yield Literal(LiteralKind.Decimal, real + '.' + (capturable.capture_each(is_cell_real) or '0'))
              else:
                  yield Literal(LiteralKind.Real, real)
          
          elif cell == '.':
              if capturable.capture('.'):
                  yield Token.Range
  
              elif cell := capturable.capture(is_cell_real):
                  yield Literal(LiteralKind.Decimal, '0.' + cell + capturable.capture_each(is_cell_real))
  
              else:
                  yield Token.Dot
          
          elif cell == '#':
              if capturable.capture(' '):
                  yield Comment(capturable.capture_each(lambda cell: cell and cell != '\n'))
              else:
                  yield Comment(capturable.capture_each(lambda cell: cell and cell != '\n'))
          
          elif cell == '"' or cell == "'":
              quote_cell = cell
              accept_next = False
  
              def is_quote(cell: str):
                  nonlocal accept_next
                  
                  if accept_next:
                      accept_next = False
                      return True
                  elif cell == '\\':
                      accept_next = True
  
                  return cell and cell != quote_cell
  
              yield Literal(LiteralKind.String, cell + capturable.capture_each(is_quote) + cell)
              capturable.capture()
  
          elif cell == '\r':
              yield Token.Return
          elif cell == '\n':
              yield Token.Newline
          elif cell == '\t':
              yield Token.Tab
          elif cell == '+':
              if capturable.capture('='):
                  yield Token.PlusAssign
              else:
                  yield Token.Plus
  
          elif cell == '-':
              if capturable.capture('='):
                  yield Token.MinusAssign
              elif capturable.capture('>'):
                  yield Token.ArrowRight
              else:
                  yield Token.Minus
  
          elif cell == '*':
              if capturable.capture('*'):
                  if capturable.capture('='):
                      yield Token.DoubleStarAssign
                  else:
                      yield Token.DoubleStar
  
              elif capturable.capture('='):
                  yield Token.StarAssign
              else:
                  yield Token.Star
          
          elif cell == '/':
              if capturable.capture('/'):
                  if capturable.capture('='):
                      yield Token.DoubleSlashAssign
                  else:
                      yield Token.DoubleSlash
  
              elif capturable.capture('='):
                  yield Token.SlashAssign
              else:
                  yield Token.Slash
          
          elif cell == ':':
              if capturable.capture('='):
                  yield Token.ColonAssign
              else:
                  yield Token.Colon
          elif cell == '<':
              if capturable.capture('-'):
                  yield Token.ArrowLeft
              elif capturable.capture('='):
                  yield Token.LessThanOrEqualTo
              else:
                  yield Token.LessThan
          
          elif cell == '>':
              if capturable.capture('='):
                  yield Token.GreaterThanOrEqualTo
              else:
                  yield Token.GreaterThan
          
          elif cell == '^':
              if capturable.capture('='):
                  yield Token.HatAssign
              else:
                  yield Token.Hat
          
          elif cell == '%':
              if capturable.capture('='):
                  yield Token.PercentAssign
              else:
                  yield Token.Percent
  
          elif cell == '@':
              yield Token.At
          elif cell == '{':
              yield Token.LeftCurlyBracket
          elif cell == '}':
              yield Token.RightCurlyBracket
          elif cell == '(':
              yield Token.LeftParenthesis
          elif cell == ')':
              yield Token.RightParenthesis
          elif cell == '=':
              if capturable.capture('='):
                  yield Token.EqualTo
              else:
                  yield Token.Equal
          
  
      yield Token.EndOfFile