from collections import deque
import enum

t = enum.Enum("Tokens", "ADD MIN ID PLUS_PLUS MIN_MIN EOF")

# some test tokens
t1 = [t.MIN, t.ID, t.ADD, t.ID, t.ADD, t.ID, t.MIN_MIN, t.EOF]
t2 = [t.MIN, t.EOF]
t3 = [t.ID, t.EOF]
t4 = [t.ID, t.ADD, t.ID, t.EOF]
t5 = [t.ID, t.ID, t.EOF]
t6 = [t.ID, t.PLUS_PLUS, t.EOF]

def start():
    return P3() and (next_token() == t.EOF)

def P3():
    return P2() and P3p()

def P3p():
    token = next_token()
    if (token == t.ADD):
        return P2() and P3p()

    unget_token(token)
    return True

def P2():
    token = next_token()
    if (token == t.MIN):
        return P2()

    unget_token (token)
    return P1()

def P1():
    token = next_token()
    if (token == t.ID):
        return P1p()

    unget_token(token)
    return False

def P1p():
    token = next_token()
    if (token == t.PLUS_PLUS or token == t.MIN_MIN):
        return P1p()

    unget_token(token)
    return True

def run(toks):
    global tokens, next_token, unget_token
    tokens = deque(toks)
    unget_token = tokens.appendleft
    next_token = tokens.popleft

    success = start()
    print(f"{toks}: Parses properly!") if success else print(f"{toks}: doesn't parse.")
    return success

assert run(t1)
assert not run(t2)
assert run(t3)
assert run(t4)
assert not run(t5)
assert run(t6)