#!/usr/bin/python

import sys
import re
import string
import copy

def isint(s):
  try:
    int(s)
    return True
  except ValueError:
    return False

if len(sys.argv) != 2:
  print 'Usage: ', sys.argv[0], ' bison_output_file'
  sys.exit(1)

bfile = file(sys.argv[1],'r')
sfile = file("spec.txt",'w')

while True:
  line = bfile.readline()
  if not line or line.strip() == 'Grammar': break

prevnt = ''
stringrules = []
while True:
  line = bfile.readline()
  if not line or line.strip().startswith('Terminals'): break
  if len(line.strip()) == 0: continue
  [grnum,nt,rhs] = re.split('(?:\\s|:|/\*.*\*/)+',line.strip(),2)
  if nt == '|': nt = prevnt
  prevnt = nt
  stringrules.append((grnum,[nt] + rhs.split()))

syms = dict()
nonterms = set()
while True:
  line = bfile.readline()
  if not line or line.strip().startswith('Nonterminals'): break
  if len(line.strip()) == 0: continue
  [trname,trnum,junk] = re.split('[ ()]+',line.strip(),2)
  if trname == 'error': continue
  syms[trname] = trnum
  nonterms.add(trname)
  sfile.write(trnum + ' ' + trname + '\n')
sfile.write('\n')
sfile.flush()

while True:
  line = bfile.readline()
  if not line or line.strip().startswith('state'): break
  if len(line.strip()) == 0 or line.startswith(' ') or line.startswith('\t'):
    continue
  [ntname,ntnum,junk] = re.split('[ ()]+',line.strip(),2)
  syms[ntname] = ntnum
  sfile.write(ntnum + ' ' + ntname + '\n')
sfile.write('\n')
sfile.flush()

for (grnum,rule) in stringrules:
  sfile.write(grnum)
  for sym in rule:
    sfile.write(' ' + syms[sym])
  sfile.write('\n')
sfile.write('\n')
sfile.flush()

while True:
  if not line: break
  sfile.write(line.split()[1] + '\n')
  fordef = copy.copy(nonterms)
  while True:
    line = bfile.readline()
    if (not line) or line.startswith('state'): break
    if len(line.strip()) == 0: continue
    if isint(line.split()[0]): continue
    sad = re.split('(?:\\s|shift, and|to state|using rule|\(.*\))+',line.strip())
    if sad[1] == 'accept':
      sfile.write('a\n')
      continue
    [sym,action,dest] = sad[:3]
    if sym == '$default':
      for defsym in fordef:
        sfile.write(syms[defsym] + ' ')
        if action == 'go':
          sfile.write('s ')
          sfile.write(dest)
        elif action == 'reduce':
          sfile.write('r ')
          sfile.write(dest)
        elif action == 'accept':
          sfile.write('a')
        sfile.write('\n')
    else:
      fordef.discard(sym)
      sfile.write(syms[sym] + ' ')
      if action == 'go':
        sfile.write('s ')
        sfile.write(dest)
      elif action == 'reduce':
        sfile.write('r ')
        sfile.write(dest)
      elif action == 'accept':
        sfile.write('a')
      sfile.write('\n')
  sfile.write('\n')
  sfile.flush()

bfile.close()
sfile.close()