
import sqlparse

# TODO: choose a better exception type

pushback = None

def init_parser(stmt):
    global pushback
    pushback = []
    for token in stmt.flatten():
        if token.is_whitespace:
            continue
        if token.ttype in sqlparse.tokens.Token.Comment:
            continue
        pushback.append(token)

def take():
    if len(pushback) > 0:
        return pushback.pop(0)
    else:
        return None

def untake(tok):
    pushback.insert(0, tok)#.append(tok)

def match_token(tok, ttype, value=None, icmp=False):
    if tok.ttype not in ttype:
        return False
    if value is not None:
        if tok.is_keyword or icmp:
            return tok.value.upper() == value.upper()
        else:
            return tok.value == value
    else:
        return True

def consume(ttype=None, value=None, icmp=False):
    tok = take()
    if tok is None:
        raise ValueError("Unexpected end of stream.")
    if ttype is None:
        return tok
    if not match_token(tok, ttype, value, icmp):
        raise ValueError("Unexpected token {}\"{}\" (expected {}\"{}\")."
                .format(tok.ttype, tok.value, ttype, value))
    return tok

def peek(ttype, value=None, icmp=False):
    tok = take()
    if tok is None:
        return False
    untake(tok)
    return match_token(tok, ttype, value, icmp)
