code: def read_token(self, prev: Token) -> Token:
          
          source = self.source
          body = source.body
          body_length = len(body)
  
          pos = self.position_after_whitespace(body, prev.end)
          line = self.line
          col = 1 + pos - self.line_start
  
          if pos >= body_length:
              return Token(TokenKind.EOF, body_length, body_length, line, col, prev)
  
          char = body[pos]
          kind = _KIND_FOR_PUNCT.get(char)
          if kind:
              return Token(kind, pos, pos + 1, line, col, prev)
          if char == "#":
              return self.read_comment(pos, line, col, prev)
          elif char == ".":
              if body[pos + 1 : pos + 3] == "..":
                  return Token(TokenKind.SPREAD, pos, pos + 3, line, col, prev)
          elif "A" <= char <= "Z" or "a" <= char <= "z" or char == "_":
              return self.read_name(pos, line, col, prev)
          elif "0" <= char <= "9" or char == "-":
              return self.read_number(pos, char, line, col, prev)
          elif char == '"':
              if body[pos + 1 : pos + 3] == '""':
                  return self.read_block_string(pos, line, col, prev)
              return self.read_string(pos, line, col, prev)
  
          raise GraphQLSyntaxError(source, pos, unexpected_character_message(char))
docs: Get the next token from the source starting at the given position.
  
          This skips over whitespace until it finds the next lexable token, then lexes
          punctuators immediately or calls the appropriate helper function for more
          complicated tokens.