is_a = isinstance

from t2 import *

from pdb import set_trace as trace
from pprint import pprint as pp

def make_map (l):
    m = {}
    for i in range (len (l)):
        m[l[i]] = i
    return m

def build_tables (s):
    tokens   = s._tokens.keys()
    nonterms = s._nonterms.keys()
    goto     = s._goto
    action   = s._action
    token_map = make_map (tokens)
    nt_map = make_map (nonterms)
    action2 = []
    for i in range (len (action)):
        d = {}
        for k,v in action[i].iteritems():
            # v is always a one-element list?  GLR-related?
            if is_a (v[0], Parsing.ShiftAction):
                v = -1, v[0].nextState
            elif is_a (v[0], Parsing.ReduceAction):
                p = v[0].production
                v = -2, (len(p.rhs), p.lhs.name)
            else:
                raise ValueError
            d[token_map[k.name]] = v
        action2.append (d)
    goto2 = []
    for i in range (len (goto)):
        d = {}
        for k,v in goto[i].iteritems():
            d[k.name] = v
        goto2.append (d)
    return goto2, action2, token_map, nt_map

def get_state (stack):
    if stack:
        return stack[-1][1]
    else:
        return 0

def machine (goto, action, tmap, ntmap, stream):
    stack = []
    while len(stream):
        kind, val = stream[0]
        state = get_state (stack)
        print '-----  stack=', stack
        print '*****     kind,val=',kind,val
        print '********* state=',state
        shift_reduce, n = action[state][tmap[kind]]
        if shift_reduce is -1:
            # shift
            stream.pop (0)
            stack.append ((val, n))
        elif shift_reduce is -2:
            # reduce
            plen, nt = n
            print '-------   plen,nt=', plen, nt
            if plen == 0:
                args = []
            else:
                stack, args = stack[:-plen], stack[-plen:]
            next_state = goto[get_state(stack)][nt]
            stack.append (((nt,[x[0] for x in args]), next_state))
    if stack[-1][0] == '<$>':
        return stack[0][0]
    else:
        raise SyntaxError

import sys

stream = [
    ('NAME','x'),
    ('plus','+'),
    ('NAME','y'),
    ('slash','/'),
    ('NAME','z'),
    ('splatsplat','**'),
    ('NUMBER','3'),
    ('<$>','<$>')
    ]

stream = [
    ('NAME','x'),
    ('or','or'),
    ('NAME','y'),
    ('or','or'),
    ('NAME','z'),
    ('<$>','<$>')
    ]    

stream = [
    ('def','def'),
    ('NAME','thing'),
    ('lparen','('),
    ('NAME','x'),
    ('rparen',')'),
    ('colon', ':'),
    ('NEWLINE', ''),
    ('INDENT', ''),
    ('pass', 'pass'),
    ('NEWLINE', ''),
    ('DEDENT', ''),
    ('<$>','<$>')
    ]    

class Parser (Parsing.Lr):

    def scan (self, input):
        for ttype, tdata in input:
            tok = eval ('t_%s' % (ttype,)) (self)
	    self.token (tok)
	self.eoi()

spec = Parsing.Spec (sys.modules[__name__], skinny=False, logFile="t0.log", verbose=True)

#p = Parser (spec)
#p._verbose = True
#p.scan (stream)

goto, action, tmap, ntmap = build_tables (spec)
pp (machine (goto, action, tmap, ntmap, stream))