Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / cmd / goyacc / yacc.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/cmd/goyacc/yacc.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/cmd/goyacc/yacc.go
new file mode 100644 (file)
index 0000000..fdd44c1
--- /dev/null
@@ -0,0 +1,3595 @@
+/*
+Derived from Inferno's utils/iyacc/yacc.c
+http://code.google.com/p/inferno-os/source/browse/utils/iyacc/yacc.c
+
+This copyright NOTICE applies to all files in this directory and
+subdirectories, unless another copyright notice appears in a given
+file or subdirectory.  If you take substantial code from this software to use in
+other programs, you must somehow include with it an appropriate
+copyright notice that includes the copyright notice and the other
+notices below.  It is fine (and often tidier) to do that in a separate
+file such as NOTICE, LICENCE or COPYING.
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+       Portions Copyright © 1997-1999 Vita Nuova Limited
+       Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+       Portions Copyright © 2004,2006 Bruce Ellis
+       Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+       Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+       Portions Copyright © 2009 The Go Authors. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+package main
+
+// yacc
+// major difference is lack of stem ("y" variable)
+//
+
+import (
+       "bufio"
+       "bytes"
+       "flag"
+       "fmt"
+       "go/format"
+       "io/ioutil"
+       "os"
+       "strconv"
+       "strings"
+       "unicode"
+)
+
+// the following are adjustable
+// according to memory size
+const (
+       ACTSIZE  = 120000
+       NSTATES  = 8000
+       TEMPSIZE = 8000
+
+       SYMINC   = 50  // increase for non-term or term
+       RULEINC  = 50  // increase for max rule length prodptr[i]
+       PRODINC  = 100 // increase for productions     prodptr
+       WSETINC  = 50  // increase for working sets    wsets
+       STATEINC = 200 // increase for states          statemem
+
+       PRIVATE = 0xE000 // unicode private use
+
+       // relationships which must hold:
+       //      TEMPSIZE >= NTERMS + NNONTERM + 1;
+       //      TEMPSIZE >= NSTATES;
+       //
+
+       NTBASE     = 010000
+       ERRCODE    = 8190
+       ACCEPTCODE = 8191
+       YYLEXUNK   = 3
+       TOKSTART   = 4 //index of first defined token
+)
+
+// no, left, right, binary assoc.
+const (
+       NOASC = iota
+       LASC
+       RASC
+       BASC
+)
+
+// flags for state generation
+const (
+       DONE = iota
+       MUSTDO
+       MUSTLOOKAHEAD
+)
+
+// flags for a rule having an action, and being reduced
+const (
+       ACTFLAG = 1 << (iota + 2)
+       REDFLAG
+)
+
+// output parser flags
+const yyFlag = -1000
+
+// parse tokens
+const (
+       IDENTIFIER = PRIVATE + iota
+       MARK
+       TERM
+       LEFT
+       RIGHT
+       BINARY
+       PREC
+       LCURLY
+       IDENTCOLON
+       NUMBER
+       START
+       TYPEDEF
+       TYPENAME
+       UNION
+       ERROR
+)
+
+const ENDFILE = 0
+const EMPTY = 1
+const WHOKNOWS = 0
+const OK = 1
+const NOMORE = -1000
+
+// macros for getting associativity and precedence levels
+func ASSOC(i int) int { return i & 3 }
+
+func PLEVEL(i int) int { return (i >> 4) & 077 }
+
+func TYPE(i int) int { return (i >> 10) & 077 }
+
+// macros for setting associativity and precedence levels
+func SETASC(i, j int) int { return i | j }
+
+func SETPLEV(i, j int) int { return i | (j << 4) }
+
+func SETTYPE(i, j int) int { return i | (j << 10) }
+
+// I/O descriptors
+var finput *bufio.Reader // input file
+var stderr *bufio.Writer
+var ftable *bufio.Writer    // y.go file
+var fcode = &bytes.Buffer{} // saved code
+var foutput *bufio.Writer   // y.output file
+
+var fmtImported bool // output file has recorded an import of "fmt"
+
+var oflag string  // -o [y.go]         - y.go file
+var vflag string  // -v [y.output]     - y.output file
+var lflag bool    // -l                        - disable line directives
+var prefix string // name prefix for identifiers, default yy
+
+func init() {
+       flag.StringVar(&oflag, "o", "y.go", "parser output")
+       flag.StringVar(&prefix, "p", "yy", "name prefix to use in generated code")
+       flag.StringVar(&vflag, "v", "y.output", "create parsing tables")
+       flag.BoolVar(&lflag, "l", false, "disable line directives")
+}
+
+var initialstacksize = 16
+
+// communication variables between various I/O routines
+var infile string  // input file name
+var numbval int    // value of an input number
+var tokname string // input token name, slop for runes and 0
+var tokflag = false
+
+// structure declarations
+type Lkset []int
+
+type Pitem struct {
+       prod   []int
+       off    int // offset within the production
+       first  int // first term or non-term in item
+       prodno int // production number for sorting
+}
+
+type Item struct {
+       pitem Pitem
+       look  Lkset
+}
+
+type Symb struct {
+       name    string
+       noconst bool
+       value   int
+}
+
+type Wset struct {
+       pitem Pitem
+       flag  int
+       ws    Lkset
+}
+
+// storage of types
+var ntypes int                     // number of types defined
+var typeset = make(map[int]string) // pointers to type tags
+
+// token information
+
+var ntokens = 0 // number of tokens
+var tokset []Symb
+var toklev []int // vector with the precedence of the terminals
+
+// nonterminal information
+
+var nnonter = -1 // the number of nonterminals
+var nontrst []Symb
+var start int // start symbol
+
+// state information
+
+var nstate = 0                      // number of states
+var pstate = make([]int, NSTATES+2) // index into statemem to the descriptions of the states
+var statemem []Item
+var tystate = make([]int, NSTATES) // contains type information about the states
+var tstates []int                  // states generated by terminal gotos
+var ntstates []int                 // states generated by nonterminal gotos
+var mstates = make([]int, NSTATES) // chain of overflows of term/nonterm generation lists
+var lastred int                    // number of last reduction of a state
+var defact = make([]int, NSTATES)  // default actions of states
+
+// lookahead set information
+
+var nolook = 0  // flag to turn off lookahead computations
+var tbitset = 0 // size of lookahead sets
+var clset Lkset // temporary storage for lookahead computations
+
+// working set information
+
+var wsets []Wset
+var cwp int
+
+// storage for action table
+
+var amem []int                   // action table storage
+var memp int                     // next free action table position
+var indgo = make([]int, NSTATES) // index to the stored goto table
+
+// temporary vector, indexable by states, terms, or ntokens
+
+var temp1 = make([]int, TEMPSIZE) // temporary storage, indexed by terms + ntokens or states
+var lineno = 1                    // current input line number
+var fatfl = 1                     // if on, error is fatal
+var nerrors = 0                   // number of errors
+
+// assigned token type values
+
+var extval = 0
+
+// grammar rule information
+
+var nprod = 1      // number of productions
+var prdptr [][]int // pointers to descriptions of productions
+var levprd []int   // precedence levels for the productions
+var rlines []int   // line number for this rule
+
+// statistics collection variables
+
+var zzgoent = 0
+var zzgobest = 0
+var zzacent = 0
+var zzexcp = 0
+var zzclose = 0
+var zzrrconf = 0
+var zzsrconf = 0
+var zzstate = 0
+
+// optimizer arrays
+
+var yypgo [][]int
+var optst [][]int
+var ggreed []int
+var pgo []int
+
+var maxspr int // maximum spread of any entry
+var maxoff int // maximum offset into a array
+var maxa int
+
+// storage for information about the nonterminals
+
+var pres [][][]int // vector of pointers to productions yielding each nonterminal
+var pfirst []Lkset
+var pempty []int // vector of nonterminals nontrivially deriving e
+
+// random stuff picked out from between functions
+
+var indebug = 0 // debugging flag for cpfir
+var pidebug = 0 // debugging flag for putitem
+var gsdebug = 0 // debugging flag for stagen
+var cldebug = 0 // debugging flag for closure
+var pkdebug = 0 // debugging flag for apack
+var g2debug = 0 // debugging for go2gen
+var adb = 0     // debugging for callopt
+
+type Resrv struct {
+       name  string
+       value int
+}
+
+var resrv = []Resrv{
+       {"binary", BINARY},
+       {"left", LEFT},
+       {"nonassoc", BINARY},
+       {"prec", PREC},
+       {"right", RIGHT},
+       {"start", START},
+       {"term", TERM},
+       {"token", TERM},
+       {"type", TYPEDEF},
+       {"union", UNION},
+       {"struct", UNION},
+       {"error", ERROR},
+}
+
+type Error struct {
+       lineno int
+       tokens []string
+       msg    string
+}
+
+var errors []Error
+
+type Row struct {
+       actions       []int
+       defaultAction int
+}
+
+var stateTable []Row
+
+var zznewstate = 0
+
+const EOF = -1
+
+func main() {
+
+       setup() // initialize and read productions
+
+       tbitset = (ntokens + 32) / 32
+       cpres()  // make table of which productions yield a given nonterminal
+       cempty() // make a table of which nonterminals can match the empty string
+       cpfir()  // make a table of firsts of nonterminals
+
+       stagen() // generate the states
+
+       yypgo = make([][]int, nnonter+1)
+       optst = make([][]int, nstate)
+       output() // write the states and the tables
+       go2out()
+
+       hideprod()
+       summary()
+
+       callopt()
+
+       others()
+
+       exit(0)
+}
+
+func setup() {
+       var j, ty int
+
+       stderr = bufio.NewWriter(os.Stderr)
+       foutput = nil
+
+       flag.Parse()
+       if flag.NArg() != 1 {
+               usage()
+       }
+       if initialstacksize < 1 {
+               // never set so cannot happen
+               fmt.Fprintf(stderr, "yacc: stack size too small\n")
+               usage()
+       }
+       yaccpar = strings.Replace(yaccpartext, "$$", prefix, -1)
+       openup()
+
+       fmt.Fprintf(ftable, "// Code generated by goyacc %s. DO NOT EDIT.\n", strings.Join(os.Args[1:], " "))
+
+       defin(0, "$end")
+       extval = PRIVATE // tokens start in unicode 'private use'
+       defin(0, "error")
+       defin(1, "$accept")
+       defin(0, "$unk")
+       i := 0
+
+       t := gettok()
+
+outer:
+       for {
+               switch t {
+               default:
+                       errorf("syntax error tok=%v", t-PRIVATE)
+
+               case MARK, ENDFILE:
+                       break outer
+
+               case ';':
+                       // Do nothing.
+
+               case START:
+                       t = gettok()
+                       if t != IDENTIFIER {
+                               errorf("bad %%start construction")
+                       }
+                       start = chfind(1, tokname)
+
+               case ERROR:
+                       lno := lineno
+                       var tokens []string
+                       for {
+                               t := gettok()
+                               if t == ':' {
+                                       break
+                               }
+                               if t != IDENTIFIER && t != IDENTCOLON {
+                                       errorf("bad syntax in %%error")
+                               }
+                               tokens = append(tokens, tokname)
+                               if t == IDENTCOLON {
+                                       break
+                               }
+                       }
+                       if gettok() != IDENTIFIER {
+                               errorf("bad syntax in %%error")
+                       }
+                       errors = append(errors, Error{lno, tokens, tokname})
+
+               case TYPEDEF:
+                       t = gettok()
+                       if t != TYPENAME {
+                               errorf("bad syntax in %%type")
+                       }
+                       ty = numbval
+                       for {
+                               t = gettok()
+                               switch t {
+                               case IDENTIFIER:
+                                       t = chfind(1, tokname)
+                                       if t < NTBASE {
+                                               j = TYPE(toklev[t])
+                                               if j != 0 && j != ty {
+                                                       errorf("type redeclaration of token %s",
+                                                               tokset[t].name)
+                                               } else {
+                                                       toklev[t] = SETTYPE(toklev[t], ty)
+                                               }
+                                       } else {
+                                               j = nontrst[t-NTBASE].value
+                                               if j != 0 && j != ty {
+                                                       errorf("type redeclaration of nonterminal %v",
+                                                               nontrst[t-NTBASE].name)
+                                               } else {
+                                                       nontrst[t-NTBASE].value = ty
+                                               }
+                                       }
+                                       continue
+
+                               case ',':
+                                       continue
+                               }
+                               break
+                       }
+                       continue
+
+               case UNION:
+                       cpyunion()
+
+               case LEFT, BINARY, RIGHT, TERM:
+                       // nonzero means new prec. and assoc.
+                       lev := t - TERM
+                       if lev != 0 {
+                               i++
+                       }
+                       ty = 0
+
+                       // get identifiers so defined
+                       t = gettok()
+
+                       // there is a type defined
+                       if t == TYPENAME {
+                               ty = numbval
+                               t = gettok()
+                       }
+                       for {
+                               switch t {
+                               case ',':
+                                       t = gettok()
+                                       continue
+
+                               case ';':
+                                       // Do nothing.
+
+                               case IDENTIFIER:
+                                       j = chfind(0, tokname)
+                                       if j >= NTBASE {
+                                               errorf("%v defined earlier as nonterminal", tokname)
+                                       }
+                                       if lev != 0 {
+                                               if ASSOC(toklev[j]) != 0 {
+                                                       errorf("redeclaration of precedence of %v", tokname)
+                                               }
+                                               toklev[j] = SETASC(toklev[j], lev)
+                                               toklev[j] = SETPLEV(toklev[j], i)
+                                       }
+                                       if ty != 0 {
+                                               if TYPE(toklev[j]) != 0 {
+                                                       errorf("redeclaration of type of %v", tokname)
+                                               }
+                                               toklev[j] = SETTYPE(toklev[j], ty)
+                                       }
+                                       t = gettok()
+                                       if t == NUMBER {
+                                               tokset[j].value = numbval
+                                               t = gettok()
+                                       }
+
+                                       continue
+                               }
+                               break
+                       }
+                       continue
+
+               case LCURLY:
+                       cpycode()
+               }
+               t = gettok()
+       }
+
+       if t == ENDFILE {
+               errorf("unexpected EOF before %%")
+       }
+
+       fmt.Fprintf(fcode, "switch %snt {\n", prefix)
+
+       moreprod()
+       prdptr[0] = []int{NTBASE, start, 1, 0}
+
+       nprod = 1
+       curprod := make([]int, RULEINC)
+       t = gettok()
+       if t != IDENTCOLON {
+               errorf("bad syntax on first rule")
+       }
+
+       if start == 0 {
+               prdptr[0][1] = chfind(1, tokname)
+       }
+
+       // read rules
+       // put into prdptr array in the format
+       // target
+       // followed by id's of terminals and non-terminals
+       // followed by -nprod
+
+       for t != MARK && t != ENDFILE {
+               mem := 0
+
+               // process a rule
+               rlines[nprod] = lineno
+               ruleline := lineno
+               if t == '|' {
+                       curprod[mem] = prdptr[nprod-1][0]
+                       mem++
+               } else if t == IDENTCOLON {
+                       curprod[mem] = chfind(1, tokname)
+                       if curprod[mem] < NTBASE {
+                               lerrorf(ruleline, "token illegal on LHS of grammar rule")
+                       }
+                       mem++
+               } else {
+                       lerrorf(ruleline, "illegal rule: missing semicolon or | ?")
+               }
+
+               // read rule body
+               t = gettok()
+               for {
+                       for t == IDENTIFIER {
+                               curprod[mem] = chfind(1, tokname)
+                               if curprod[mem] < NTBASE {
+                                       levprd[nprod] = toklev[curprod[mem]]
+                               }
+                               mem++
+                               if mem >= len(curprod) {
+                                       ncurprod := make([]int, mem+RULEINC)
+                                       copy(ncurprod, curprod)
+                                       curprod = ncurprod
+                               }
+                               t = gettok()
+                       }
+                       if t == PREC {
+                               if gettok() != IDENTIFIER {
+                                       lerrorf(ruleline, "illegal %%prec syntax")
+                               }
+                               j = chfind(2, tokname)
+                               if j >= NTBASE {
+                                       lerrorf(ruleline, "nonterminal "+nontrst[j-NTBASE].name+" illegal after %%prec")
+                               }
+                               levprd[nprod] = toklev[j]
+                               t = gettok()
+                       }
+                       if t != '=' {
+                               break
+                       }
+                       levprd[nprod] |= ACTFLAG
+                       fmt.Fprintf(fcode, "\n\tcase %v:", nprod)
+                       fmt.Fprintf(fcode, "\n\t\t%sDollar = %sS[%spt-%v:%spt+1]", prefix, prefix, prefix, mem-1, prefix)
+                       cpyact(curprod, mem)
+
+                       // action within rule...
+                       t = gettok()
+                       if t == IDENTIFIER {
+                               // make it a nonterminal
+                               j = chfind(1, fmt.Sprintf("$$%v", nprod))
+
+                               //
+                               // the current rule will become rule number nprod+1
+                               // enter null production for action
+                               //
+                               prdptr[nprod] = make([]int, 2)
+                               prdptr[nprod][0] = j
+                               prdptr[nprod][1] = -nprod
+
+                               // update the production information
+                               nprod++
+                               moreprod()
+                               levprd[nprod] = levprd[nprod-1] & ^ACTFLAG
+                               levprd[nprod-1] = ACTFLAG
+                               rlines[nprod] = lineno
+
+                               // make the action appear in the original rule
+                               curprod[mem] = j
+                               mem++
+                               if mem >= len(curprod) {
+                                       ncurprod := make([]int, mem+RULEINC)
+                                       copy(ncurprod, curprod)
+                                       curprod = ncurprod
+                               }
+                       }
+               }
+
+               for t == ';' {
+                       t = gettok()
+               }
+               curprod[mem] = -nprod
+               mem++
+
+               // check that default action is reasonable
+               if ntypes != 0 && (levprd[nprod]&ACTFLAG) == 0 &&
+                       nontrst[curprod[0]-NTBASE].value != 0 {
+                       // no explicit action, LHS has value
+                       tempty := curprod[1]
+                       if tempty < 0 {
+                               lerrorf(ruleline, "must return a value, since LHS has a type")
+                       }
+                       if tempty >= NTBASE {
+                               tempty = nontrst[tempty-NTBASE].value
+                       } else {
+                               tempty = TYPE(toklev[tempty])
+                       }
+                       if tempty != nontrst[curprod[0]-NTBASE].value {
+                               lerrorf(ruleline, "default action causes potential type clash")
+                       }
+               }
+               moreprod()
+               prdptr[nprod] = make([]int, mem)
+               copy(prdptr[nprod], curprod)
+               nprod++
+               moreprod()
+               levprd[nprod] = 0
+       }
+
+       if TEMPSIZE < ntokens+nnonter+1 {
+               errorf("too many tokens (%d) or non-terminals (%d)", ntokens, nnonter)
+       }
+
+       //
+       // end of all rules
+       // dump out the prefix code
+       //
+
+       fmt.Fprintf(fcode, "\n\t}")
+
+       // put out non-literal terminals
+       for i := TOKSTART; i <= ntokens; i++ {
+               // non-literals
+               if !tokset[i].noconst {
+                       fmt.Fprintf(ftable, "const %v = %v\n", tokset[i].name, tokset[i].value)
+               }
+       }
+
+       // put out names of tokens
+       ftable.WriteRune('\n')
+       fmt.Fprintf(ftable, "var %sToknames = [...]string{\n", prefix)
+       for i := 1; i <= ntokens; i++ {
+               fmt.Fprintf(ftable, "\t%q,\n", tokset[i].name)
+       }
+       fmt.Fprintf(ftable, "}\n")
+
+       // put out names of states.
+       // commented out to avoid a huge table just for debugging.
+       // re-enable to have the names in the binary.
+       ftable.WriteRune('\n')
+       fmt.Fprintf(ftable, "var %sStatenames = [...]string{\n", prefix)
+       //      for i:=TOKSTART; i<=ntokens; i++ {
+       //              fmt.Fprintf(ftable, "\t%q,\n", tokset[i].name);
+       //      }
+       fmt.Fprintf(ftable, "}\n")
+
+       ftable.WriteRune('\n')
+       fmt.Fprintf(ftable, "const %sEofCode = 1\n", prefix)
+       fmt.Fprintf(ftable, "const %sErrCode = 2\n", prefix)
+       fmt.Fprintf(ftable, "const %sInitialStackSize = %v\n", prefix, initialstacksize)
+
+       //
+       // copy any postfix code
+       //
+       if t == MARK {
+               if !lflag {
+                       fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
+               }
+               for {
+                       c := getrune(finput)
+                       if c == EOF {
+                               break
+                       }
+                       ftable.WriteRune(c)
+               }
+       }
+}
+
+//
+// allocate enough room to hold another production
+//
+func moreprod() {
+       n := len(prdptr)
+       if nprod >= n {
+               nn := n + PRODINC
+               aprod := make([][]int, nn)
+               alevprd := make([]int, nn)
+               arlines := make([]int, nn)
+
+               copy(aprod, prdptr)
+               copy(alevprd, levprd)
+               copy(arlines, rlines)
+
+               prdptr = aprod
+               levprd = alevprd
+               rlines = arlines
+       }
+}
+
+//
+// define s to be a terminal if nt==0
+// or a nonterminal if nt==1
+//
+func defin(nt int, s string) int {
+       val := 0
+       if nt != 0 {
+               nnonter++
+               if nnonter >= len(nontrst) {
+                       anontrst := make([]Symb, nnonter+SYMINC)
+                       copy(anontrst, nontrst)
+                       nontrst = anontrst
+               }
+               nontrst[nnonter] = Symb{name: s}
+               return NTBASE + nnonter
+       }
+
+       // must be a token
+       ntokens++
+       if ntokens >= len(tokset) {
+               nn := ntokens + SYMINC
+               atokset := make([]Symb, nn)
+               atoklev := make([]int, nn)
+
+               copy(atoklev, toklev)
+               copy(atokset, tokset)
+
+               tokset = atokset
+               toklev = atoklev
+       }
+       tokset[ntokens].name = s
+       toklev[ntokens] = 0
+
+       // establish value for token
+       // single character literal
+       if s[0] == '\'' || s[0] == '"' {
+               q, err := strconv.Unquote(s)
+               if err != nil {
+                       errorf("invalid token: %s", err)
+               }
+               rq := []rune(q)
+               if len(rq) != 1 {
+                       errorf("character token too long: %s", s)
+               }
+               val = int(rq[0])
+               if val == 0 {
+                       errorf("token value 0 is illegal")
+               }
+               tokset[ntokens].noconst = true
+       } else {
+               val = extval
+               extval++
+               if s[0] == '$' {
+                       tokset[ntokens].noconst = true
+               }
+       }
+
+       tokset[ntokens].value = val
+       return ntokens
+}
+
+var peekline = 0
+
+func gettok() int {
+       var i int
+       var match, c rune
+
+       tokname = ""
+       for {
+               lineno += peekline
+               peekline = 0
+               c = getrune(finput)
+               for c == ' ' || c == '\n' || c == '\t' || c == '\v' || c == '\r' {
+                       if c == '\n' {
+                               lineno++
+                       }
+                       c = getrune(finput)
+               }
+
+               // skip comment -- fix
+               if c != '/' {
+                       break
+               }
+               lineno += skipcom()
+       }
+
+       switch c {
+       case EOF:
+               if tokflag {
+                       fmt.Printf(">>> ENDFILE %v\n", lineno)
+               }
+               return ENDFILE
+
+       case '{':
+               ungetrune(finput, c)
+               if tokflag {
+                       fmt.Printf(">>> ={ %v\n", lineno)
+               }
+               return '='
+
+       case '<':
+               // get, and look up, a type name (union member name)
+               c = getrune(finput)
+               for c != '>' && c != EOF && c != '\n' {
+                       tokname += string(c)
+                       c = getrune(finput)
+               }
+
+               if c != '>' {
+                       errorf("unterminated < ... > clause")
+               }
+
+               for i = 1; i <= ntypes; i++ {
+                       if typeset[i] == tokname {
+                               numbval = i
+                               if tokflag {
+                                       fmt.Printf(">>> TYPENAME old <%v> %v\n", tokname, lineno)
+                               }
+                               return TYPENAME
+                       }
+               }
+               ntypes++
+               numbval = ntypes
+               typeset[numbval] = tokname
+               if tokflag {
+                       fmt.Printf(">>> TYPENAME new <%v> %v\n", tokname, lineno)
+               }
+               return TYPENAME
+
+       case '"', '\'':
+               match = c
+               tokname = string(c)
+               for {
+                       c = getrune(finput)
+                       if c == '\n' || c == EOF {
+                               errorf("illegal or missing ' or \"")
+                       }
+                       if c == '\\' {
+                               tokname += string('\\')
+                               c = getrune(finput)
+                       } else if c == match {
+                               if tokflag {
+                                       fmt.Printf(">>> IDENTIFIER \"%v\" %v\n", tokname, lineno)
+                               }
+                               tokname += string(c)
+                               return IDENTIFIER
+                       }
+                       tokname += string(c)
+               }
+
+       case '%':
+               c = getrune(finput)
+               switch c {
+               case '%':
+                       if tokflag {
+                               fmt.Printf(">>> MARK %%%% %v\n", lineno)
+                       }
+                       return MARK
+               case '=':
+                       if tokflag {
+                               fmt.Printf(">>> PREC %%= %v\n", lineno)
+                       }
+                       return PREC
+               case '{':
+                       if tokflag {
+                               fmt.Printf(">>> LCURLY %%{ %v\n", lineno)
+                       }
+                       return LCURLY
+               }
+
+               getword(c)
+               // find a reserved word
+               for i := range resrv {
+                       if tokname == resrv[i].name {
+                               if tokflag {
+                                       fmt.Printf(">>> %%%v %v %v\n", tokname,
+                                               resrv[i].value-PRIVATE, lineno)
+                               }
+                               return resrv[i].value
+                       }
+               }
+               errorf("invalid escape, or illegal reserved word: %v", tokname)
+
+       case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+               numbval = int(c - '0')
+               for {
+                       c = getrune(finput)
+                       if !isdigit(c) {
+                               break
+                       }
+                       numbval = numbval*10 + int(c-'0')
+               }
+               ungetrune(finput, c)
+               if tokflag {
+                       fmt.Printf(">>> NUMBER %v %v\n", numbval, lineno)
+               }
+               return NUMBER
+
+       default:
+               if isword(c) || c == '.' || c == '$' {
+                       getword(c)
+                       break
+               }
+               if tokflag {
+                       fmt.Printf(">>> OPERATOR %v %v\n", string(c), lineno)
+               }
+               return int(c)
+       }
+
+       // look ahead to distinguish IDENTIFIER from IDENTCOLON
+       c = getrune(finput)
+       for c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\r' || c == '/' {
+               if c == '\n' {
+                       peekline++
+               }
+               // look for comments
+               if c == '/' {
+                       peekline += skipcom()
+               }
+               c = getrune(finput)
+       }
+       if c == ':' {
+               if tokflag {
+                       fmt.Printf(">>> IDENTCOLON %v: %v\n", tokname, lineno)
+               }
+               return IDENTCOLON
+       }
+
+       ungetrune(finput, c)
+       if tokflag {
+               fmt.Printf(">>> IDENTIFIER %v %v\n", tokname, lineno)
+       }
+       return IDENTIFIER
+}
+
+func getword(c rune) {
+       tokname = ""
+       for isword(c) || isdigit(c) || c == '.' || c == '$' {
+               tokname += string(c)
+               c = getrune(finput)
+       }
+       ungetrune(finput, c)
+}
+
+//
+// determine the type of a symbol
+//
+func fdtype(t int) int {
+       var v int
+       var s string
+
+       if t >= NTBASE {
+               v = nontrst[t-NTBASE].value
+               s = nontrst[t-NTBASE].name
+       } else {
+               v = TYPE(toklev[t])
+               s = tokset[t].name
+       }
+       if v <= 0 {
+               errorf("must specify type for %v", s)
+       }
+       return v
+}
+
+func chfind(t int, s string) int {
+       if s[0] == '"' || s[0] == '\'' {
+               t = 0
+       }
+       for i := 0; i <= ntokens; i++ {
+               if s == tokset[i].name {
+                       return i
+               }
+       }
+       for i := 0; i <= nnonter; i++ {
+               if s == nontrst[i].name {
+                       return NTBASE + i
+               }
+       }
+
+       // cannot find name
+       if t > 1 {
+               errorf("%v should have been defined earlier", s)
+       }
+       return defin(t, s)
+}
+
+//
+// copy the union declaration to the output, and the define file if present
+//
+func cpyunion() {
+
+       if !lflag {
+               fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
+       }
+       fmt.Fprintf(ftable, "type %sSymType struct", prefix)
+
+       level := 0
+
+out:
+       for {
+               c := getrune(finput)
+               if c == EOF {
+                       errorf("EOF encountered while processing %%union")
+               }
+               ftable.WriteRune(c)
+               switch c {
+               case '\n':
+                       lineno++
+               case '{':
+                       if level == 0 {
+                               fmt.Fprintf(ftable, "\n\tyys int")
+                       }
+                       level++
+               case '}':
+                       level--
+                       if level == 0 {
+                               break out
+                       }
+               }
+       }
+       fmt.Fprintf(ftable, "\n\n")
+}
+
+//
+// saves code between %{ and %}
+// adds an import for __fmt__ the first time
+//
+func cpycode() {
+       lno := lineno
+
+       c := getrune(finput)
+       if c == '\n' {
+               c = getrune(finput)
+               lineno++
+       }
+       if !lflag {
+               fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
+       }
+       // accumulate until %}
+       code := make([]rune, 0, 1024)
+       for c != EOF {
+               if c == '%' {
+                       c = getrune(finput)
+                       if c == '}' {
+                               emitcode(code, lno+1)
+                               return
+                       }
+                       code = append(code, '%')
+               }
+               code = append(code, c)
+               if c == '\n' {
+                       lineno++
+               }
+               c = getrune(finput)
+       }
+       lineno = lno
+       errorf("eof before %%}")
+}
+
+//
+// emits code saved up from between %{ and %}
+// called by cpycode
+// adds an import for __yyfmt__ after the package clause
+//
+func emitcode(code []rune, lineno int) {
+       for i, line := range lines(code) {
+               writecode(line)
+               if !fmtImported && isPackageClause(line) {
+                       fmt.Fprintln(ftable, `import __yyfmt__ "fmt"`)
+                       if !lflag {
+                               fmt.Fprintf(ftable, "//line %v:%v\n\t\t", infile, lineno+i)
+                       }
+                       fmtImported = true
+               }
+       }
+}
+
+//
+// does this line look like a package clause?  not perfect: might be confused by early comments.
+//
+func isPackageClause(line []rune) bool {
+       line = skipspace(line)
+
+       // must be big enough.
+       if len(line) < len("package X\n") {
+               return false
+       }
+
+       // must start with "package"
+       for i, r := range []rune("package") {
+               if line[i] != r {
+                       return false
+               }
+       }
+       line = skipspace(line[len("package"):])
+
+       // must have another identifier.
+       if len(line) == 0 || (!unicode.IsLetter(line[0]) && line[0] != '_') {
+               return false
+       }
+       for len(line) > 0 {
+               if !unicode.IsLetter(line[0]) && !unicode.IsDigit(line[0]) && line[0] != '_' {
+                       break
+               }
+               line = line[1:]
+       }
+       line = skipspace(line)
+
+       // eol, newline, or comment must follow
+       if len(line) == 0 {
+               return true
+       }
+       if line[0] == '\r' || line[0] == '\n' {
+               return true
+       }
+       if len(line) >= 2 {
+               return line[0] == '/' && (line[1] == '/' || line[1] == '*')
+       }
+       return false
+}
+
+//
+// skip initial spaces
+//
+func skipspace(line []rune) []rune {
+       for len(line) > 0 {
+               if line[0] != ' ' && line[0] != '\t' {
+                       break
+               }
+               line = line[1:]
+       }
+       return line
+}
+
+//
+// break code into lines
+//
+func lines(code []rune) [][]rune {
+       l := make([][]rune, 0, 100)
+       for len(code) > 0 {
+               // one line per loop
+               var i int
+               for i = range code {
+                       if code[i] == '\n' {
+                               break
+                       }
+               }
+               l = append(l, code[:i+1])
+               code = code[i+1:]
+       }
+       return l
+}
+
+//
+// writes code to ftable
+//
+func writecode(code []rune) {
+       for _, r := range code {
+               ftable.WriteRune(r)
+       }
+}
+
+//
+// skip over comments
+// skipcom is called after reading a '/'
+//
+func skipcom() int {
+       c := getrune(finput)
+       if c == '/' {
+               for c != EOF {
+                       if c == '\n' {
+                               return 1
+                       }
+                       c = getrune(finput)
+               }
+               errorf("EOF inside comment")
+               return 0
+       }
+       if c != '*' {
+               errorf("illegal comment")
+       }
+
+       nl := 0 // lines skipped
+       c = getrune(finput)
+
+l1:
+       switch c {
+       case '*':
+               c = getrune(finput)
+               if c == '/' {
+                       break
+               }
+               goto l1
+
+       case '\n':
+               nl++
+               fallthrough
+
+       default:
+               c = getrune(finput)
+               goto l1
+       }
+       return nl
+}
+
+//
+// copy action to the next ; or closing }
+//
+func cpyact(curprod []int, max int) {
+
+       if !lflag {
+               fmt.Fprintf(fcode, "\n//line %v:%v", infile, lineno)
+       }
+       fmt.Fprint(fcode, "\n\t\t")
+
+       lno := lineno
+       brac := 0
+
+loop:
+       for {
+               c := getrune(finput)
+
+       swt:
+               switch c {
+               case ';':
+                       if brac == 0 {
+                               fcode.WriteRune(c)
+                               return
+                       }
+
+               case '{':
+                       brac++
+
+               case '$':
+                       s := 1
+                       tok := -1
+                       c = getrune(finput)
+
+                       // type description
+                       if c == '<' {
+                               ungetrune(finput, c)
+                               if gettok() != TYPENAME {
+                                       errorf("bad syntax on $<ident> clause")
+                               }
+                               tok = numbval
+                               c = getrune(finput)
+                       }
+                       if c == '$' {
+                               fmt.Fprintf(fcode, "%sVAL", prefix)
+
+                               // put out the proper tag...
+                               if ntypes != 0 {
+                                       if tok < 0 {
+                                               tok = fdtype(curprod[0])
+                                       }
+                                       fmt.Fprintf(fcode, ".%v", typeset[tok])
+                               }
+                               continue loop
+                       }
+                       if c == '-' {
+                               s = -s
+                               c = getrune(finput)
+                       }
+                       j := 0
+                       if isdigit(c) {
+                               for isdigit(c) {
+                                       j = j*10 + int(c-'0')
+                                       c = getrune(finput)
+                               }
+                               ungetrune(finput, c)
+                               j = j * s
+                               if j >= max {
+                                       errorf("Illegal use of $%v", j)
+                               }
+                       } else if isword(c) || c == '.' {
+                               // look for $name
+                               ungetrune(finput, c)
+                               if gettok() != IDENTIFIER {
+                                       errorf("$ must be followed by an identifier")
+                               }
+                               tokn := chfind(2, tokname)
+                               fnd := -1
+                               c = getrune(finput)
+                               if c != '@' {
+                                       ungetrune(finput, c)
+                               } else if gettok() != NUMBER {
+                                       errorf("@ must be followed by number")
+                               } else {
+                                       fnd = numbval
+                               }
+                               for j = 1; j < max; j++ {
+                                       if tokn == curprod[j] {
+                                               fnd--
+                                               if fnd <= 0 {
+                                                       break
+                                               }
+                                       }
+                               }
+                               if j >= max {
+                                       errorf("$name or $name@number not found")
+                               }
+                       } else {
+                               fcode.WriteRune('$')
+                               if s < 0 {
+                                       fcode.WriteRune('-')
+                               }
+                               ungetrune(finput, c)
+                               continue loop
+                       }
+                       fmt.Fprintf(fcode, "%sDollar[%v]", prefix, j)
+
+                       // put out the proper tag
+                       if ntypes != 0 {
+                               if j <= 0 && tok < 0 {
+                                       errorf("must specify type of $%v", j)
+                               }
+                               if tok < 0 {
+                                       tok = fdtype(curprod[j])
+                               }
+                               fmt.Fprintf(fcode, ".%v", typeset[tok])
+                       }
+                       continue loop
+
+               case '}':
+                       brac--
+                       if brac != 0 {
+                               break
+                       }
+                       fcode.WriteRune(c)
+                       return
+
+               case '/':
+                       nc := getrune(finput)
+                       if nc != '/' && nc != '*' {
+                               ungetrune(finput, nc)
+                               break
+                       }
+                       // a comment
+                       fcode.WriteRune(c)
+                       fcode.WriteRune(nc)
+                       c = getrune(finput)
+                       for c != EOF {
+                               switch {
+                               case c == '\n':
+                                       lineno++
+                                       if nc == '/' { // end of // comment
+                                               break swt
+                                       }
+                               case c == '*' && nc == '*': // end of /* comment?
+                                       nnc := getrune(finput)
+                                       if nnc == '/' {
+                                               fcode.WriteRune('*')
+                                               fcode.WriteRune('/')
+                                               continue loop
+                                       }
+                                       ungetrune(finput, nnc)
+                               }
+                               fcode.WriteRune(c)
+                               c = getrune(finput)
+                       }
+                       errorf("EOF inside comment")
+
+               case '\'', '"':
+                       // character string or constant
+                       match := c
+                       fcode.WriteRune(c)
+                       c = getrune(finput)
+                       for c != EOF {
+                               if c == '\\' {
+                                       fcode.WriteRune(c)
+                                       c = getrune(finput)
+                                       if c == '\n' {
+                                               lineno++
+                                       }
+                               } else if c == match {
+                                       break swt
+                               }
+                               if c == '\n' {
+                                       errorf("newline in string or char const")
+                               }
+                               fcode.WriteRune(c)
+                               c = getrune(finput)
+                       }
+                       errorf("EOF in string or character constant")
+
+               case EOF:
+                       lineno = lno
+                       errorf("action does not terminate")
+
+               case '\n':
+                       fmt.Fprint(fcode, "\n\t")
+                       lineno++
+                       continue loop
+               }
+
+               fcode.WriteRune(c)
+       }
+}
+
+func openup() {
+       infile = flag.Arg(0)
+       finput = open(infile)
+       if finput == nil {
+               errorf("cannot open %v", infile)
+       }
+
+       foutput = nil
+       if vflag != "" {
+               foutput = create(vflag)
+               if foutput == nil {
+                       errorf("can't create file %v", vflag)
+               }
+       }
+
+       ftable = nil
+       if oflag == "" {
+               oflag = "y.go"
+       }
+       ftable = create(oflag)
+       if ftable == nil {
+               errorf("can't create file %v", oflag)
+       }
+
+}
+
+//
+// return a pointer to the name of symbol i
+//
+func symnam(i int) string {
+       var s string
+
+       if i >= NTBASE {
+               s = nontrst[i-NTBASE].name
+       } else {
+               s = tokset[i].name
+       }
+       return s
+}
+
+//
+// set elements 0 through n-1 to c
+//
+func aryfil(v []int, n, c int) {
+       for i := 0; i < n; i++ {
+               v[i] = c
+       }
+}
+
+//
+// compute an array with the beginnings of productions yielding given nonterminals
+// The array pres points to these lists
+// the array pyield has the lists: the total size is only NPROD+1
+//
+func cpres() {
+       pres = make([][][]int, nnonter+1)
+       curres := make([][]int, nprod)
+
+       if false {
+               for j := 0; j <= nnonter; j++ {
+                       fmt.Printf("nnonter[%v] = %v\n", j, nontrst[j].name)
+               }
+               for j := 0; j < nprod; j++ {
+                       fmt.Printf("prdptr[%v][0] = %v+NTBASE\n", j, prdptr[j][0]-NTBASE)
+               }
+       }
+
+       fatfl = 0 // make undefined symbols nonfatal
+       for i := 0; i <= nnonter; i++ {
+               n := 0
+               c := i + NTBASE
+               for j := 0; j < nprod; j++ {
+                       if prdptr[j][0] == c {
+                               curres[n] = prdptr[j][1:]
+                               n++
+                       }
+               }
+               if n == 0 {
+                       errorf("nonterminal %v not defined", nontrst[i].name)
+                       continue
+               }
+               pres[i] = make([][]int, n)
+               copy(pres[i], curres)
+       }
+       fatfl = 1
+       if nerrors != 0 {
+               summary()
+               exit(1)
+       }
+}
+
+//
+// mark nonterminals which derive the empty string
+// also, look for nonterminals which don't derive any token strings
+//
+func cempty() {
+       var i, p, np int
+       var prd []int
+
+       pempty = make([]int, nnonter+1)
+
+       // first, use the array pempty to detect productions that can never be reduced
+       // set pempty to WHONOWS
+       aryfil(pempty, nnonter+1, WHOKNOWS)
+
+       // now, look at productions, marking nonterminals which derive something
+more:
+       for {
+               for i = 0; i < nprod; i++ {
+                       prd = prdptr[i]
+                       if pempty[prd[0]-NTBASE] != 0 {
+                               continue
+                       }
+                       np = len(prd) - 1
+                       for p = 1; p < np; p++ {
+                               if prd[p] >= NTBASE && pempty[prd[p]-NTBASE] == WHOKNOWS {
+                                       break
+                               }
+                       }
+                       // production can be derived
+                       if p == np {
+                               pempty[prd[0]-NTBASE] = OK
+                               continue more
+                       }
+               }
+               break
+       }
+
+       // now, look at the nonterminals, to see if they are all OK
+       for i = 0; i <= nnonter; i++ {
+               // the added production rises or falls as the start symbol ...
+               if i == 0 {
+                       continue
+               }
+               if pempty[i] != OK {
+                       fatfl = 0
+                       errorf("nonterminal " + nontrst[i].name + " never derives any token string")
+               }
+       }
+
+       if nerrors != 0 {
+               summary()
+               exit(1)
+       }
+
+       // now, compute the pempty array, to see which nonterminals derive the empty string
+       // set pempty to WHOKNOWS
+       aryfil(pempty, nnonter+1, WHOKNOWS)
+
+       // loop as long as we keep finding empty nonterminals
+
+again:
+       for {
+       next:
+               for i = 1; i < nprod; i++ {
+                       // not known to be empty
+                       prd = prdptr[i]
+                       if pempty[prd[0]-NTBASE] != WHOKNOWS {
+                               continue
+                       }
+                       np = len(prd) - 1
+                       for p = 1; p < np; p++ {
+                               if prd[p] < NTBASE || pempty[prd[p]-NTBASE] != EMPTY {
+                                       continue next
+                               }
+                       }
+
+                       // we have a nontrivially empty nonterminal
+                       pempty[prd[0]-NTBASE] = EMPTY
+
+                       // got one ... try for another
+                       continue again
+               }
+               return
+       }
+}
+
+//
+// compute an array with the first of nonterminals
+//
+func cpfir() {
+       var s, n, p, np, ch, i int
+       var curres [][]int
+       var prd []int
+
+       wsets = make([]Wset, nnonter+WSETINC)
+       pfirst = make([]Lkset, nnonter+1)
+       for i = 0; i <= nnonter; i++ {
+               wsets[i].ws = mkset()
+               pfirst[i] = mkset()
+               curres = pres[i]
+               n = len(curres)
+
+               // initially fill the sets
+               for s = 0; s < n; s++ {
+                       prd = curres[s]
+                       np = len(prd) - 1
+                       for p = 0; p < np; p++ {
+                               ch = prd[p]
+                               if ch < NTBASE {
+                                       setbit(pfirst[i], ch)
+                                       break
+                               }
+                               if pempty[ch-NTBASE] == 0 {
+                                       break
+                               }
+                       }
+               }
+       }
+
+       // now, reflect transitivity
+       changes := 1
+       for changes != 0 {
+               changes = 0
+               for i = 0; i <= nnonter; i++ {
+                       curres = pres[i]
+                       n = len(curres)
+                       for s = 0; s < n; s++ {
+                               prd = curres[s]
+                               np = len(prd) - 1
+                               for p = 0; p < np; p++ {
+                                       ch = prd[p] - NTBASE
+                                       if ch < 0 {
+                                               break
+                                       }
+                                       changes |= setunion(pfirst[i], pfirst[ch])
+                                       if pempty[ch] == 0 {
+                                               break
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if indebug == 0 {
+               return
+       }
+       if foutput != nil {
+               for i = 0; i <= nnonter; i++ {
+                       fmt.Fprintf(foutput, "\n%v: %v %v\n",
+                               nontrst[i].name, pfirst[i], pempty[i])
+               }
+       }
+}
+
+//
+// generate the states
+//
+func stagen() {
+       // initialize
+       nstate = 0
+       tstates = make([]int, ntokens+1)  // states generated by terminal gotos
+       ntstates = make([]int, nnonter+1) // states generated by nonterminal gotos
+       amem = make([]int, ACTSIZE)
+       memp = 0
+
+       clset = mkset()
+       pstate[0] = 0
+       pstate[1] = 0
+       aryfil(clset, tbitset, 0)
+       putitem(Pitem{prdptr[0], 0, 0, 0}, clset)
+       tystate[0] = MUSTDO
+       nstate = 1
+       pstate[2] = pstate[1]
+
+       //
+       // now, the main state generation loop
+       // first pass generates all of the states
+       // later passes fix up lookahead
+       // could be sped up a lot by remembering
+       // results of the first pass rather than recomputing
+       //
+       first := 1
+       for more := 1; more != 0; first = 0 {
+               more = 0
+               for i := 0; i < nstate; i++ {
+                       if tystate[i] != MUSTDO {
+                               continue
+                       }
+
+                       tystate[i] = DONE
+                       aryfil(temp1, nnonter+1, 0)
+
+                       // take state i, close it, and do gotos
+                       closure(i)
+
+                       // generate goto's
+                       for p := 0; p < cwp; p++ {
+                               pi := wsets[p]
+                               if pi.flag != 0 {
+                                       continue
+                               }
+                               wsets[p].flag = 1
+                               c := pi.pitem.first
+                               if c <= 1 {
+                                       if pstate[i+1]-pstate[i] <= p {
+                                               tystate[i] = MUSTLOOKAHEAD
+                                       }
+                                       continue
+                               }
+
+                               // do a goto on c
+                               putitem(wsets[p].pitem, wsets[p].ws)
+                               for q := p + 1; q < cwp; q++ {
+                                       // this item contributes to the goto
+                                       if c == wsets[q].pitem.first {
+                                               putitem(wsets[q].pitem, wsets[q].ws)
+                                               wsets[q].flag = 1
+                                       }
+                               }
+
+                               if c < NTBASE {
+                                       state(c) // register new state
+                               } else {
+                                       temp1[c-NTBASE] = state(c)
+                               }
+                       }
+
+                       if gsdebug != 0 && foutput != nil {
+                               fmt.Fprintf(foutput, "%v: ", i)
+                               for j := 0; j <= nnonter; j++ {
+                                       if temp1[j] != 0 {
+                                               fmt.Fprintf(foutput, "%v %v,", nontrst[j].name, temp1[j])
+                                       }
+                               }
+                               fmt.Fprintf(foutput, "\n")
+                       }
+
+                       if first != 0 {
+                               indgo[i] = apack(temp1[1:], nnonter-1) - 1
+                       }
+
+                       more++
+               }
+       }
+}
+
+//
+// generate the closure of state i
+//
+func closure(i int) {
+       zzclose++
+
+       // first, copy kernel of state i to wsets
+       cwp = 0
+       q := pstate[i+1]
+       for p := pstate[i]; p < q; p++ {
+               wsets[cwp].pitem = statemem[p].pitem
+               wsets[cwp].flag = 1 // this item must get closed
+               copy(wsets[cwp].ws, statemem[p].look)
+               cwp++
+       }
+
+       // now, go through the loop, closing each item
+       work := 1
+       for work != 0 {
+               work = 0
+               for u := 0; u < cwp; u++ {
+                       if wsets[u].flag == 0 {
+                               continue
+                       }
+
+                       // dot is before c
+                       c := wsets[u].pitem.first
+                       if c < NTBASE {
+                               wsets[u].flag = 0
+                               // only interesting case is where . is before nonterminal
+                               continue
+                       }
+
+                       // compute the lookahead
+                       aryfil(clset, tbitset, 0)
+
+                       // find items involving c
+                       for v := u; v < cwp; v++ {
+                               if wsets[v].flag != 1 || wsets[v].pitem.first != c {
+                                       continue
+                               }
+                               pi := wsets[v].pitem.prod
+                               ipi := wsets[v].pitem.off + 1
+
+                               wsets[v].flag = 0
+                               if nolook != 0 {
+                                       continue
+                               }
+
+                               ch := pi[ipi]
+                               ipi++
+                               for ch > 0 {
+                                       // terminal symbol
+                                       if ch < NTBASE {
+                                               setbit(clset, ch)
+                                               break
+                                       }
+
+                                       // nonterminal symbol
+                                       setunion(clset, pfirst[ch-NTBASE])
+                                       if pempty[ch-NTBASE] == 0 {
+                                               break
+                                       }
+                                       ch = pi[ipi]
+                                       ipi++
+                               }
+                               if ch <= 0 {
+                                       setunion(clset, wsets[v].ws)
+                               }
+                       }
+
+                       //
+                       // now loop over productions derived from c
+                       //
+                       curres := pres[c-NTBASE]
+                       n := len(curres)
+
+               nexts:
+                       // initially fill the sets
+                       for s := 0; s < n; s++ {
+                               prd := curres[s]
+
+                               //
+                               // put these items into the closure
+                               // is the item there
+                               //
+                               for v := 0; v < cwp; v++ {
+                                       // yes, it is there
+                                       if wsets[v].pitem.off == 0 &&
+                                               aryeq(wsets[v].pitem.prod, prd) != 0 {
+                                               if nolook == 0 &&
+                                                       setunion(wsets[v].ws, clset) != 0 {
+                                                       wsets[v].flag = 1
+                                                       work = 1
+                                               }
+                                               continue nexts
+                                       }
+                               }
+
+                               //  not there; make a new entry
+                               if cwp >= len(wsets) {
+                                       awsets := make([]Wset, cwp+WSETINC)
+                                       copy(awsets, wsets)
+                                       wsets = awsets
+                               }
+                               wsets[cwp].pitem = Pitem{prd, 0, prd[0], -prd[len(prd)-1]}
+                               wsets[cwp].flag = 1
+                               wsets[cwp].ws = mkset()
+                               if nolook == 0 {
+                                       work = 1
+                                       copy(wsets[cwp].ws, clset)
+                               }
+                               cwp++
+                       }
+               }
+       }
+
+       // have computed closure; flags are reset; return
+       if cldebug != 0 && foutput != nil {
+               fmt.Fprintf(foutput, "\nState %v, nolook = %v\n", i, nolook)
+               for u := 0; u < cwp; u++ {
+                       if wsets[u].flag != 0 {
+                               fmt.Fprintf(foutput, "flag set\n")
+                       }
+                       wsets[u].flag = 0
+                       fmt.Fprintf(foutput, "\t%v", writem(wsets[u].pitem))
+                       prlook(wsets[u].ws)
+                       fmt.Fprintf(foutput, "\n")
+               }
+       }
+}
+
+//
+// sorts last state,and sees if it equals earlier ones. returns state number
+//
+func state(c int) int {
+       zzstate++
+       p1 := pstate[nstate]
+       p2 := pstate[nstate+1]
+       if p1 == p2 {
+               return 0 // null state
+       }
+
+       // sort the items
+       var k, l int
+       for k = p1 + 1; k < p2; k++ { // make k the biggest
+               for l = k; l > p1; l-- {
+                       if statemem[l].pitem.prodno < statemem[l-1].pitem.prodno ||
+                               statemem[l].pitem.prodno == statemem[l-1].pitem.prodno &&
+                                       statemem[l].pitem.off < statemem[l-1].pitem.off {
+                               s := statemem[l]
+                               statemem[l] = statemem[l-1]
+                               statemem[l-1] = s
+                       } else {
+                               break
+                       }
+               }
+       }
+
+       size1 := p2 - p1 // size of state
+
+       var i int
+       if c >= NTBASE {
+               i = ntstates[c-NTBASE]
+       } else {
+               i = tstates[c]
+       }
+
+look:
+       for ; i != 0; i = mstates[i] {
+               // get ith state
+               q1 := pstate[i]
+               q2 := pstate[i+1]
+               size2 := q2 - q1
+               if size1 != size2 {
+                       continue
+               }
+               k = p1
+               for l = q1; l < q2; l++ {
+                       if aryeq(statemem[l].pitem.prod, statemem[k].pitem.prod) == 0 ||
+                               statemem[l].pitem.off != statemem[k].pitem.off {
+                               continue look
+                       }
+                       k++
+               }
+
+               // found it
+               pstate[nstate+1] = pstate[nstate] // delete last state
+
+               // fix up lookaheads
+               if nolook != 0 {
+                       return i
+               }
+               k = p1
+               for l = q1; l < q2; l++ {
+                       if setunion(statemem[l].look, statemem[k].look) != 0 {
+                               tystate[i] = MUSTDO
+                       }
+                       k++
+               }
+               return i
+       }
+
+       // state is new
+       zznewstate++
+       if nolook != 0 {
+               errorf("yacc state/nolook error")
+       }
+       pstate[nstate+2] = p2
+       if nstate+1 >= NSTATES {
+               errorf("too many states")
+       }
+       if c >= NTBASE {
+               mstates[nstate] = ntstates[c-NTBASE]
+               ntstates[c-NTBASE] = nstate
+       } else {
+               mstates[nstate] = tstates[c]
+               tstates[c] = nstate
+       }
+       tystate[nstate] = MUSTDO
+       nstate++
+       return nstate - 1
+}
+
+func putitem(p Pitem, set Lkset) {
+       p.off++
+       p.first = p.prod[p.off]
+
+       if pidebug != 0 && foutput != nil {
+               fmt.Fprintf(foutput, "putitem(%v), state %v\n", writem(p), nstate)
+       }
+       j := pstate[nstate+1]
+       if j >= len(statemem) {
+               asm := make([]Item, j+STATEINC)
+               copy(asm, statemem)
+               statemem = asm
+       }
+       statemem[j].pitem = p
+       if nolook == 0 {
+               s := mkset()
+               copy(s, set)
+               statemem[j].look = s
+       }
+       j++
+       pstate[nstate+1] = j
+}
+
+//
+// creates output string for item pointed to by pp
+//
+func writem(pp Pitem) string {
+       var i int
+
+       p := pp.prod
+       q := chcopy(nontrst[prdptr[pp.prodno][0]-NTBASE].name) + ": "
+       npi := pp.off
+
+       pi := aryeq(p, prdptr[pp.prodno])
+
+       for {
+               c := ' '
+               if pi == npi {
+                       c = '.'
+               }
+               q += string(c)
+
+               i = p[pi]
+               pi++
+               if i <= 0 {
+                       break
+               }
+               q += chcopy(symnam(i))
+       }
+
+       // an item calling for a reduction
+       i = p[npi]
+       if i < 0 {
+               q += fmt.Sprintf("    (%v)", -i)
+       }
+
+       return q
+}
+
+//
+// pack state i from temp1 into amem
+//
+func apack(p []int, n int) int {
+       //
+       // we don't need to worry about checking because
+       // we will only look at entries known to be there...
+       // eliminate leading and trailing 0's
+       //
+       off := 0
+       pp := 0
+       for ; pp <= n && p[pp] == 0; pp++ {
+               off--
+       }
+
+       // no actions
+       if pp > n {
+               return 0
+       }
+       for ; n > pp && p[n] == 0; n-- {
+       }
+       p = p[pp : n+1]
+
+       // now, find a place for the elements from p to q, inclusive
+       r := len(amem) - len(p)
+
+nextk:
+       for rr := 0; rr <= r; rr++ {
+               qq := rr
+               for pp = 0; pp < len(p); pp++ {
+                       if p[pp] != 0 {
+                               if p[pp] != amem[qq] && amem[qq] != 0 {
+                                       continue nextk
+                               }
+                       }
+                       qq++
+               }
+
+               // we have found an acceptable k
+               if pkdebug != 0 && foutput != nil {
+                       fmt.Fprintf(foutput, "off = %v, k = %v\n", off+rr, rr)
+               }
+               qq = rr
+               for pp = 0; pp < len(p); pp++ {
+                       if p[pp] != 0 {
+                               if qq > memp {
+                                       memp = qq
+                               }
+                               amem[qq] = p[pp]
+                       }
+                       qq++
+               }
+               if pkdebug != 0 && foutput != nil {
+                       for pp = 0; pp <= memp; pp += 10 {
+                               fmt.Fprintf(foutput, "\n")
+                               for qq = pp; qq <= pp+9; qq++ {
+                                       fmt.Fprintf(foutput, "%v ", amem[qq])
+                               }
+                               fmt.Fprintf(foutput, "\n")
+                       }
+               }
+               return off + rr
+       }
+       errorf("no space in action table")
+       return 0
+}
+
+//
+// print the output for the states
+//
+func output() {
+       var c, u, v int
+
+       if !lflag {
+               fmt.Fprintf(ftable, "\n//line yacctab:1")
+       }
+       fmt.Fprintf(ftable, "\nvar %sExca = [...]int{\n", prefix)
+
+       if len(errors) > 0 {
+               stateTable = make([]Row, nstate)
+       }
+
+       noset := mkset()
+
+       // output the stuff for state i
+       for i := 0; i < nstate; i++ {
+               nolook = 0
+               if tystate[i] != MUSTLOOKAHEAD {
+                       nolook = 1
+               }
+               closure(i)
+
+               // output actions
+               nolook = 1
+               aryfil(temp1, ntokens+nnonter+1, 0)
+               for u = 0; u < cwp; u++ {
+                       c = wsets[u].pitem.first
+                       if c > 1 && c < NTBASE && temp1[c] == 0 {
+                               for v = u; v < cwp; v++ {
+                                       if c == wsets[v].pitem.first {
+                                               putitem(wsets[v].pitem, noset)
+                                       }
+                               }
+                               temp1[c] = state(c)
+                       } else if c > NTBASE {
+                               c -= NTBASE
+                               if temp1[c+ntokens] == 0 {
+                                       temp1[c+ntokens] = amem[indgo[i]+c]
+                               }
+                       }
+               }
+               if i == 1 {
+                       temp1[1] = ACCEPTCODE
+               }
+
+               // now, we have the shifts; look at the reductions
+               lastred = 0
+               for u = 0; u < cwp; u++ {
+                       c = wsets[u].pitem.first
+
+                       // reduction
+                       if c > 0 {
+                               continue
+                       }
+                       lastred = -c
+                       us := wsets[u].ws
+                       for k := 0; k <= ntokens; k++ {
+                               if bitset(us, k) == 0 {
+                                       continue
+                               }
+                               if temp1[k] == 0 {
+                                       temp1[k] = c
+                               } else if temp1[k] < 0 { // reduce/reduce conflict
+                                       if foutput != nil {
+                                               fmt.Fprintf(foutput,
+                                                       "\n %v: reduce/reduce conflict  (red'ns "+
+                                                               "%v and %v) on %v",
+                                                       i, -temp1[k], lastred, symnam(k))
+                                       }
+                                       if -temp1[k] > lastred {
+                                               temp1[k] = -lastred
+                                       }
+                                       zzrrconf++
+                               } else {
+                                       // potential shift/reduce conflict
+                                       precftn(lastred, k, i)
+                               }
+                       }
+               }
+               wract(i)
+       }
+
+       fmt.Fprintf(ftable, "}\n")
+       ftable.WriteRune('\n')
+       fmt.Fprintf(ftable, "const %sPrivate = %v\n", prefix, PRIVATE)
+}
+
+//
+// decide a shift/reduce conflict by precedence.
+// r is a rule number, t a token number
+// the conflict is in state s
+// temp1[t] is changed to reflect the action
+//
+func precftn(r, t, s int) {
+       action := NOASC
+
+       lp := levprd[r]
+       lt := toklev[t]
+       if PLEVEL(lt) == 0 || PLEVEL(lp) == 0 {
+               // conflict
+               if foutput != nil {
+                       fmt.Fprintf(foutput,
+                               "\n%v: shift/reduce conflict (shift %v(%v), red'n %v(%v)) on %v",
+                               s, temp1[t], PLEVEL(lt), r, PLEVEL(lp), symnam(t))
+               }
+               zzsrconf++
+               return
+       }
+       if PLEVEL(lt) == PLEVEL(lp) {
+               action = ASSOC(lt)
+       } else if PLEVEL(lt) > PLEVEL(lp) {
+               action = RASC // shift
+       } else {
+               action = LASC
+       } // reduce
+       switch action {
+       case BASC: // error action
+               temp1[t] = ERRCODE
+       case LASC: // reduce
+               temp1[t] = -r
+       }
+}
+
+//
+// output state i
+// temp1 has the actions, lastred the default
+//
+func wract(i int) {
+       var p, p1 int
+
+       // find the best choice for lastred
+       lastred = 0
+       ntimes := 0
+       for j := 0; j <= ntokens; j++ {
+               if temp1[j] >= 0 {
+                       continue
+               }
+               if temp1[j]+lastred == 0 {
+                       continue
+               }
+               // count the number of appearances of temp1[j]
+               count := 0
+               tred := -temp1[j]
+               levprd[tred] |= REDFLAG
+               for p = 0; p <= ntokens; p++ {
+                       if temp1[p]+tred == 0 {
+                               count++
+                       }
+               }
+               if count > ntimes {
+                       lastred = tred
+                       ntimes = count
+               }
+       }
+
+       //
+       // for error recovery, arrange that, if there is a shift on the
+       // error recovery token, `error', that the default be the error action
+       //
+       if temp1[2] > 0 {
+               lastred = 0
+       }
+
+       // clear out entries in temp1 which equal lastred
+       // count entries in optst table
+       n := 0
+       for p = 0; p <= ntokens; p++ {
+               p1 = temp1[p]
+               if p1+lastred == 0 {
+                       temp1[p] = 0
+                       p1 = 0
+               }
+               if p1 > 0 && p1 != ACCEPTCODE && p1 != ERRCODE {
+                       n++
+               }
+       }
+
+       wrstate(i)
+       defact[i] = lastred
+       flag := 0
+       os := make([]int, n*2)
+       n = 0
+       for p = 0; p <= ntokens; p++ {
+               p1 = temp1[p]
+               if p1 != 0 {
+                       if p1 < 0 {
+                               p1 = -p1
+                       } else if p1 == ACCEPTCODE {
+                               p1 = -1
+                       } else if p1 == ERRCODE {
+                               p1 = 0
+                       } else {
+                               os[n] = p
+                               n++
+                               os[n] = p1
+                               n++
+                               zzacent++
+                               continue
+                       }
+                       if flag == 0 {
+                               fmt.Fprintf(ftable, "\t-1, %v,\n", i)
+                       }
+                       flag++
+                       fmt.Fprintf(ftable, "\t%v, %v,\n", p, p1)
+                       zzexcp++
+               }
+       }
+       if flag != 0 {
+               defact[i] = -2
+               fmt.Fprintf(ftable, "\t-2, %v,\n", lastred)
+       }
+       optst[i] = os
+}
+
+//
+// writes state i
+//
+func wrstate(i int) {
+       var j0, j1, u int
+       var pp, qq int
+
+       if len(errors) > 0 {
+               actions := append([]int(nil), temp1...)
+               defaultAction := ERRCODE
+               if lastred != 0 {
+                       defaultAction = -lastred
+               }
+               stateTable[i] = Row{actions, defaultAction}
+       }
+
+       if foutput == nil {
+               return
+       }
+       fmt.Fprintf(foutput, "\nstate %v\n", i)
+       qq = pstate[i+1]
+       for pp = pstate[i]; pp < qq; pp++ {
+               fmt.Fprintf(foutput, "\t%v\n", writem(statemem[pp].pitem))
+       }
+       if tystate[i] == MUSTLOOKAHEAD {
+               // print out empty productions in closure
+               for u = pstate[i+1] - pstate[i]; u < cwp; u++ {
+                       if wsets[u].pitem.first < 0 {
+                               fmt.Fprintf(foutput, "\t%v\n", writem(wsets[u].pitem))
+                       }
+               }
+       }
+
+       // check for state equal to another
+       for j0 = 0; j0 <= ntokens; j0++ {
+               j1 = temp1[j0]
+               if j1 != 0 {
+                       fmt.Fprintf(foutput, "\n\t%v  ", symnam(j0))
+
+                       // shift, error, or accept
+                       if j1 > 0 {
+                               if j1 == ACCEPTCODE {
+                                       fmt.Fprintf(foutput, "accept")
+                               } else if j1 == ERRCODE {
+                                       fmt.Fprintf(foutput, "error")
+                               } else {
+                                       fmt.Fprintf(foutput, "shift %v", j1)
+                               }
+                       } else {
+                               fmt.Fprintf(foutput, "reduce %v (src line %v)", -j1, rlines[-j1])
+                       }
+               }
+       }
+
+       // output the final production
+       if lastred != 0 {
+               fmt.Fprintf(foutput, "\n\t.  reduce %v (src line %v)\n\n",
+                       lastred, rlines[lastred])
+       } else {
+               fmt.Fprintf(foutput, "\n\t.  error\n\n")
+       }
+
+       // now, output nonterminal actions
+       j1 = ntokens
+       for j0 = 1; j0 <= nnonter; j0++ {
+               j1++
+               if temp1[j1] != 0 {
+                       fmt.Fprintf(foutput, "\t%v  goto %v\n", symnam(j0+NTBASE), temp1[j1])
+               }
+       }
+}
+
+//
+// output the gotos for the nontermninals
+//
+func go2out() {
+       for i := 1; i <= nnonter; i++ {
+               go2gen(i)
+
+               // find the best one to make default
+               best := -1
+               times := 0
+
+               // is j the most frequent
+               for j := 0; j < nstate; j++ {
+                       if tystate[j] == 0 {
+                               continue
+                       }
+                       if tystate[j] == best {
+                               continue
+                       }
+
+                       // is tystate[j] the most frequent
+                       count := 0
+                       cbest := tystate[j]
+                       for k := j; k < nstate; k++ {
+                               if tystate[k] == cbest {
+                                       count++
+                               }
+                       }
+                       if count > times {
+                               best = cbest
+                               times = count
+                       }
+               }
+
+               // best is now the default entry
+               zzgobest += times - 1
+               n := 0
+               for j := 0; j < nstate; j++ {
+                       if tystate[j] != 0 && tystate[j] != best {
+                               n++
+                       }
+               }
+               goent := make([]int, 2*n+1)
+               n = 0
+               for j := 0; j < nstate; j++ {
+                       if tystate[j] != 0 && tystate[j] != best {
+                               goent[n] = j
+                               n++
+                               goent[n] = tystate[j]
+                               n++
+                               zzgoent++
+                       }
+               }
+
+               // now, the default
+               if best == -1 {
+                       best = 0
+               }
+
+               zzgoent++
+               goent[n] = best
+               yypgo[i] = goent
+       }
+}
+
+//
+// output the gotos for nonterminal c
+//
+func go2gen(c int) {
+       var i, cc, p, q int
+
+       // first, find nonterminals with gotos on c
+       aryfil(temp1, nnonter+1, 0)
+       temp1[c] = 1
+       work := 1
+       for work != 0 {
+               work = 0
+               for i = 0; i < nprod; i++ {
+                       // cc is a nonterminal with a goto on c
+                       cc = prdptr[i][1] - NTBASE
+                       if cc >= 0 && temp1[cc] != 0 {
+                               // thus, the left side of production i does too
+                               cc = prdptr[i][0] - NTBASE
+                               if temp1[cc] == 0 {
+                                       work = 1
+                                       temp1[cc] = 1
+                               }
+                       }
+               }
+       }
+
+       // now, we have temp1[c] = 1 if a goto on c in closure of cc
+       if g2debug != 0 && foutput != nil {
+               fmt.Fprintf(foutput, "%v: gotos on ", nontrst[c].name)
+               for i = 0; i <= nnonter; i++ {
+                       if temp1[i] != 0 {
+                               fmt.Fprintf(foutput, "%v ", nontrst[i].name)
+                       }
+               }
+               fmt.Fprintf(foutput, "\n")
+       }
+
+       // now, go through and put gotos into tystate
+       aryfil(tystate, nstate, 0)
+       for i = 0; i < nstate; i++ {
+               q = pstate[i+1]
+               for p = pstate[i]; p < q; p++ {
+                       cc = statemem[p].pitem.first
+                       if cc >= NTBASE {
+                               // goto on c is possible
+                               if temp1[cc-NTBASE] != 0 {
+                                       tystate[i] = amem[indgo[i]+c]
+                                       break
+                               }
+                       }
+               }
+       }
+}
+
+//
+// in order to free up the mem and amem arrays for the optimizer,
+// and still be able to output yyr1, etc., after the sizes of
+// the action array is known, we hide the nonterminals
+// derived by productions in levprd.
+//
+func hideprod() {
+       nred := 0
+       levprd[0] = 0
+       for i := 1; i < nprod; i++ {
+               if (levprd[i] & REDFLAG) == 0 {
+                       if foutput != nil {
+                               fmt.Fprintf(foutput, "Rule not reduced: %v\n",
+                                       writem(Pitem{prdptr[i], 0, 0, i}))
+                       }
+                       fmt.Printf("rule %v never reduced\n", writem(Pitem{prdptr[i], 0, 0, i}))
+                       nred++
+               }
+               levprd[i] = prdptr[i][0] - NTBASE
+       }
+       if nred != 0 {
+               fmt.Printf("%v rules never reduced\n", nred)
+       }
+}
+
+func callopt() {
+       var j, k, p, q, i int
+       var v []int
+
+       pgo = make([]int, nnonter+1)
+       pgo[0] = 0
+       maxoff = 0
+       maxspr = 0
+       for i = 0; i < nstate; i++ {
+               k = 32000
+               j = 0
+               v = optst[i]
+               q = len(v)
+               for p = 0; p < q; p += 2 {
+                       if v[p] > j {
+                               j = v[p]
+                       }
+                       if v[p] < k {
+                               k = v[p]
+                       }
+               }
+
+               // nontrivial situation
+               if k <= j {
+                       // j is now the range
+                       //                      j -= k;                 // call scj
+                       if k > maxoff {
+                               maxoff = k
+                       }
+               }
+               tystate[i] = q + 2*j
+               if j > maxspr {
+                       maxspr = j
+               }
+       }
+
+       // initialize ggreed table
+       ggreed = make([]int, nnonter+1)
+       for i = 1; i <= nnonter; i++ {
+               ggreed[i] = 1
+               j = 0
+
+               // minimum entry index is always 0
+               v = yypgo[i]
+               q = len(v) - 1
+               for p = 0; p < q; p += 2 {
+                       ggreed[i] += 2
+                       if v[p] > j {
+                               j = v[p]
+                       }
+               }
+               ggreed[i] = ggreed[i] + 2*j
+               if j > maxoff {
+                       maxoff = j
+               }
+       }
+
+       // now, prepare to put the shift actions into the amem array
+       for i = 0; i < ACTSIZE; i++ {
+               amem[i] = 0
+       }
+       maxa = 0
+       for i = 0; i < nstate; i++ {
+               if tystate[i] == 0 && adb > 1 {
+                       fmt.Fprintf(ftable, "State %v: null\n", i)
+               }
+               indgo[i] = yyFlag
+       }
+
+       i = nxti()
+       for i != NOMORE {
+               if i >= 0 {
+                       stin(i)
+               } else {
+                       gin(-i)
+               }
+               i = nxti()
+       }
+
+       // print amem array
+       if adb > 2 {
+               for p = 0; p <= maxa; p += 10 {
+                       fmt.Fprintf(ftable, "%v  ", p)
+                       for i = 0; i < 10; i++ {
+                               fmt.Fprintf(ftable, "%v  ", amem[p+i])
+                       }
+                       ftable.WriteRune('\n')
+               }
+       }
+
+       aoutput()
+       osummary()
+}
+
+//
+// finds the next i
+//
+func nxti() int {
+       max := 0
+       maxi := 0
+       for i := 1; i <= nnonter; i++ {
+               if ggreed[i] >= max {
+                       max = ggreed[i]
+                       maxi = -i
+               }
+       }
+       for i := 0; i < nstate; i++ {
+               if tystate[i] >= max {
+                       max = tystate[i]
+                       maxi = i
+               }
+       }
+       if max == 0 {
+               return NOMORE
+       }
+       return maxi
+}
+
+func gin(i int) {
+       var s int
+
+       // enter gotos on nonterminal i into array amem
+       ggreed[i] = 0
+
+       q := yypgo[i]
+       nq := len(q) - 1
+
+       // now, find amem place for it
+nextgp:
+       for p := 0; p < ACTSIZE; p++ {
+               if amem[p] != 0 {
+                       continue
+               }
+               for r := 0; r < nq; r += 2 {
+                       s = p + q[r] + 1
+                       if s > maxa {
+                               maxa = s
+                               if maxa >= ACTSIZE {
+                                       errorf("a array overflow")
+                               }
+                       }
+                       if amem[s] != 0 {
+                               continue nextgp
+                       }
+               }
+
+               // we have found amem spot
+               amem[p] = q[nq]
+               if p > maxa {
+                       maxa = p
+               }
+               for r := 0; r < nq; r += 2 {
+                       s = p + q[r] + 1
+                       amem[s] = q[r+1]
+               }
+               pgo[i] = p
+               if adb > 1 {
+                       fmt.Fprintf(ftable, "Nonterminal %v, entry at %v\n", i, pgo[i])
+               }
+               return
+       }
+       errorf("cannot place goto %v\n", i)
+}
+
+func stin(i int) {
+       var s int
+
+       tystate[i] = 0
+
+       // enter state i into the amem array
+       q := optst[i]
+       nq := len(q)
+
+nextn:
+       // find an acceptable place
+       for n := -maxoff; n < ACTSIZE; n++ {
+               flag := 0
+               for r := 0; r < nq; r += 2 {
+                       s = q[r] + n
+                       if s < 0 || s > ACTSIZE {
+                               continue nextn
+                       }
+                       if amem[s] == 0 {
+                               flag++
+                       } else if amem[s] != q[r+1] {
+                               continue nextn
+                       }
+               }
+
+               // check the position equals another only if the states are identical
+               for j := 0; j < nstate; j++ {
+                       if indgo[j] == n {
+
+                               // we have some disagreement
+                               if flag != 0 {
+                                       continue nextn
+                               }
+                               if nq == len(optst[j]) {
+
+                                       // states are equal
+                                       indgo[i] = n
+                                       if adb > 1 {
+                                               fmt.Fprintf(ftable, "State %v: entry at"+
+                                                       "%v equals state %v\n",
+                                                       i, n, j)
+                                       }
+                                       return
+                               }
+
+                               // we have some disagreement
+                               continue nextn
+                       }
+               }
+
+               for r := 0; r < nq; r += 2 {
+                       s = q[r] + n
+                       if s > maxa {
+                               maxa = s
+                       }
+                       if amem[s] != 0 && amem[s] != q[r+1] {
+                               errorf("clobber of a array, pos'n %v, by %v", s, q[r+1])
+                       }
+                       amem[s] = q[r+1]
+               }
+               indgo[i] = n
+               if adb > 1 {
+                       fmt.Fprintf(ftable, "State %v: entry at %v\n", i, indgo[i])
+               }
+               return
+       }
+       errorf("Error; failure to place state %v", i)
+}
+
+//
+// this version is for limbo
+// write out the optimized parser
+//
+func aoutput() {
+       ftable.WriteRune('\n')
+       fmt.Fprintf(ftable, "const %sLast = %v\n", prefix, maxa+1)
+       arout("Act", amem, maxa+1)
+       arout("Pact", indgo, nstate)
+       arout("Pgo", pgo, nnonter+1)
+}
+
+//
+// put out other arrays, copy the parsers
+//
+func others() {
+       var i, j int
+
+       arout("R1", levprd, nprod)
+       aryfil(temp1, nprod, 0)
+
+       //
+       //yyr2 is the number of rules for each production
+       //
+       for i = 1; i < nprod; i++ {
+               temp1[i] = len(prdptr[i]) - 2
+       }
+       arout("R2", temp1, nprod)
+
+       aryfil(temp1, nstate, -1000)
+       for i = 0; i <= ntokens; i++ {
+               for j := tstates[i]; j != 0; j = mstates[j] {
+                       temp1[j] = i
+               }
+       }
+       for i = 0; i <= nnonter; i++ {
+               for j = ntstates[i]; j != 0; j = mstates[j] {
+                       temp1[j] = -i
+               }
+       }
+       arout("Chk", temp1, nstate)
+       arout("Def", defact, nstate)
+
+       // put out token translation tables
+       // table 1 has 0-256
+       aryfil(temp1, 256, 0)
+       c := 0
+       for i = 1; i <= ntokens; i++ {
+               j = tokset[i].value
+               if j >= 0 && j < 256 {
+                       if temp1[j] != 0 {
+                               fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n")
+                               fmt.Printf("    %s and %s\n", tokset[i].name, tokset[temp1[j]].name)
+                               nerrors++
+                       }
+                       temp1[j] = i
+                       if j > c {
+                               c = j
+                       }
+               }
+       }
+       for i = 0; i <= c; i++ {
+               if temp1[i] == 0 {
+                       temp1[i] = YYLEXUNK
+               }
+       }
+       arout("Tok1", temp1, c+1)
+
+       // table 2 has PRIVATE-PRIVATE+256
+       aryfil(temp1, 256, 0)
+       c = 0
+       for i = 1; i <= ntokens; i++ {
+               j = tokset[i].value - PRIVATE
+               if j >= 0 && j < 256 {
+                       if temp1[j] != 0 {
+                               fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n")
+                               fmt.Printf("    %s and %s\n", tokset[i].name, tokset[temp1[j]].name)
+                               nerrors++
+                       }
+                       temp1[j] = i
+                       if j > c {
+                               c = j
+                       }
+               }
+       }
+       arout("Tok2", temp1, c+1)
+
+       // table 3 has everything else
+       ftable.WriteRune('\n')
+       fmt.Fprintf(ftable, "var %sTok3 = [...]int{\n\t", prefix)
+       c = 0
+       for i = 1; i <= ntokens; i++ {
+               j = tokset[i].value
+               if j >= 0 && j < 256 {
+                       continue
+               }
+               if j >= PRIVATE && j < 256+PRIVATE {
+                       continue
+               }
+
+               if c%5 != 0 {
+                       ftable.WriteRune(' ')
+               }
+               fmt.Fprintf(ftable, "%d, %d,", j, i)
+               c++
+               if c%5 == 0 {
+                       fmt.Fprint(ftable, "\n\t")
+               }
+       }
+       if c%5 != 0 {
+               ftable.WriteRune(' ')
+       }
+       fmt.Fprintf(ftable, "%d,\n}\n", 0)
+
+       // Custom error messages.
+       fmt.Fprintf(ftable, "\n")
+       fmt.Fprintf(ftable, "var %sErrorMessages = [...]struct {\n", prefix)
+       fmt.Fprintf(ftable, "\tstate int\n")
+       fmt.Fprintf(ftable, "\ttoken int\n")
+       fmt.Fprintf(ftable, "\tmsg   string\n")
+       fmt.Fprintf(ftable, "}{\n")
+       for _, error := range errors {
+               lineno = error.lineno
+               state, token := runMachine(error.tokens)
+               fmt.Fprintf(ftable, "\t{%v, %v, %s},\n", state, token, error.msg)
+       }
+       fmt.Fprintf(ftable, "}\n")
+
+       // copy parser text
+       ch := getrune(finput)
+       for ch != EOF {
+               ftable.WriteRune(ch)
+               ch = getrune(finput)
+       }
+
+       // copy yaccpar
+       if !lflag {
+               fmt.Fprintf(ftable, "\n//line yaccpar:1\n")
+       }
+
+       parts := strings.SplitN(yaccpar, prefix+"run()", 2)
+       fmt.Fprintf(ftable, "%v", parts[0])
+       ftable.Write(fcode.Bytes())
+       fmt.Fprintf(ftable, "%v", parts[1])
+}
+
+func runMachine(tokens []string) (state, token int) {
+       var stack []int
+       i := 0
+       token = -1
+
+Loop:
+       if token < 0 {
+               token = chfind(2, tokens[i])
+               i++
+       }
+
+       row := stateTable[state]
+
+       c := token
+       if token >= NTBASE {
+               c = token - NTBASE + ntokens
+       }
+       action := row.actions[c]
+       if action == 0 {
+               action = row.defaultAction
+       }
+
+       switch {
+       case action == ACCEPTCODE:
+               errorf("tokens are accepted")
+               return
+       case action == ERRCODE:
+               if token >= NTBASE {
+                       errorf("error at non-terminal token %s", symnam(token))
+               }
+               return
+       case action > 0:
+               // Shift to state action.
+               stack = append(stack, state)
+               state = action
+               token = -1
+               goto Loop
+       default:
+               // Reduce by production -action.
+               prod := prdptr[-action]
+               if rhsLen := len(prod) - 2; rhsLen > 0 {
+                       n := len(stack) - rhsLen
+                       state = stack[n]
+                       stack = stack[:n]
+               }
+               if token >= 0 {
+                       i--
+               }
+               token = prod[0]
+               goto Loop
+       }
+}
+
+func arout(s string, v []int, n int) {
+       s = prefix + s
+       ftable.WriteRune('\n')
+       fmt.Fprintf(ftable, "var %v = [...]int{", s)
+       for i := 0; i < n; i++ {
+               if i%10 == 0 {
+                       fmt.Fprintf(ftable, "\n\t")
+               } else {
+                       ftable.WriteRune(' ')
+               }
+               fmt.Fprintf(ftable, "%d,", v[i])
+       }
+       fmt.Fprintf(ftable, "\n}\n")
+}
+
+//
+// output the summary on y.output
+//
+func summary() {
+       if foutput != nil {
+               fmt.Fprintf(foutput, "\n%v terminals, %v nonterminals\n", ntokens, nnonter+1)
+               fmt.Fprintf(foutput, "%v grammar rules, %v/%v states\n", nprod, nstate, NSTATES)
+               fmt.Fprintf(foutput, "%v shift/reduce, %v reduce/reduce conflicts reported\n", zzsrconf, zzrrconf)
+               fmt.Fprintf(foutput, "%v working sets used\n", len(wsets))
+               fmt.Fprintf(foutput, "memory: parser %v/%v\n", memp, ACTSIZE)
+               fmt.Fprintf(foutput, "%v extra closures\n", zzclose-2*nstate)
+               fmt.Fprintf(foutput, "%v shift entries, %v exceptions\n", zzacent, zzexcp)
+               fmt.Fprintf(foutput, "%v goto entries\n", zzgoent)
+               fmt.Fprintf(foutput, "%v entries saved by goto default\n", zzgobest)
+       }
+       if zzsrconf != 0 || zzrrconf != 0 {
+               fmt.Printf("\nconflicts: ")
+               if zzsrconf != 0 {
+                       fmt.Printf("%v shift/reduce", zzsrconf)
+               }
+               if zzsrconf != 0 && zzrrconf != 0 {
+                       fmt.Printf(", ")
+               }
+               if zzrrconf != 0 {
+                       fmt.Printf("%v reduce/reduce", zzrrconf)
+               }
+               fmt.Printf("\n")
+       }
+}
+
+//
+// write optimizer summary
+//
+func osummary() {
+       if foutput == nil {
+               return
+       }
+       i := 0
+       for p := maxa; p >= 0; p-- {
+               if amem[p] == 0 {
+                       i++
+               }
+       }
+
+       fmt.Fprintf(foutput, "Optimizer space used: output %v/%v\n", maxa+1, ACTSIZE)
+       fmt.Fprintf(foutput, "%v table entries, %v zero\n", maxa+1, i)
+       fmt.Fprintf(foutput, "maximum spread: %v, maximum offset: %v\n", maxspr, maxoff)
+}
+
+//
+// copies and protects "'s in q
+//
+func chcopy(q string) string {
+       s := ""
+       i := 0
+       j := 0
+       for i = 0; i < len(q); i++ {
+               if q[i] == '"' {
+                       s += q[j:i] + "\\"
+                       j = i
+               }
+       }
+       return s + q[j:i]
+}
+
+func usage() {
+       fmt.Fprintf(stderr, "usage: yacc [-o output] [-v parsetable] input\n")
+       exit(1)
+}
+
+func bitset(set Lkset, bit int) int { return set[bit>>5] & (1 << uint(bit&31)) }
+
+func setbit(set Lkset, bit int) { set[bit>>5] |= (1 << uint(bit&31)) }
+
+func mkset() Lkset { return make([]int, tbitset) }
+
+//
+// set a to the union of a and b
+// return 1 if b is not a subset of a, 0 otherwise
+//
+func setunion(a, b []int) int {
+       sub := 0
+       for i := 0; i < tbitset; i++ {
+               x := a[i]
+               y := x | b[i]
+               a[i] = y
+               if y != x {
+                       sub = 1
+               }
+       }
+       return sub
+}
+
+func prlook(p Lkset) {
+       if p == nil {
+               fmt.Fprintf(foutput, "\tNULL")
+               return
+       }
+       fmt.Fprintf(foutput, " { ")
+       for j := 0; j <= ntokens; j++ {
+               if bitset(p, j) != 0 {
+                       fmt.Fprintf(foutput, "%v ", symnam(j))
+               }
+       }
+       fmt.Fprintf(foutput, "}")
+}
+
+//
+// utility routines
+//
+var peekrune rune
+
+func isdigit(c rune) bool { return c >= '0' && c <= '9' }
+
+func isword(c rune) bool {
+       return c >= 0xa0 || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+}
+
+//
+// return 1 if 2 arrays are equal
+// return 0 if not equal
+//
+func aryeq(a []int, b []int) int {
+       n := len(a)
+       if len(b) != n {
+               return 0
+       }
+       for ll := 0; ll < n; ll++ {
+               if a[ll] != b[ll] {
+                       return 0
+               }
+       }
+       return 1
+}
+
+func getrune(f *bufio.Reader) rune {
+       var r rune
+
+       if peekrune != 0 {
+               if peekrune == EOF {
+                       return EOF
+               }
+               r = peekrune
+               peekrune = 0
+               return r
+       }
+
+       c, n, err := f.ReadRune()
+       if n == 0 {
+               return EOF
+       }
+       if err != nil {
+               errorf("read error: %v", err)
+       }
+       //fmt.Printf("rune = %v n=%v\n", string(c), n);
+       return c
+}
+
+func ungetrune(f *bufio.Reader, c rune) {
+       if f != finput {
+               panic("ungetc - not finput")
+       }
+       if peekrune != 0 {
+               panic("ungetc - 2nd unget")
+       }
+       peekrune = c
+}
+
+func open(s string) *bufio.Reader {
+       fi, err := os.Open(s)
+       if err != nil {
+               errorf("error opening %v: %v", s, err)
+       }
+       //fmt.Printf("open %v\n", s);
+       return bufio.NewReader(fi)
+}
+
+func create(s string) *bufio.Writer {
+       fo, err := os.Create(s)
+       if err != nil {
+               errorf("error creating %v: %v", s, err)
+       }
+       //fmt.Printf("create %v mode %v\n", s);
+       return bufio.NewWriter(fo)
+}
+
+//
+// write out error comment
+//
+func lerrorf(lineno int, s string, v ...interface{}) {
+       nerrors++
+       fmt.Fprintf(stderr, s, v...)
+       fmt.Fprintf(stderr, ": %v:%v\n", infile, lineno)
+       if fatfl != 0 {
+               summary()
+               exit(1)
+       }
+}
+
+func errorf(s string, v ...interface{}) {
+       lerrorf(lineno, s, v...)
+}
+
+func exit(status int) {
+       if ftable != nil {
+               ftable.Flush()
+               ftable = nil
+               gofmt()
+       }
+       if foutput != nil {
+               foutput.Flush()
+               foutput = nil
+       }
+       if stderr != nil {
+               stderr.Flush()
+               stderr = nil
+       }
+       os.Exit(status)
+}
+
+func gofmt() {
+       src, err := ioutil.ReadFile(oflag)
+       if err != nil {
+               return
+       }
+       src, err = format.Source(src)
+       if err != nil {
+               return
+       }
+       ioutil.WriteFile(oflag, src, 0666)
+}
+
+var yaccpar string // will be processed version of yaccpartext: s/$$/prefix/g
+var yaccpartext = `
+/*     parser for yacc output  */
+
+var (
+       $$Debug        = 0
+       $$ErrorVerbose = false
+)
+
+type $$Lexer interface {
+       Lex(lval *$$SymType) int
+       Error(s string)
+}
+
+type $$Parser interface {
+       Parse($$Lexer) int
+       Lookahead() int
+}
+
+type $$ParserImpl struct {
+       lval  $$SymType
+       stack [$$InitialStackSize]$$SymType
+       char  int
+}
+
+func (p *$$ParserImpl) Lookahead() int {
+       return p.char
+}
+
+func $$NewParser() $$Parser {
+       return &$$ParserImpl{}
+}
+
+const $$Flag = -1000
+
+func $$Tokname(c int) string {
+       if c >= 1 && c-1 < len($$Toknames) {
+               if $$Toknames[c-1] != "" {
+                       return $$Toknames[c-1]
+               }
+       }
+       return __yyfmt__.Sprintf("tok-%v", c)
+}
+
+func $$Statname(s int) string {
+       if s >= 0 && s < len($$Statenames) {
+               if $$Statenames[s] != "" {
+                       return $$Statenames[s]
+               }
+       }
+       return __yyfmt__.Sprintf("state-%v", s)
+}
+
+func $$ErrorMessage(state, lookAhead int) string {
+       const TOKSTART = 4
+
+       if !$$ErrorVerbose {
+               return "syntax error"
+       }
+
+       for _, e := range $$ErrorMessages {
+               if e.state == state && e.token == lookAhead {
+                       return "syntax error: " + e.msg
+               }
+       }
+
+       res := "syntax error: unexpected " + $$Tokname(lookAhead)
+
+       // To match Bison, suggest at most four expected tokens.
+       expected := make([]int, 0, 4)
+
+       // Look for shiftable tokens.
+       base := $$Pact[state]
+       for tok := TOKSTART; tok-1 < len($$Toknames); tok++ {
+               if n := base + tok; n >= 0 && n < $$Last && $$Chk[$$Act[n]] == tok {
+                       if len(expected) == cap(expected) {
+                               return res
+                       }
+                       expected = append(expected, tok)
+               }
+       }
+
+       if $$Def[state] == -2 {
+               i := 0
+               for $$Exca[i] != -1 || $$Exca[i+1] != state {
+                       i += 2
+               }
+
+               // Look for tokens that we accept or reduce.
+               for i += 2; $$Exca[i] >= 0; i += 2 {
+                       tok := $$Exca[i]
+                       if tok < TOKSTART || $$Exca[i+1] == 0 {
+                               continue
+                       }
+                       if len(expected) == cap(expected) {
+                               return res
+                       }
+                       expected = append(expected, tok)
+               }
+
+               // If the default action is to accept or reduce, give up.
+               if $$Exca[i+1] != 0 {
+                       return res
+               }
+       }
+
+       for i, tok := range expected {
+               if i == 0 {
+                       res += ", expecting "
+               } else {
+                       res += " or "
+               }
+               res += $$Tokname(tok)
+       }
+       return res
+}
+
+func $$lex1(lex $$Lexer, lval *$$SymType) (char, token int) {
+       token = 0
+       char = lex.Lex(lval)
+       if char <= 0 {
+               token = $$Tok1[0]
+               goto out
+       }
+       if char < len($$Tok1) {
+               token = $$Tok1[char]
+               goto out
+       }
+       if char >= $$Private {
+               if char < $$Private+len($$Tok2) {
+                       token = $$Tok2[char-$$Private]
+                       goto out
+               }
+       }
+       for i := 0; i < len($$Tok3); i += 2 {
+               token = $$Tok3[i+0]
+               if token == char {
+                       token = $$Tok3[i+1]
+                       goto out
+               }
+       }
+
+out:
+       if token == 0 {
+               token = $$Tok2[1] /* unknown char */
+       }
+       if $$Debug >= 3 {
+               __yyfmt__.Printf("lex %s(%d)\n", $$Tokname(token), uint(char))
+       }
+       return char, token
+}
+
+func $$Parse($$lex $$Lexer) int {
+       return $$NewParser().Parse($$lex)
+}
+
+func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int {
+       var $$n int
+       var $$VAL $$SymType
+       var $$Dollar []$$SymType
+       _ = $$Dollar // silence set and not used
+       $$S := $$rcvr.stack[:]
+
+       Nerrs := 0   /* number of errors */
+       Errflag := 0 /* error recovery flag */
+       $$state := 0
+       $$rcvr.char = -1
+       $$token := -1 // $$rcvr.char translated into internal numbering
+       defer func() {
+               // Make sure we report no lookahead when not parsing.
+               $$state = -1
+               $$rcvr.char = -1
+               $$token = -1
+       }()
+       $$p := -1
+       goto $$stack
+
+ret0:
+       return 0
+
+ret1:
+       return 1
+
+$$stack:
+       /* put a state and value onto the stack */
+       if $$Debug >= 4 {
+               __yyfmt__.Printf("char %v in %v\n", $$Tokname($$token), $$Statname($$state))
+       }
+
+       $$p++
+       if $$p >= len($$S) {
+               nyys := make([]$$SymType, len($$S)*2)
+               copy(nyys, $$S)
+               $$S = nyys
+       }
+       $$S[$$p] = $$VAL
+       $$S[$$p].yys = $$state
+
+$$newstate:
+       $$n = $$Pact[$$state]
+       if $$n <= $$Flag {
+               goto $$default /* simple state */
+       }
+       if $$rcvr.char < 0 {
+               $$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)
+       }
+       $$n += $$token
+       if $$n < 0 || $$n >= $$Last {
+               goto $$default
+       }
+       $$n = $$Act[$$n]
+       if $$Chk[$$n] == $$token { /* valid shift */
+               $$rcvr.char = -1
+               $$token = -1
+               $$VAL = $$rcvr.lval
+               $$state = $$n
+               if Errflag > 0 {
+                       Errflag--
+               }
+               goto $$stack
+       }
+
+$$default:
+       /* default state action */
+       $$n = $$Def[$$state]
+       if $$n == -2 {
+               if $$rcvr.char < 0 {
+                       $$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)
+               }
+
+               /* look through exception table */
+               xi := 0
+               for {
+                       if $$Exca[xi+0] == -1 && $$Exca[xi+1] == $$state {
+                               break
+                       }
+                       xi += 2
+               }
+               for xi += 2; ; xi += 2 {
+                       $$n = $$Exca[xi+0]
+                       if $$n < 0 || $$n == $$token {
+                               break
+                       }
+               }
+               $$n = $$Exca[xi+1]
+               if $$n < 0 {
+                       goto ret0
+               }
+       }
+       if $$n == 0 {
+               /* error ... attempt to resume parsing */
+               switch Errflag {
+               case 0: /* brand new error */
+                       $$lex.Error($$ErrorMessage($$state, $$token))
+                       Nerrs++
+                       if $$Debug >= 1 {
+                               __yyfmt__.Printf("%s", $$Statname($$state))
+                               __yyfmt__.Printf(" saw %s\n", $$Tokname($$token))
+                       }
+                       fallthrough
+
+               case 1, 2: /* incompletely recovered error ... try again */
+                       Errflag = 3
+
+                       /* find a state where "error" is a legal shift action */
+                       for $$p >= 0 {
+                               $$n = $$Pact[$$S[$$p].yys] + $$ErrCode
+                               if $$n >= 0 && $$n < $$Last {
+                                       $$state = $$Act[$$n] /* simulate a shift of "error" */
+                                       if $$Chk[$$state] == $$ErrCode {
+                                               goto $$stack
+                                       }
+                               }
+
+                               /* the current p has no shift on "error", pop stack */
+                               if $$Debug >= 2 {
+                                       __yyfmt__.Printf("error recovery pops state %d\n", $$S[$$p].yys)
+                               }
+                               $$p--
+                       }
+                       /* there is no state on the stack with an error shift ... abort */
+                       goto ret1
+
+               case 3: /* no shift yet; clobber input char */
+                       if $$Debug >= 2 {
+                               __yyfmt__.Printf("error recovery discards %s\n", $$Tokname($$token))
+                       }
+                       if $$token == $$EofCode {
+                               goto ret1
+                       }
+                       $$rcvr.char = -1
+                       $$token = -1
+                       goto $$newstate /* try again in the same state */
+               }
+       }
+
+       /* reduction by production $$n */
+       if $$Debug >= 2 {
+               __yyfmt__.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
+       }
+
+       $$nt := $$n
+       $$pt := $$p
+       _ = $$pt // guard against "declared and not used"
+
+       $$p -= $$R2[$$n]
+       // $$p is now the index of $0. Perform the default action. Iff the
+       // reduced production is ε, $1 is possibly out of range.
+       if $$p+1 >= len($$S) {
+               nyys := make([]$$SymType, len($$S)*2)
+               copy(nyys, $$S)
+               $$S = nyys
+       }
+       $$VAL = $$S[$$p+1]
+
+       /* consult goto table to find next state */
+       $$n = $$R1[$$n]
+       $$g := $$Pgo[$$n]
+       $$j := $$g + $$S[$$p].yys + 1
+
+       if $$j >= $$Last {
+               $$state = $$Act[$$g]
+       } else {
+               $$state = $$Act[$$j]
+               if $$Chk[$$state] != -$$n {
+                       $$state = $$Act[$$g]
+               }
+       }
+       // dummy call; replaced with literal code
+       $$run()
+       goto $$stack /* stack new state and value */
+}
+`