is_a = isinstance
import Parsing
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
datatypes = """
(datatype action
(:shift int)
(:reduce int int))
(datatype action-list
(:nil)
(:cons int (action) (action-list)))
(datatype goto-list
(:nil)
(:cons int int (goto-list)))
"""
def gen_irken (file, tables):
W = file.write
W (datatypes)
goto, actions, tm, ntm = tables
items = tm.items()
items.sort (lambda a,b: cmp (a[1],b[1]))
W ('(define terminals \'#(\n')
for item, index in items:
W (' %s\n' % (item,))
W (' ))\n')
items = ntm.items()
items.sort (lambda a,b: cmp (a[1],b[1]))
W ('(define non-terminals \'#(\n')
for item, index in items:
W (' %s\n' % (item,))
W (' ))\n')
W ('(define actions\n')
W (' (literal #(\n')
for action in actions:
l = '(action-list:nil)'
for k, v in action.items():
shift_reduce, n = v
if shift_reduce == -1:
l = '(action-list:cons %d (action:shift %d) %s)' % (k, n, l)
else:
plen, nt = n
l = '(action-list:cons %d (action:reduce %d %d) %s)' % (k, plen, ntm[nt], l)
W (' %s\n' % l)
W (' )))\n')
W ('(define goto\n')
W (' (literal #(\n')
for entry in goto:
l = '(goto-list:nil)'
items = entry.items()[:]
items.reverse()
for k, v in items:
l = '(goto-list:cons %d %d %s)' % (ntm[k], v, l)
W (' %s\n' % l)
W (' )))\n')
if __name__ == '__main__':
import sys
base = sys.argv[1]
exec ("import %s" % (base,))
spec = eval ("%s.spec" % (base,))
tables = build_tables (spec)
file = open ('%s.scm' % (base,), 'wb')
gen_irken (file, tables)