<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def read_token(self, prev: Token) -> Token: """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. """

        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))