github.com/team-ide/go-dialect@v1.9.20/vitess/sqlparser/goyacc/goyacc.go (about)

     1  /*
     2  Derived from Inferno's utils/iyacc/yacc.c
     3  http://code.google.com/p/inferno-os/source/browse/utils/iyacc/yacc.c
     4  
     5  This copyright NOTICE applies to all files in this directory and
     6  subdirectories, unless another copyright notice appears in a given
     7  file or subdirectory.  If you take substantial code from this software to use in
     8  other programs, you must somehow include with it an appropriate
     9  copyright notice that includes the copyright notice and the other
    10  notices below.  It is fine (and often tidier) to do that in a separate
    11  file such as NOTICE, LICENCE or COPYING.
    12  
    13  	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
    14  	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
    15  	Portions Copyright © 1997-1999 Vita Nuova Limited
    16  	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
    17  	Portions Copyright © 2004,2006 Bruce Ellis
    18  	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    19  	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    20  	Portions Copyright © 2009 The Go Authors. All rights reserved.
    21  	Portions Copyright © 2021 The Vitess Authors.
    22  
    23  Permission is hereby granted, free of charge, to any person obtaining a copy
    24  of this software and associated documentation files (the "Software"), to deal
    25  in the Software without restriction, including without limitation the rights
    26  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    27  copies of the Software, and to permit persons to whom the Software is
    28  furnished to do so, subject to the following conditions:
    29  
    30  The above copyright notice and this permission notice shall be included in
    31  all copies or substantial portions of the Software.
    32  
    33  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    34  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    35  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    36  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    37  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    38  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    39  THE SOFTWARE.
    40  */
    41  
    42  package main
    43  
    44  // yacc
    45  // major difference is lack of stem ("y" variable)
    46  //
    47  
    48  import (
    49  	"bufio"
    50  	"bytes"
    51  	"flag"
    52  	"fmt"
    53  	"go/format"
    54  	"os"
    55  	"regexp"
    56  	"sort"
    57  	"strconv"
    58  	"strings"
    59  	"unicode"
    60  )
    61  
    62  // the following are adjustable
    63  // according to memory size
    64  const (
    65  	ACTSIZE  = 120000
    66  	NSTATES  = 8000
    67  	TEMPSIZE = 8000
    68  
    69  	SYMINC   = 50  // increase for non-term or term
    70  	RULEINC  = 50  // increase for max rule length prodptr[i]
    71  	PRODINC  = 100 // increase for productions     prodptr
    72  	WSETINC  = 50  // increase for working sets    wsets
    73  	STATEINC = 200 // increase for states          statemem
    74  
    75  	PRIVATE = 0xE000 // unicode private use
    76  
    77  	// relationships which must hold:
    78  	//	TEMPSIZE >= NTERMS + NNONTERM + 1;
    79  	//	TEMPSIZE >= NSTATES;
    80  	//
    81  
    82  	NTBASE     = 010000
    83  	ERRCODE    = 8190
    84  	ACCEPTCODE = 8191
    85  	YYLEXUNK   = 3
    86  	TOKSTART   = 4 //index of first defined token
    87  )
    88  
    89  // no, left, right, binary assoc.
    90  const (
    91  	LASC = iota + 1
    92  	RASC
    93  	BASC
    94  )
    95  
    96  // flags for state generation
    97  const (
    98  	DONE = iota
    99  	MUSTDO
   100  	MUSTLOOKAHEAD
   101  )
   102  
   103  // flags for a rule having an action, and being reduced
   104  const (
   105  	ACTFLAG = 1 << (iota + 2)
   106  	REDFLAG
   107  )
   108  
   109  // output parser flags
   110  const yyFlag = -1000
   111  
   112  // parse tokens
   113  const (
   114  	IDENTIFIER = PRIVATE + iota
   115  	MARK
   116  	TERM
   117  	LEFT
   118  	RIGHT
   119  	BINARY
   120  	PREC
   121  	LCURLY
   122  	IDENTCOLON
   123  	NUMBER
   124  	START
   125  	TYPEDEF
   126  	TYPENAME
   127  	STRUCT
   128  	UNION
   129  	ERROR
   130  )
   131  
   132  const ENDFILE = 0
   133  const EMPTY = 1
   134  const WHOKNOWS = 0
   135  const OK = 1
   136  const NOMORE = -1000
   137  
   138  // macros for getting associativity and precedence levels
   139  func ASSOC(i int) int { return i & 3 }
   140  
   141  func PLEVEL(i int) int { return (i >> 4) & 077 }
   142  
   143  func TYPE(i int) int { return (i >> 10) & 077 }
   144  
   145  // macros for setting associativity and precedence levels
   146  func SETASC(i, j int) int { return i | j }
   147  
   148  func SETPLEV(i, j int) int { return i | (j << 4) }
   149  
   150  func SETTYPE(i, j int) int { return i | (j << 10) }
   151  
   152  // I/O descriptors
   153  var finput *bufio.Reader // input file
   154  var stderr *bufio.Writer
   155  var ftable *bufio.Writer     // y.go file
   156  var fcode = &bytes.Buffer{}  // saved code
   157  var ftypes = &bytes.Buffer{} // saved type definitions
   158  var foutput *bufio.Writer    // y.output file
   159  
   160  var writtenImports bool // output file has recorded an import of "fmt"
   161  
   162  var oflag string  // -o [y.go]		- y.go file
   163  var vflag string  // -v [y.output]	- y.output file
   164  var lflag bool    // -l			- disable line directives
   165  var prefix string // name prefix for identifiers, default yy
   166  var allowFastAppend bool
   167  
   168  func init() {
   169  	flag.StringVar(&oflag, "o", "y.go", "parser output")
   170  	flag.StringVar(&prefix, "p", "yy", "name prefix to use in generated code")
   171  	flag.StringVar(&vflag, "v", "y.output", "create parsing tables")
   172  	flag.BoolVar(&lflag, "l", false, "disable line directives")
   173  	flag.BoolVar(&allowFastAppend, "fast-append", false, "enable fast-append optimization")
   174  }
   175  
   176  var initialstacksize = 16
   177  
   178  // communication variables between various I/O routines
   179  var infile string  // input file name
   180  var numbval int    // value of an input number
   181  var tokname string // input token name, slop for runes and 0
   182  var tokflag = false
   183  
   184  // structure declarations
   185  type Lkset []int
   186  
   187  type Pitem struct {
   188  	prod   []int
   189  	off    int // offset within the production
   190  	first  int // first term or non-term in item
   191  	prodno int // production number for sorting
   192  }
   193  
   194  type Item struct {
   195  	pitem Pitem
   196  	look  Lkset
   197  }
   198  
   199  type Symb struct {
   200  	name    string
   201  	noconst bool
   202  	value   int
   203  }
   204  
   205  type Wset struct {
   206  	pitem Pitem
   207  	flag  int
   208  	ws    Lkset
   209  }
   210  
   211  // storage of types
   212  var ntypes int                     // number of types defined
   213  var typeset = make(map[int]string) // pointers to type tags
   214  
   215  // token information
   216  
   217  var ntokens = 0 // number of tokens
   218  var tokset []Symb
   219  var toklev []int // vector with the precedence of the terminals
   220  
   221  // nonterminal information
   222  
   223  var nnonter = -1 // the number of nonterminals
   224  var nontrst []Symb
   225  var start int // start symbol
   226  
   227  // state information
   228  
   229  var nstate = 0                      // number of states
   230  var pstate = make([]int, NSTATES+2) // index into statemem to the descriptions of the states
   231  var statemem []Item
   232  var tystate = make([]int, NSTATES) // contains type information about the states
   233  var tstates []int                  // states generated by terminal gotos
   234  var ntstates []int                 // states generated by nonterminal gotos
   235  var mstates = make([]int, NSTATES) // chain of overflows of term/nonterm generation lists
   236  var lastred int                    // number of last reduction of a state
   237  var defact = make([]int, NSTATES)  // default actions of states
   238  
   239  // lookahead set information
   240  
   241  var nolook = 0  // flag to turn off lookahead computations
   242  var tbitset = 0 // size of lookahead sets
   243  var clset Lkset // temporary storage for lookahead computations
   244  
   245  // working set information
   246  
   247  var wsets []Wset
   248  var cwp int
   249  
   250  // storage for action table
   251  
   252  var amem []int                   // action table storage
   253  var memp int                     // next free action table position
   254  var indgo = make([]int, NSTATES) // index to the stored goto table
   255  
   256  // temporary vector, indexable by states, terms, or ntokens
   257  
   258  var temp1 = make([]int, TEMPSIZE) // temporary storage, indexed by terms + ntokens or states
   259  var lineno = 1                    // current input line number
   260  var fatfl = 1                     // if on, error is fatal
   261  var nerrors = 0                   // number of errors
   262  
   263  // assigned token type values
   264  
   265  var extval = 0
   266  
   267  // grammar rule information
   268  
   269  var nprod = 1      // number of productions
   270  var prdptr [][]int // pointers to descriptions of productions
   271  var levprd []int   // precedence levels for the productions
   272  var rlines []int   // line number for this rule
   273  
   274  // statistics collection variables
   275  
   276  var zzgoent = 0
   277  var zzgobest = 0
   278  var zzacent = 0
   279  var zzexcp = 0
   280  var zzclose = 0
   281  var zzrrconf = 0
   282  var zzsrconf = 0
   283  var zzstate = 0
   284  
   285  // optimizer arrays
   286  
   287  var yypgo [][]int
   288  var optst [][]int
   289  var ggreed []int
   290  var pgo []int
   291  
   292  var maxspr int // maximum spread of any entry
   293  var maxoff int // maximum offset into a array
   294  var maxa int
   295  
   296  // storage for information about the nonterminals
   297  
   298  var pres [][][]int // vector of pointers to productions yielding each nonterminal
   299  var pfirst []Lkset
   300  var pempty []int // vector of nonterminals nontrivially deriving e
   301  
   302  // random stuff picked out from between functions
   303  
   304  var indebug = 0 // debugging flag for cpfir
   305  var pidebug = 0 // debugging flag for putitem
   306  var gsdebug = 0 // debugging flag for stagen
   307  var cldebug = 0 // debugging flag for closure
   308  var pkdebug = 0 // debugging flag for apack
   309  var g2debug = 0 // debugging for go2gen
   310  var adb = 0     // debugging for callopt
   311  
   312  type Resrv struct {
   313  	name  string
   314  	value int
   315  }
   316  
   317  var resrv = []Resrv{
   318  	{"binary", BINARY},
   319  	{"left", LEFT},
   320  	{"nonassoc", BINARY},
   321  	{"prec", PREC},
   322  	{"right", RIGHT},
   323  	{"start", START},
   324  	{"term", TERM},
   325  	{"token", TERM},
   326  	{"type", TYPEDEF},
   327  	{"union", UNION},
   328  	{"struct", STRUCT},
   329  	{"error", ERROR},
   330  }
   331  
   332  type Error struct {
   333  	lineno int
   334  	tokens []string
   335  	msg    string
   336  }
   337  
   338  var errors []Error
   339  
   340  type Row struct {
   341  	actions       []int
   342  	defaultAction int
   343  }
   344  
   345  var stateTable []Row
   346  
   347  var zznewstate = 0
   348  
   349  const EOF = -1
   350  
   351  func main() {
   352  
   353  	setup() // initialize and read productions
   354  
   355  	tbitset = (ntokens + 32) / 32
   356  	cpres()  // make table of which productions yield a given nonterminal
   357  	cempty() // make a table of which nonterminals can match the empty string
   358  	cpfir()  // make a table of firsts of nonterminals
   359  
   360  	stagen() // generate the states
   361  
   362  	yypgo = make([][]int, nnonter+1)
   363  	optst = make([][]int, nstate)
   364  	output() // write the states and the tables
   365  	go2out()
   366  
   367  	hideprod()
   368  	summary()
   369  
   370  	callopt()
   371  
   372  	typeinfo()
   373  	others()
   374  
   375  	exit(0)
   376  }
   377  
   378  func setup() {
   379  	var j, ty int
   380  
   381  	stderr = bufio.NewWriter(os.Stderr)
   382  	foutput = nil
   383  
   384  	flag.Parse()
   385  	if flag.NArg() != 1 {
   386  		usage()
   387  	}
   388  	if initialstacksize < 1 {
   389  		// never set so cannot happen
   390  		fmt.Fprintf(stderr, "yacc: stack size too small\n")
   391  		usage()
   392  	}
   393  	yaccpar = strings.Replace(yaccpartext, "$$", prefix, -1)
   394  	openup()
   395  
   396  	fmt.Fprintf(ftable, "// Code generated by goyacc %s. DO NOT EDIT.\n", strings.Join(os.Args[1:], " "))
   397  
   398  	defin(0, "$end")
   399  	extval = PRIVATE // tokens start in unicode 'private use'
   400  	defin(0, "error")
   401  	defin(1, "$accept")
   402  	defin(0, "$unk")
   403  	i := 0
   404  
   405  	t := gettok()
   406  
   407  outer:
   408  	for {
   409  		switch t {
   410  		default:
   411  			errorf("syntax error tok=%v", t-PRIVATE)
   412  
   413  		case MARK, ENDFILE:
   414  			break outer
   415  
   416  		case ';':
   417  			// Do nothing.
   418  
   419  		case START:
   420  			t = gettok()
   421  			if t != IDENTIFIER {
   422  				errorf("bad %%start construction")
   423  			}
   424  			start = chfind(1, tokname)
   425  
   426  		case ERROR:
   427  			lno := lineno
   428  			var tokens []string
   429  			for {
   430  				t := gettok()
   431  				if t == ':' {
   432  					break
   433  				}
   434  				if t != IDENTIFIER && t != IDENTCOLON {
   435  					errorf("bad syntax in %%error")
   436  				}
   437  				tokens = append(tokens, tokname)
   438  				if t == IDENTCOLON {
   439  					break
   440  				}
   441  			}
   442  			if gettok() != IDENTIFIER {
   443  				errorf("bad syntax in %%error")
   444  			}
   445  			errors = append(errors, Error{lno, tokens, tokname})
   446  
   447  		case TYPEDEF:
   448  			t = gettok()
   449  			if t != TYPENAME {
   450  				errorf("bad syntax in %%type")
   451  			}
   452  			ty = numbval
   453  			for {
   454  				t = gettok()
   455  				switch t {
   456  				case IDENTIFIER:
   457  					t = chfind(1, tokname)
   458  					if t < NTBASE {
   459  						j = TYPE(toklev[t])
   460  						if j != 0 && j != ty {
   461  							errorf("type redeclaration of token %s",
   462  								tokset[t].name)
   463  						} else {
   464  							toklev[t] = SETTYPE(toklev[t], ty)
   465  						}
   466  					} else {
   467  						j = nontrst[t-NTBASE].value
   468  						if j != 0 && j != ty {
   469  							errorf("type redeclaration of nonterminal %v",
   470  								nontrst[t-NTBASE].name)
   471  						} else {
   472  							nontrst[t-NTBASE].value = ty
   473  						}
   474  					}
   475  					continue
   476  
   477  				case ',':
   478  					continue
   479  				}
   480  				break
   481  			}
   482  			continue
   483  
   484  		case UNION:
   485  			parsetypes(true)
   486  
   487  		case STRUCT:
   488  			parsetypes(false)
   489  
   490  		case LEFT, BINARY, RIGHT, TERM:
   491  			// nonzero means new prec. and assoc.
   492  			lev := t - TERM
   493  			if lev != 0 {
   494  				i++
   495  			}
   496  			ty = 0
   497  
   498  			// get identifiers so defined
   499  			t = gettok()
   500  
   501  			// there is a type defined
   502  			if t == TYPENAME {
   503  				ty = numbval
   504  				t = gettok()
   505  			}
   506  			for {
   507  				switch t {
   508  				case ',':
   509  					t = gettok()
   510  					continue
   511  
   512  				case ';':
   513  					// Do nothing.
   514  
   515  				case IDENTIFIER:
   516  					j = chfind(0, tokname)
   517  					if j >= NTBASE {
   518  						errorf("%v defined earlier as nonterminal", tokname)
   519  					}
   520  					if lev != 0 {
   521  						if ASSOC(toklev[j]) != 0 {
   522  							errorf("redeclaration of precedence of %v", tokname)
   523  						}
   524  						toklev[j] = SETASC(toklev[j], lev)
   525  						toklev[j] = SETPLEV(toklev[j], i)
   526  					}
   527  					if ty != 0 {
   528  						if TYPE(toklev[j]) != 0 {
   529  							errorf("redeclaration of type of %v", tokname)
   530  						}
   531  						toklev[j] = SETTYPE(toklev[j], ty)
   532  					}
   533  					t = gettok()
   534  					if t == NUMBER {
   535  						tokset[j].value = numbval
   536  						t = gettok()
   537  					}
   538  
   539  					continue
   540  				}
   541  				break
   542  			}
   543  			continue
   544  
   545  		case LCURLY:
   546  			cpycode()
   547  		}
   548  		t = gettok()
   549  	}
   550  
   551  	if t == ENDFILE {
   552  		errorf("unexpected EOF before %%")
   553  	}
   554  
   555  	fmt.Fprintf(fcode, "switch %snt {\n", prefix)
   556  
   557  	moreprod()
   558  	prdptr[0] = []int{NTBASE, start, 1, 0}
   559  
   560  	nprod = 1
   561  	curprod := make([]int, RULEINC)
   562  	t = gettok()
   563  	if t != IDENTCOLON {
   564  		errorf("bad syntax on first rule")
   565  	}
   566  
   567  	if start == 0 {
   568  		prdptr[0][1] = chfind(1, tokname)
   569  	}
   570  
   571  	// read rules
   572  	// put into prdptr array in the format
   573  	// target
   574  	// followed by id's of terminals and non-terminals
   575  	// followed by -nprod
   576  
   577  	for t != MARK && t != ENDFILE {
   578  		mem := 0
   579  
   580  		// process a rule
   581  		rlines[nprod] = lineno
   582  		ruleline := lineno
   583  		if t == '|' {
   584  			curprod[mem] = prdptr[nprod-1][0]
   585  			mem++
   586  		} else if t == IDENTCOLON {
   587  			curprod[mem] = chfind(1, tokname)
   588  			if curprod[mem] < NTBASE {
   589  				lerrorf(ruleline, "token illegal on LHS of grammar rule")
   590  			}
   591  			mem++
   592  		} else {
   593  			lerrorf(ruleline, "illegal rule: missing semicolon or | ?")
   594  		}
   595  
   596  		// read rule body
   597  		t = gettok()
   598  		for {
   599  			for t == IDENTIFIER {
   600  				curprod[mem] = chfind(1, tokname)
   601  				if curprod[mem] < NTBASE {
   602  					levprd[nprod] = toklev[curprod[mem]]
   603  				}
   604  				mem++
   605  				if mem >= len(curprod) {
   606  					ncurprod := make([]int, mem+RULEINC)
   607  					copy(ncurprod, curprod)
   608  					curprod = ncurprod
   609  				}
   610  				t = gettok()
   611  			}
   612  			if t == PREC {
   613  				if gettok() != IDENTIFIER {
   614  					lerrorf(ruleline, "illegal %%prec syntax")
   615  				}
   616  				j = chfind(2, tokname)
   617  				if j >= NTBASE {
   618  					lerrorf(ruleline, "nonterminal "+nontrst[j-NTBASE].name+" illegal after %%prec")
   619  				}
   620  				levprd[nprod] = toklev[j]
   621  				t = gettok()
   622  			}
   623  			if t != '=' {
   624  				break
   625  			}
   626  			levprd[nprod] |= ACTFLAG
   627  			fmt.Fprintf(fcode, "\n\tcase %v:", nprod)
   628  			fmt.Fprintf(fcode, "\n\t\t%sDollar = %sS[%spt-%v:%spt+1]", prefix, prefix, prefix, mem-1, prefix)
   629  
   630  			var act bytes.Buffer
   631  			var unionType string
   632  			cpyact(&act, curprod, mem, &unionType)
   633  
   634  			if unionType != "" {
   635  				fmt.Fprintf(fcode, "\n\t\tvar %sLOCAL %s", prefix, unionType)
   636  			}
   637  			fcode.Write(act.Bytes())
   638  			if unionType != "" {
   639  				fmt.Fprintf(fcode, "\n\t\t%sVAL.union = %sLOCAL", prefix, prefix)
   640  			}
   641  
   642  			// action within rule...
   643  			t = gettok()
   644  			if t == IDENTIFIER {
   645  				// make it a nonterminal
   646  				j = chfind(1, fmt.Sprintf("$$%v", nprod))
   647  
   648  				//
   649  				// the current rule will become rule number nprod+1
   650  				// enter null production for action
   651  				//
   652  				prdptr[nprod] = make([]int, 2)
   653  				prdptr[nprod][0] = j
   654  				prdptr[nprod][1] = -nprod
   655  
   656  				// update the production information
   657  				nprod++
   658  				moreprod()
   659  				levprd[nprod] = levprd[nprod-1] & ^ACTFLAG
   660  				levprd[nprod-1] = ACTFLAG
   661  				rlines[nprod] = lineno
   662  
   663  				// make the action appear in the original rule
   664  				curprod[mem] = j
   665  				mem++
   666  				if mem >= len(curprod) {
   667  					ncurprod := make([]int, mem+RULEINC)
   668  					copy(ncurprod, curprod)
   669  					curprod = ncurprod
   670  				}
   671  			}
   672  		}
   673  
   674  		for t == ';' {
   675  			t = gettok()
   676  		}
   677  		curprod[mem] = -nprod
   678  		mem++
   679  
   680  		// check that default action is reasonable
   681  		if ntypes != 0 && (levprd[nprod]&ACTFLAG) == 0 &&
   682  			nontrst[curprod[0]-NTBASE].value != 0 {
   683  			// no explicit action, LHS has value
   684  			tempty := curprod[1]
   685  			if tempty < 0 {
   686  				lerrorf(ruleline, "must return a value, since LHS has a type")
   687  			}
   688  			if tempty >= NTBASE {
   689  				tempty = nontrst[tempty-NTBASE].value
   690  			} else {
   691  				tempty = TYPE(toklev[tempty])
   692  			}
   693  			if tempty != nontrst[curprod[0]-NTBASE].value {
   694  				lerrorf(ruleline, "default action causes potential type clash")
   695  			}
   696  		}
   697  		moreprod()
   698  		prdptr[nprod] = make([]int, mem)
   699  		copy(prdptr[nprod], curprod)
   700  		nprod++
   701  		moreprod()
   702  		levprd[nprod] = 0
   703  	}
   704  
   705  	if TEMPSIZE < ntokens+nnonter+1 {
   706  		errorf("too many tokens (%d) or non-terminals (%d)", ntokens, nnonter)
   707  	}
   708  
   709  	//
   710  	// end of all rules
   711  	// dump out the prefix code
   712  	//
   713  
   714  	fmt.Fprintf(fcode, "\n\t}")
   715  
   716  	// put out non-literal terminals
   717  	for i := TOKSTART; i <= ntokens; i++ {
   718  		// non-literals
   719  		if !tokset[i].noconst {
   720  			fmt.Fprintf(ftable, "const %v = %v\n", tokset[i].name, tokset[i].value)
   721  		}
   722  	}
   723  
   724  	// put out names of tokens
   725  	ftable.WriteRune('\n')
   726  	fmt.Fprintf(ftable, "var %sToknames = [...]string{\n", prefix)
   727  	for i := 1; i <= ntokens; i++ {
   728  		fmt.Fprintf(ftable, "\t%q,\n", tokset[i].name)
   729  	}
   730  	fmt.Fprintf(ftable, "}\n")
   731  
   732  	// put out names of states.
   733  	// commented out to avoid a huge table just for debugging.
   734  	// re-enable to have the names in the binary.
   735  	ftable.WriteRune('\n')
   736  	fmt.Fprintf(ftable, "var %sStatenames = [...]string{\n", prefix)
   737  	//	for i:=TOKSTART; i<=ntokens; i++ {
   738  	//		fmt.Fprintf(ftable, "\t%q,\n", tokset[i].name);
   739  	//	}
   740  	fmt.Fprintf(ftable, "}\n")
   741  
   742  	ftable.WriteRune('\n')
   743  	fmt.Fprintf(ftable, "const %sEofCode = 1\n", prefix)
   744  	fmt.Fprintf(ftable, "const %sErrCode = 2\n", prefix)
   745  	fmt.Fprintf(ftable, "const %sInitialStackSize = %v\n", prefix, initialstacksize)
   746  
   747  	//
   748  	// copy any postfix code
   749  	//
   750  	if t == MARK {
   751  		if !lflag {
   752  			fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
   753  		}
   754  		for {
   755  			c := getrune(finput)
   756  			if c == EOF {
   757  				break
   758  			}
   759  			ftable.WriteRune(c)
   760  		}
   761  	}
   762  }
   763  
   764  //
   765  // allocate enough room to hold another production
   766  //
   767  func moreprod() {
   768  	n := len(prdptr)
   769  	if nprod >= n {
   770  		nn := n + PRODINC
   771  		aprod := make([][]int, nn)
   772  		alevprd := make([]int, nn)
   773  		arlines := make([]int, nn)
   774  
   775  		copy(aprod, prdptr)
   776  		copy(alevprd, levprd)
   777  		copy(arlines, rlines)
   778  
   779  		prdptr = aprod
   780  		levprd = alevprd
   781  		rlines = arlines
   782  	}
   783  }
   784  
   785  //
   786  // define s to be a terminal if nt==0
   787  // or a nonterminal if nt==1
   788  //
   789  func defin(nt int, s string) int {
   790  	val := 0
   791  	if nt != 0 {
   792  		nnonter++
   793  		if nnonter >= len(nontrst) {
   794  			anontrst := make([]Symb, nnonter+SYMINC)
   795  			copy(anontrst, nontrst)
   796  			nontrst = anontrst
   797  		}
   798  		nontrst[nnonter] = Symb{name: s}
   799  		return NTBASE + nnonter
   800  	}
   801  
   802  	// must be a token
   803  	ntokens++
   804  	if ntokens >= len(tokset) {
   805  		nn := ntokens + SYMINC
   806  		atokset := make([]Symb, nn)
   807  		atoklev := make([]int, nn)
   808  
   809  		copy(atoklev, toklev)
   810  		copy(atokset, tokset)
   811  
   812  		tokset = atokset
   813  		toklev = atoklev
   814  	}
   815  	tokset[ntokens].name = s
   816  	toklev[ntokens] = 0
   817  
   818  	// establish value for token
   819  	// single character literal
   820  	if s[0] == '\'' || s[0] == '"' {
   821  		q, err := strconv.Unquote(s)
   822  		if err != nil {
   823  			errorf("invalid token: %s", err)
   824  		}
   825  		rq := []rune(q)
   826  		if len(rq) != 1 {
   827  			errorf("character token too long: %s", s)
   828  		}
   829  		val = int(rq[0])
   830  		if val == 0 {
   831  			errorf("token value 0 is illegal")
   832  		}
   833  		tokset[ntokens].noconst = true
   834  	} else {
   835  		val = extval
   836  		extval++
   837  		if s[0] == '$' {
   838  			tokset[ntokens].noconst = true
   839  		}
   840  	}
   841  
   842  	tokset[ntokens].value = val
   843  	return ntokens
   844  }
   845  
   846  var peekline = 0
   847  
   848  func gettok() int {
   849  	var i int
   850  	var match, c rune
   851  
   852  	tokname = ""
   853  	for {
   854  		lineno += peekline
   855  		peekline = 0
   856  		c = getrune(finput)
   857  		for c == ' ' || c == '\n' || c == '\t' || c == '\v' || c == '\r' {
   858  			if c == '\n' {
   859  				lineno++
   860  			}
   861  			c = getrune(finput)
   862  		}
   863  
   864  		// skip comment -- fix
   865  		if c != '/' {
   866  			break
   867  		}
   868  		lineno += skipcom()
   869  	}
   870  
   871  	switch c {
   872  	case EOF:
   873  		if tokflag {
   874  			fmt.Printf(">>> ENDFILE %v\n", lineno)
   875  		}
   876  		return ENDFILE
   877  
   878  	case '{':
   879  		ungetrune(finput, c)
   880  		if tokflag {
   881  			fmt.Printf(">>> ={ %v\n", lineno)
   882  		}
   883  		return '='
   884  
   885  	case '<':
   886  		// get, and look up, a type name (union member name)
   887  		c = getrune(finput)
   888  		for c != '>' && c != EOF && c != '\n' {
   889  			tokname += string(c)
   890  			c = getrune(finput)
   891  		}
   892  
   893  		if c != '>' {
   894  			errorf("unterminated < ... > clause")
   895  		}
   896  
   897  		for i = 1; i <= ntypes; i++ {
   898  			if typeset[i] == tokname {
   899  				numbval = i
   900  				if tokflag {
   901  					fmt.Printf(">>> TYPENAME old <%v> %v\n", tokname, lineno)
   902  				}
   903  				return TYPENAME
   904  			}
   905  		}
   906  		ntypes++
   907  		numbval = ntypes
   908  		typeset[numbval] = tokname
   909  		if tokflag {
   910  			fmt.Printf(">>> TYPENAME new <%v> %v\n", tokname, lineno)
   911  		}
   912  		return TYPENAME
   913  
   914  	case '"', '\'':
   915  		match = c
   916  		tokname = string(c)
   917  		for {
   918  			c = getrune(finput)
   919  			if c == '\n' || c == EOF {
   920  				errorf("illegal or missing ' or \"")
   921  			}
   922  			if c == '\\' {
   923  				tokname += string('\\')
   924  				c = getrune(finput)
   925  			} else if c == match {
   926  				if tokflag {
   927  					fmt.Printf(">>> IDENTIFIER \"%v\" %v\n", tokname, lineno)
   928  				}
   929  				tokname += string(c)
   930  				return IDENTIFIER
   931  			}
   932  			tokname += string(c)
   933  		}
   934  
   935  	case '%':
   936  		c = getrune(finput)
   937  		switch c {
   938  		case '%':
   939  			if tokflag {
   940  				fmt.Printf(">>> MARK %%%% %v\n", lineno)
   941  			}
   942  			return MARK
   943  		case '=':
   944  			if tokflag {
   945  				fmt.Printf(">>> PREC %%= %v\n", lineno)
   946  			}
   947  			return PREC
   948  		case '{':
   949  			if tokflag {
   950  				fmt.Printf(">>> LCURLY %%{ %v\n", lineno)
   951  			}
   952  			return LCURLY
   953  		}
   954  
   955  		getword(c)
   956  		// find a reserved word
   957  		for i := range resrv {
   958  			if tokname == resrv[i].name {
   959  				if tokflag {
   960  					fmt.Printf(">>> %%%v %v %v\n", tokname,
   961  						resrv[i].value-PRIVATE, lineno)
   962  				}
   963  				return resrv[i].value
   964  			}
   965  		}
   966  		errorf("invalid escape, or illegal reserved word: %v", tokname)
   967  
   968  	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   969  		numbval = int(c - '0')
   970  		for {
   971  			c = getrune(finput)
   972  			if !isdigit(c) {
   973  				break
   974  			}
   975  			numbval = numbval*10 + int(c-'0')
   976  		}
   977  		ungetrune(finput, c)
   978  		if tokflag {
   979  			fmt.Printf(">>> NUMBER %v %v\n", numbval, lineno)
   980  		}
   981  		return NUMBER
   982  
   983  	default:
   984  		if isword(c) || c == '.' || c == '$' {
   985  			getword(c)
   986  			break
   987  		}
   988  		if tokflag {
   989  			fmt.Printf(">>> OPERATOR %v %v\n", string(c), lineno)
   990  		}
   991  		return int(c)
   992  	}
   993  
   994  	// look ahead to distinguish IDENTIFIER from IDENTCOLON
   995  	c = getrune(finput)
   996  	for c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\r' || c == '/' {
   997  		if c == '\n' {
   998  			peekline++
   999  		}
  1000  		// look for comments
  1001  		if c == '/' {
  1002  			peekline += skipcom()
  1003  		}
  1004  		c = getrune(finput)
  1005  	}
  1006  	if c == ':' {
  1007  		if tokflag {
  1008  			fmt.Printf(">>> IDENTCOLON %v: %v\n", tokname, lineno)
  1009  		}
  1010  		return IDENTCOLON
  1011  	}
  1012  
  1013  	ungetrune(finput, c)
  1014  	if tokflag {
  1015  		fmt.Printf(">>> IDENTIFIER %v %v\n", tokname, lineno)
  1016  	}
  1017  	return IDENTIFIER
  1018  }
  1019  
  1020  func getword(c rune) {
  1021  	tokname = ""
  1022  	for isword(c) || isdigit(c) || c == '.' || c == '$' {
  1023  		tokname += string(c)
  1024  		c = getrune(finput)
  1025  	}
  1026  	ungetrune(finput, c)
  1027  }
  1028  
  1029  //
  1030  // determine the type of a symbol
  1031  //
  1032  func fdtype(t int) (int, string) {
  1033  	var v int
  1034  	var s string
  1035  
  1036  	if t >= NTBASE {
  1037  		v = nontrst[t-NTBASE].value
  1038  		s = nontrst[t-NTBASE].name
  1039  	} else {
  1040  		v = TYPE(toklev[t])
  1041  		s = tokset[t].name
  1042  	}
  1043  	return v, s
  1044  }
  1045  
  1046  func chfind(t int, s string) int {
  1047  	if s[0] == '"' || s[0] == '\'' {
  1048  		t = 0
  1049  	}
  1050  	for i := 0; i <= ntokens; i++ {
  1051  		if s == tokset[i].name {
  1052  			return i
  1053  		}
  1054  	}
  1055  	for i := 0; i <= nnonter; i++ {
  1056  		if s == nontrst[i].name {
  1057  			return NTBASE + i
  1058  		}
  1059  	}
  1060  
  1061  	// cannot find name
  1062  	if t > 1 {
  1063  		errorf("%v should have been defined earlier", s)
  1064  	}
  1065  	return defin(t, s)
  1066  }
  1067  
  1068  const (
  1069  	startUnion = iota
  1070  	skippingLeadingBlanks
  1071  	readingMember
  1072  	skippingLaterBlanks
  1073  	readingType
  1074  )
  1075  
  1076  type gotypeinfo struct {
  1077  	typename string
  1078  	union    bool
  1079  }
  1080  
  1081  var gotypes = make(map[string]*gotypeinfo)
  1082  
  1083  func typeinfo() {
  1084  	if !lflag {
  1085  		fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
  1086  	}
  1087  	fmt.Fprintf(ftable, "type %sSymType struct {", prefix)
  1088  	for _, tt := range gotypes {
  1089  		if tt.union {
  1090  			fmt.Fprintf(ftable, "\n\tunion interface{}")
  1091  			break
  1092  		}
  1093  	}
  1094  	ftable.Write(ftypes.Bytes())
  1095  	fmt.Fprintf(ftable, "\n\tyys int")
  1096  	fmt.Fprintf(ftable, "\n}\n\n")
  1097  
  1098  	var sortedTypes []string
  1099  	for member, tt := range gotypes {
  1100  		if tt.union {
  1101  			sortedTypes = append(sortedTypes, member)
  1102  		}
  1103  	}
  1104  	sort.Strings(sortedTypes)
  1105  
  1106  	for _, member := range sortedTypes {
  1107  		tt := gotypes[member]
  1108  		fmt.Fprintf(ftable, "\nfunc (st *%sSymType) %sUnion() %s {\n", prefix, member, tt.typename)
  1109  		fmt.Fprintf(ftable, "\tv, _ := st.union.(%s)\n", tt.typename)
  1110  		fmt.Fprintf(ftable, "\treturn v\n")
  1111  		fmt.Fprintf(ftable, "}\n")
  1112  	}
  1113  }
  1114  
  1115  //
  1116  // copy the union declaration to the output, and the define file if present
  1117  //
  1118  func parsetypes(union bool) {
  1119  	var member, typ bytes.Buffer
  1120  	state := startUnion
  1121  
  1122  out:
  1123  	for {
  1124  		c := getrune(finput)
  1125  		if c == EOF {
  1126  			errorf("EOF encountered while processing %%union")
  1127  		}
  1128  		switch c {
  1129  		case '\n':
  1130  			lineno++
  1131  			if state == readingType {
  1132  				gotypes[member.String()] = &gotypeinfo{
  1133  					typename: typ.String(),
  1134  					union:    union,
  1135  				}
  1136  				if !union {
  1137  					fmt.Fprintf(ftypes, "\n\t%s %s", member.Bytes(), typ.Bytes())
  1138  				}
  1139  				member.Reset()
  1140  				typ.Reset()
  1141  			}
  1142  			state = skippingLeadingBlanks
  1143  		default:
  1144  			switch state {
  1145  			case skippingLeadingBlanks:
  1146  				if c == ' ' || c == '\t' {
  1147  					continue
  1148  				}
  1149  				if c == '}' {
  1150  					break out
  1151  				}
  1152  				state = readingMember
  1153  				member.WriteRune(c)
  1154  			case readingMember:
  1155  				if c == ' ' || c == '\t' {
  1156  					state = skippingLaterBlanks
  1157  					continue
  1158  				}
  1159  				member.WriteRune(c)
  1160  			case skippingLaterBlanks:
  1161  				if c == ' ' || c == '\t' {
  1162  					continue
  1163  				}
  1164  				state = readingType
  1165  				typ.WriteRune(c)
  1166  			case readingType:
  1167  				typ.WriteRune(c)
  1168  			}
  1169  		}
  1170  	}
  1171  }
  1172  
  1173  //
  1174  // saves code between %{ and %}
  1175  // adds an import for __fmt__ the first time
  1176  //
  1177  func cpycode() {
  1178  	lno := lineno
  1179  
  1180  	c := getrune(finput)
  1181  	if c == '\n' {
  1182  		c = getrune(finput)
  1183  		lineno++
  1184  	}
  1185  	if !lflag {
  1186  		fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
  1187  	}
  1188  	// accumulate until %}
  1189  	code := make([]rune, 0, 1024)
  1190  	for c != EOF {
  1191  		if c == '%' {
  1192  			c = getrune(finput)
  1193  			if c == '}' {
  1194  				emitcode(code, lno+1)
  1195  				return
  1196  			}
  1197  			code = append(code, '%')
  1198  		}
  1199  		code = append(code, c)
  1200  		if c == '\n' {
  1201  			lineno++
  1202  		}
  1203  		c = getrune(finput)
  1204  	}
  1205  	lineno = lno
  1206  	errorf("eof before %%}")
  1207  }
  1208  
  1209  //
  1210  // emits code saved up from between %{ and %}
  1211  // called by cpycode
  1212  // adds an import for __yyfmt__ after the package clause
  1213  //
  1214  func emitcode(code []rune, lineno int) {
  1215  	for i, line := range lines(code) {
  1216  		writecode(line)
  1217  		if !writtenImports && isPackageClause(line) {
  1218  			fmt.Fprintln(ftable, `import (`)
  1219  			fmt.Fprintln(ftable, `__yyfmt__ "fmt"`)
  1220  			fmt.Fprintln(ftable, `__yyunsafe__ "unsafe"`)
  1221  			fmt.Fprintln(ftable, `)`)
  1222  			if !lflag {
  1223  				fmt.Fprintf(ftable, "//line %v:%v\n\t\t", infile, lineno+i)
  1224  			}
  1225  			writtenImports = true
  1226  		}
  1227  	}
  1228  }
  1229  
  1230  //
  1231  // does this line look like a package clause?  not perfect: might be confused by early comments.
  1232  //
  1233  func isPackageClause(line []rune) bool {
  1234  	line = skipspace(line)
  1235  
  1236  	// must be big enough.
  1237  	if len(line) < len("package X\n") {
  1238  		return false
  1239  	}
  1240  
  1241  	// must start with "package"
  1242  	for i, r := range []rune("package") {
  1243  		if line[i] != r {
  1244  			return false
  1245  		}
  1246  	}
  1247  	line = skipspace(line[len("package"):])
  1248  
  1249  	// must have another identifier.
  1250  	if len(line) == 0 || (!unicode.IsLetter(line[0]) && line[0] != '_') {
  1251  		return false
  1252  	}
  1253  	for len(line) > 0 {
  1254  		if !unicode.IsLetter(line[0]) && !unicode.IsDigit(line[0]) && line[0] != '_' {
  1255  			break
  1256  		}
  1257  		line = line[1:]
  1258  	}
  1259  	line = skipspace(line)
  1260  
  1261  	// eol, newline, or comment must follow
  1262  	if len(line) == 0 {
  1263  		return true
  1264  	}
  1265  	if line[0] == '\r' || line[0] == '\n' {
  1266  		return true
  1267  	}
  1268  	if len(line) >= 2 {
  1269  		return line[0] == '/' && (line[1] == '/' || line[1] == '*')
  1270  	}
  1271  	return false
  1272  }
  1273  
  1274  //
  1275  // skip initial spaces
  1276  //
  1277  func skipspace(line []rune) []rune {
  1278  	for len(line) > 0 {
  1279  		if line[0] != ' ' && line[0] != '\t' {
  1280  			break
  1281  		}
  1282  		line = line[1:]
  1283  	}
  1284  	return line
  1285  }
  1286  
  1287  //
  1288  // break code into lines
  1289  //
  1290  func lines(code []rune) [][]rune {
  1291  	l := make([][]rune, 0, 100)
  1292  	for len(code) > 0 {
  1293  		// one line per loop
  1294  		var i int
  1295  		for i = range code {
  1296  			if code[i] == '\n' {
  1297  				break
  1298  			}
  1299  		}
  1300  		l = append(l, code[:i+1])
  1301  		code = code[i+1:]
  1302  	}
  1303  	return l
  1304  }
  1305  
  1306  //
  1307  // writes code to ftable
  1308  //
  1309  func writecode(code []rune) {
  1310  	for _, r := range code {
  1311  		ftable.WriteRune(r)
  1312  	}
  1313  }
  1314  
  1315  //
  1316  // skip over comments
  1317  // skipcom is called after reading a '/'
  1318  //
  1319  func skipcom() int {
  1320  	c := getrune(finput)
  1321  	if c == '/' {
  1322  		for c != EOF {
  1323  			if c == '\n' {
  1324  				return 1
  1325  			}
  1326  			c = getrune(finput)
  1327  		}
  1328  		errorf("EOF inside comment")
  1329  		return 0
  1330  	}
  1331  	if c != '*' {
  1332  		errorf("illegal comment")
  1333  	}
  1334  
  1335  	nl := 0 // lines skipped
  1336  	c = getrune(finput)
  1337  
  1338  l1:
  1339  	switch c {
  1340  	case '*':
  1341  		c = getrune(finput)
  1342  		if c == '/' {
  1343  			break
  1344  		}
  1345  		goto l1
  1346  
  1347  	case '\n':
  1348  		nl++
  1349  		fallthrough
  1350  
  1351  	default:
  1352  		c = getrune(finput)
  1353  		goto l1
  1354  	}
  1355  	return nl
  1356  }
  1357  
  1358  var fastAppendRe = regexp.MustCompile(`\s+append\(\$[$1],`)
  1359  
  1360  func cpyyvalaccess(fcode *bytes.Buffer, curprod []int, tok int, unionType *string) {
  1361  	if ntypes == 0 {
  1362  		fmt.Fprintf(fcode, "%sVAL", prefix)
  1363  		return
  1364  	}
  1365  
  1366  	if tok < 0 {
  1367  		tok, _ = fdtype(curprod[0])
  1368  	}
  1369  	ti, ok := gotypes[typeset[tok]]
  1370  	if !ok {
  1371  		errorf("missing Go type information for %s", typeset[tok])
  1372  	}
  1373  	if !ti.union {
  1374  		fmt.Fprintf(fcode, "%sVAL.%s", prefix, typeset[tok])
  1375  		return
  1376  	}
  1377  
  1378  	var buf bytes.Buffer
  1379  	lvalue := false
  1380  	fastAppend := false
  1381  
  1382  loop:
  1383  	for {
  1384  		c := getrune(finput)
  1385  
  1386  		switch c {
  1387  		case ' ', '\t':
  1388  			buf.WriteRune(c)
  1389  
  1390  		case '=':
  1391  			lvalue = true
  1392  			if allowFastAppend && *unionType == "" {
  1393  				peek, err := finput.Peek(16)
  1394  				if err != nil {
  1395  					errorf("failed to scan forward: %v", err)
  1396  				}
  1397  				match := fastAppendRe.Find(peek)
  1398  				if len(match) > 0 {
  1399  					fastAppend = true
  1400  					for range match {
  1401  						_ = getrune(finput)
  1402  					}
  1403  				} else {
  1404  					buf.WriteRune(c)
  1405  				}
  1406  				break loop
  1407  			}
  1408  
  1409  			buf.WriteRune(c)
  1410  			break loop
  1411  
  1412  		default:
  1413  			buf.WriteRune(c)
  1414  			break loop
  1415  		}
  1416  	}
  1417  
  1418  	if fastAppend {
  1419  		fmt.Fprintf(fcode, "\t%sSLICE := (*%s)(%sIaddr(%sVAL.union))\n", prefix, ti.typename, prefix, prefix)
  1420  		fmt.Fprintf(fcode, "\t*%sSLICE = append(*%sSLICE, ", prefix, prefix)
  1421  	} else if lvalue {
  1422  		fmt.Fprintf(fcode, "%sLOCAL", prefix)
  1423  		*unionType = ti.typename
  1424  	} else if *unionType == "" {
  1425  		fmt.Fprintf(fcode, "%sVAL.%sUnion()", prefix, typeset[tok])
  1426  	} else {
  1427  		fmt.Fprintf(fcode, "%sLOCAL", prefix)
  1428  	}
  1429  	fcode.Write(buf.Bytes())
  1430  }
  1431  
  1432  //
  1433  // copy action to the next ; or closing }
  1434  //
  1435  func cpyact(fcode *bytes.Buffer, curprod []int, max int, unionType *string) {
  1436  	if !lflag {
  1437  		fmt.Fprintf(fcode, "\n//line %v:%v", infile, lineno)
  1438  	}
  1439  	fmt.Fprint(fcode, "\n\t\t")
  1440  
  1441  	lno := lineno
  1442  	brac := 0
  1443  
  1444  loop:
  1445  	for {
  1446  		c := getrune(finput)
  1447  
  1448  	swt:
  1449  		switch c {
  1450  		case ';':
  1451  			if brac == 0 {
  1452  				fcode.WriteRune(c)
  1453  				return
  1454  			}
  1455  
  1456  		case '{':
  1457  			brac++
  1458  
  1459  		case '$':
  1460  			s := 1
  1461  			tok := -1
  1462  			c = getrune(finput)
  1463  
  1464  			// type description
  1465  			if c == '<' {
  1466  				ungetrune(finput, c)
  1467  				if gettok() != TYPENAME {
  1468  					errorf("bad syntax on $<ident> clause")
  1469  				}
  1470  				tok = numbval
  1471  				c = getrune(finput)
  1472  			}
  1473  			if c == '$' {
  1474  				cpyyvalaccess(fcode, curprod, tok, unionType)
  1475  				continue loop
  1476  			}
  1477  			if c == '-' {
  1478  				s = -s
  1479  				c = getrune(finput)
  1480  			}
  1481  			j := 0
  1482  			if isdigit(c) {
  1483  				for isdigit(c) {
  1484  					j = j*10 + int(c-'0')
  1485  					c = getrune(finput)
  1486  				}
  1487  				ungetrune(finput, c)
  1488  				j = j * s
  1489  				if j >= max {
  1490  					errorf("Illegal use of $%v", j)
  1491  				}
  1492  			} else if isword(c) || c == '.' {
  1493  				// look for $name
  1494  				ungetrune(finput, c)
  1495  				if gettok() != IDENTIFIER {
  1496  					errorf("$ must be followed by an identifier")
  1497  				}
  1498  				tokn := chfind(2, tokname)
  1499  				fnd := -1
  1500  				c = getrune(finput)
  1501  				if c != '@' {
  1502  					ungetrune(finput, c)
  1503  				} else if gettok() != NUMBER {
  1504  					errorf("@ must be followed by number")
  1505  				} else {
  1506  					fnd = numbval
  1507  				}
  1508  				for j = 1; j < max; j++ {
  1509  					if tokn == curprod[j] {
  1510  						fnd--
  1511  						if fnd <= 0 {
  1512  							break
  1513  						}
  1514  					}
  1515  				}
  1516  				if j >= max {
  1517  					errorf("$name or $name@number not found")
  1518  				}
  1519  			} else {
  1520  				fcode.WriteRune('$')
  1521  				if s < 0 {
  1522  					fcode.WriteRune('-')
  1523  				}
  1524  				ungetrune(finput, c)
  1525  				continue loop
  1526  			}
  1527  			fmt.Fprintf(fcode, "%sDollar[%v]", prefix, j)
  1528  
  1529  			// put out the proper tag
  1530  			if ntypes != 0 {
  1531  				if j <= 0 && tok < 0 {
  1532  					errorf("must specify type of $%v", j)
  1533  				}
  1534  				if tok < 0 {
  1535  					tok, _ = fdtype(curprod[j])
  1536  				}
  1537  				ti, ok := gotypes[typeset[tok]]
  1538  				if !ok {
  1539  					errorf("missing Go type information for %s", typeset[tok])
  1540  				}
  1541  				if ti.union {
  1542  					fmt.Fprintf(fcode, ".%sUnion()", typeset[tok])
  1543  				} else {
  1544  					fmt.Fprintf(fcode, ".%s", typeset[tok])
  1545  				}
  1546  			}
  1547  			continue loop
  1548  
  1549  		case '}':
  1550  			brac--
  1551  			if brac != 0 {
  1552  				break
  1553  			}
  1554  			fcode.WriteRune(c)
  1555  			return
  1556  
  1557  		case '/':
  1558  			nc := getrune(finput)
  1559  			if nc != '/' && nc != '*' {
  1560  				ungetrune(finput, nc)
  1561  				break
  1562  			}
  1563  			// a comment
  1564  			fcode.WriteRune(c)
  1565  			fcode.WriteRune(nc)
  1566  			c = getrune(finput)
  1567  			for c != EOF {
  1568  				switch {
  1569  				case c == '\n':
  1570  					lineno++
  1571  					if nc == '/' { // end of // comment
  1572  						break swt
  1573  					}
  1574  				case c == '*' && nc == '*': // end of /* comment?
  1575  					nnc := getrune(finput)
  1576  					if nnc == '/' {
  1577  						fcode.WriteRune('*')
  1578  						fcode.WriteRune('/')
  1579  						continue loop
  1580  					}
  1581  					ungetrune(finput, nnc)
  1582  				}
  1583  				fcode.WriteRune(c)
  1584  				c = getrune(finput)
  1585  			}
  1586  			errorf("EOF inside comment")
  1587  
  1588  		case '\'', '"':
  1589  			// character string or constant
  1590  			match := c
  1591  			fcode.WriteRune(c)
  1592  			c = getrune(finput)
  1593  			for c != EOF {
  1594  				if c == '\\' {
  1595  					fcode.WriteRune(c)
  1596  					c = getrune(finput)
  1597  					if c == '\n' {
  1598  						lineno++
  1599  					}
  1600  				} else if c == match {
  1601  					break swt
  1602  				}
  1603  				if c == '\n' {
  1604  					errorf("newline in string or char const")
  1605  				}
  1606  				fcode.WriteRune(c)
  1607  				c = getrune(finput)
  1608  			}
  1609  			errorf("EOF in string or character constant")
  1610  
  1611  		case EOF:
  1612  			lineno = lno
  1613  			errorf("action does not terminate")
  1614  
  1615  		case '\n':
  1616  			fmt.Fprint(fcode, "\n\t")
  1617  			lineno++
  1618  			continue loop
  1619  		}
  1620  
  1621  		fcode.WriteRune(c)
  1622  	}
  1623  }
  1624  
  1625  func openup() {
  1626  	infile = flag.Arg(0)
  1627  	finput = open(infile)
  1628  	if finput == nil {
  1629  		errorf("cannot open %v", infile)
  1630  	}
  1631  
  1632  	foutput = nil
  1633  	if vflag != "" {
  1634  		foutput = create(vflag)
  1635  		if foutput == nil {
  1636  			errorf("can't create file %v", vflag)
  1637  		}
  1638  	}
  1639  
  1640  	ftable = nil
  1641  	if oflag == "" {
  1642  		oflag = "y.go"
  1643  	}
  1644  	ftable = create(oflag)
  1645  	if ftable == nil {
  1646  		errorf("can't create file %v", oflag)
  1647  	}
  1648  
  1649  }
  1650  
  1651  //
  1652  // return a pointer to the name of symbol i
  1653  //
  1654  func symnam(i int) string {
  1655  	var s string
  1656  
  1657  	if i >= NTBASE {
  1658  		s = nontrst[i-NTBASE].name
  1659  	} else {
  1660  		s = tokset[i].name
  1661  	}
  1662  	return s
  1663  }
  1664  
  1665  //
  1666  // set elements 0 through n-1 to c
  1667  //
  1668  func aryfil(v []int, n, c int) {
  1669  	for i := 0; i < n; i++ {
  1670  		v[i] = c
  1671  	}
  1672  }
  1673  
  1674  //
  1675  // compute an array with the beginnings of productions yielding given nonterminals
  1676  // The array pres points to these lists
  1677  // the array pyield has the lists: the total size is only NPROD+1
  1678  //
  1679  func cpres() {
  1680  	pres = make([][][]int, nnonter+1)
  1681  	curres := make([][]int, nprod)
  1682  
  1683  	if false {
  1684  		for j := 0; j <= nnonter; j++ {
  1685  			fmt.Printf("nnonter[%v] = %v\n", j, nontrst[j].name)
  1686  		}
  1687  		for j := 0; j < nprod; j++ {
  1688  			fmt.Printf("prdptr[%v][0] = %v+NTBASE\n", j, prdptr[j][0]-NTBASE)
  1689  		}
  1690  	}
  1691  
  1692  	fatfl = 0 // make undefined symbols nonfatal
  1693  	for i := 0; i <= nnonter; i++ {
  1694  		n := 0
  1695  		c := i + NTBASE
  1696  		for j := 0; j < nprod; j++ {
  1697  			if prdptr[j][0] == c {
  1698  				curres[n] = prdptr[j][1:]
  1699  				n++
  1700  			}
  1701  		}
  1702  		if n == 0 {
  1703  			errorf("nonterminal %v not defined", nontrst[i].name)
  1704  			continue
  1705  		}
  1706  		pres[i] = make([][]int, n)
  1707  		copy(pres[i], curres)
  1708  	}
  1709  	fatfl = 1
  1710  	if nerrors != 0 {
  1711  		summary()
  1712  		exit(1)
  1713  	}
  1714  }
  1715  
  1716  //
  1717  // mark nonterminals which derive the empty string
  1718  // also, look for nonterminals which don't derive any token strings
  1719  //
  1720  func cempty() {
  1721  	var i, p, np int
  1722  	var prd []int
  1723  
  1724  	pempty = make([]int, nnonter+1)
  1725  
  1726  	// first, use the array pempty to detect productions that can never be reduced
  1727  	// set pempty to WHONOWS
  1728  	aryfil(pempty, nnonter+1, WHOKNOWS)
  1729  
  1730  	// now, look at productions, marking nonterminals which derive something
  1731  more:
  1732  	for {
  1733  		for i = 0; i < nprod; i++ {
  1734  			prd = prdptr[i]
  1735  			if pempty[prd[0]-NTBASE] != 0 {
  1736  				continue
  1737  			}
  1738  			np = len(prd) - 1
  1739  			for p = 1; p < np; p++ {
  1740  				if prd[p] >= NTBASE && pempty[prd[p]-NTBASE] == WHOKNOWS {
  1741  					break
  1742  				}
  1743  			}
  1744  			// production can be derived
  1745  			if p == np {
  1746  				pempty[prd[0]-NTBASE] = OK
  1747  				continue more
  1748  			}
  1749  		}
  1750  		break
  1751  	}
  1752  
  1753  	// now, look at the nonterminals, to see if they are all OK
  1754  	for i = 0; i <= nnonter; i++ {
  1755  		// the added production rises or falls as the start symbol ...
  1756  		if i == 0 {
  1757  			continue
  1758  		}
  1759  		if pempty[i] != OK {
  1760  			fatfl = 0
  1761  			errorf("nonterminal " + nontrst[i].name + " never derives any token string")
  1762  		}
  1763  	}
  1764  
  1765  	if nerrors != 0 {
  1766  		summary()
  1767  		exit(1)
  1768  	}
  1769  
  1770  	// now, compute the pempty array, to see which nonterminals derive the empty string
  1771  	// set pempty to WHOKNOWS
  1772  	aryfil(pempty, nnonter+1, WHOKNOWS)
  1773  
  1774  	// loop as long as we keep finding empty nonterminals
  1775  
  1776  again:
  1777  	for {
  1778  	next:
  1779  		for i = 1; i < nprod; i++ {
  1780  			// not known to be empty
  1781  			prd = prdptr[i]
  1782  			if pempty[prd[0]-NTBASE] != WHOKNOWS {
  1783  				continue
  1784  			}
  1785  			np = len(prd) - 1
  1786  			for p = 1; p < np; p++ {
  1787  				if prd[p] < NTBASE || pempty[prd[p]-NTBASE] != EMPTY {
  1788  					continue next
  1789  				}
  1790  			}
  1791  
  1792  			// we have a nontrivially empty nonterminal
  1793  			pempty[prd[0]-NTBASE] = EMPTY
  1794  
  1795  			// got one ... try for another
  1796  			continue again
  1797  		}
  1798  		return
  1799  	}
  1800  }
  1801  
  1802  //
  1803  // compute an array with the first of nonterminals
  1804  //
  1805  func cpfir() {
  1806  	var s, n, p, np, ch, i int
  1807  	var curres [][]int
  1808  	var prd []int
  1809  
  1810  	wsets = make([]Wset, nnonter+WSETINC)
  1811  	pfirst = make([]Lkset, nnonter+1)
  1812  	for i = 0; i <= nnonter; i++ {
  1813  		wsets[i].ws = mkset()
  1814  		pfirst[i] = mkset()
  1815  		curres = pres[i]
  1816  		n = len(curres)
  1817  
  1818  		// initially fill the sets
  1819  		for s = 0; s < n; s++ {
  1820  			prd = curres[s]
  1821  			np = len(prd) - 1
  1822  			for p = 0; p < np; p++ {
  1823  				ch = prd[p]
  1824  				if ch < NTBASE {
  1825  					setbit(pfirst[i], ch)
  1826  					break
  1827  				}
  1828  				if pempty[ch-NTBASE] == 0 {
  1829  					break
  1830  				}
  1831  			}
  1832  		}
  1833  	}
  1834  
  1835  	// now, reflect transitivity
  1836  	changes := 1
  1837  	for changes != 0 {
  1838  		changes = 0
  1839  		for i = 0; i <= nnonter; i++ {
  1840  			curres = pres[i]
  1841  			n = len(curres)
  1842  			for s = 0; s < n; s++ {
  1843  				prd = curres[s]
  1844  				np = len(prd) - 1
  1845  				for p = 0; p < np; p++ {
  1846  					ch = prd[p] - NTBASE
  1847  					if ch < 0 {
  1848  						break
  1849  					}
  1850  					changes |= setunion(pfirst[i], pfirst[ch])
  1851  					if pempty[ch] == 0 {
  1852  						break
  1853  					}
  1854  				}
  1855  			}
  1856  		}
  1857  	}
  1858  
  1859  	if indebug == 0 {
  1860  		return
  1861  	}
  1862  	if foutput != nil {
  1863  		for i = 0; i <= nnonter; i++ {
  1864  			fmt.Fprintf(foutput, "\n%v: %v %v\n",
  1865  				nontrst[i].name, pfirst[i], pempty[i])
  1866  		}
  1867  	}
  1868  }
  1869  
  1870  //
  1871  // generate the states
  1872  //
  1873  func stagen() {
  1874  	// initialize
  1875  	nstate = 0
  1876  	tstates = make([]int, ntokens+1)  // states generated by terminal gotos
  1877  	ntstates = make([]int, nnonter+1) // states generated by nonterminal gotos
  1878  	amem = make([]int, ACTSIZE)
  1879  	memp = 0
  1880  
  1881  	clset = mkset()
  1882  	pstate[0] = 0
  1883  	pstate[1] = 0
  1884  	aryfil(clset, tbitset, 0)
  1885  	putitem(Pitem{prdptr[0], 0, 0, 0}, clset)
  1886  	tystate[0] = MUSTDO
  1887  	nstate = 1
  1888  	pstate[2] = pstate[1]
  1889  
  1890  	//
  1891  	// now, the main state generation loop
  1892  	// first pass generates all of the states
  1893  	// later passes fix up lookahead
  1894  	// could be sped up a lot by remembering
  1895  	// results of the first pass rather than recomputing
  1896  	//
  1897  	first := 1
  1898  	for more := 1; more != 0; first = 0 {
  1899  		more = 0
  1900  		for i := 0; i < nstate; i++ {
  1901  			if tystate[i] != MUSTDO {
  1902  				continue
  1903  			}
  1904  
  1905  			tystate[i] = DONE
  1906  			aryfil(temp1, nnonter+1, 0)
  1907  
  1908  			// take state i, close it, and do gotos
  1909  			closure(i)
  1910  
  1911  			// generate goto's
  1912  			for p := 0; p < cwp; p++ {
  1913  				pi := wsets[p]
  1914  				if pi.flag != 0 {
  1915  					continue
  1916  				}
  1917  				wsets[p].flag = 1
  1918  				c := pi.pitem.first
  1919  				if c <= 1 {
  1920  					if pstate[i+1]-pstate[i] <= p {
  1921  						tystate[i] = MUSTLOOKAHEAD
  1922  					}
  1923  					continue
  1924  				}
  1925  
  1926  				// do a goto on c
  1927  				putitem(wsets[p].pitem, wsets[p].ws)
  1928  				for q := p + 1; q < cwp; q++ {
  1929  					// this item contributes to the goto
  1930  					if c == wsets[q].pitem.first {
  1931  						putitem(wsets[q].pitem, wsets[q].ws)
  1932  						wsets[q].flag = 1
  1933  					}
  1934  				}
  1935  
  1936  				if c < NTBASE {
  1937  					state(c) // register new state
  1938  				} else {
  1939  					temp1[c-NTBASE] = state(c)
  1940  				}
  1941  			}
  1942  
  1943  			if gsdebug != 0 && foutput != nil {
  1944  				fmt.Fprintf(foutput, "%v: ", i)
  1945  				for j := 0; j <= nnonter; j++ {
  1946  					if temp1[j] != 0 {
  1947  						fmt.Fprintf(foutput, "%v %v,", nontrst[j].name, temp1[j])
  1948  					}
  1949  				}
  1950  				fmt.Fprintf(foutput, "\n")
  1951  			}
  1952  
  1953  			if first != 0 {
  1954  				indgo[i] = apack(temp1[1:], nnonter-1) - 1
  1955  			}
  1956  
  1957  			more++
  1958  		}
  1959  	}
  1960  }
  1961  
  1962  //
  1963  // generate the closure of state i
  1964  //
  1965  func closure(i int) {
  1966  	zzclose++
  1967  
  1968  	// first, copy kernel of state i to wsets
  1969  	cwp = 0
  1970  	q := pstate[i+1]
  1971  	for p := pstate[i]; p < q; p++ {
  1972  		wsets[cwp].pitem = statemem[p].pitem
  1973  		wsets[cwp].flag = 1 // this item must get closed
  1974  		copy(wsets[cwp].ws, statemem[p].look)
  1975  		cwp++
  1976  	}
  1977  
  1978  	// now, go through the loop, closing each item
  1979  	work := 1
  1980  	for work != 0 {
  1981  		work = 0
  1982  		for u := 0; u < cwp; u++ {
  1983  			if wsets[u].flag == 0 {
  1984  				continue
  1985  			}
  1986  
  1987  			// dot is before c
  1988  			c := wsets[u].pitem.first
  1989  			if c < NTBASE {
  1990  				wsets[u].flag = 0
  1991  				// only interesting case is where . is before nonterminal
  1992  				continue
  1993  			}
  1994  
  1995  			// compute the lookahead
  1996  			aryfil(clset, tbitset, 0)
  1997  
  1998  			// find items involving c
  1999  			for v := u; v < cwp; v++ {
  2000  				if wsets[v].flag != 1 || wsets[v].pitem.first != c {
  2001  					continue
  2002  				}
  2003  				pi := wsets[v].pitem.prod
  2004  				ipi := wsets[v].pitem.off + 1
  2005  
  2006  				wsets[v].flag = 0
  2007  				if nolook != 0 {
  2008  					continue
  2009  				}
  2010  
  2011  				ch := pi[ipi]
  2012  				ipi++
  2013  				for ch > 0 {
  2014  					// terminal symbol
  2015  					if ch < NTBASE {
  2016  						setbit(clset, ch)
  2017  						break
  2018  					}
  2019  
  2020  					// nonterminal symbol
  2021  					setunion(clset, pfirst[ch-NTBASE])
  2022  					if pempty[ch-NTBASE] == 0 {
  2023  						break
  2024  					}
  2025  					ch = pi[ipi]
  2026  					ipi++
  2027  				}
  2028  				if ch <= 0 {
  2029  					setunion(clset, wsets[v].ws)
  2030  				}
  2031  			}
  2032  
  2033  			//
  2034  			// now loop over productions derived from c
  2035  			//
  2036  			curres := pres[c-NTBASE]
  2037  			n := len(curres)
  2038  
  2039  		nexts:
  2040  			// initially fill the sets
  2041  			for s := 0; s < n; s++ {
  2042  				prd := curres[s]
  2043  
  2044  				//
  2045  				// put these items into the closure
  2046  				// is the item there
  2047  				//
  2048  				for v := 0; v < cwp; v++ {
  2049  					// yes, it is there
  2050  					if wsets[v].pitem.off == 0 &&
  2051  						aryeq(wsets[v].pitem.prod, prd) != 0 {
  2052  						if nolook == 0 &&
  2053  							setunion(wsets[v].ws, clset) != 0 {
  2054  							wsets[v].flag = 1
  2055  							work = 1
  2056  						}
  2057  						continue nexts
  2058  					}
  2059  				}
  2060  
  2061  				//  not there; make a new entry
  2062  				if cwp >= len(wsets) {
  2063  					awsets := make([]Wset, cwp+WSETINC)
  2064  					copy(awsets, wsets)
  2065  					wsets = awsets
  2066  				}
  2067  				wsets[cwp].pitem = Pitem{prd, 0, prd[0], -prd[len(prd)-1]}
  2068  				wsets[cwp].flag = 1
  2069  				wsets[cwp].ws = mkset()
  2070  				if nolook == 0 {
  2071  					work = 1
  2072  					copy(wsets[cwp].ws, clset)
  2073  				}
  2074  				cwp++
  2075  			}
  2076  		}
  2077  	}
  2078  
  2079  	// have computed closure; flags are reset; return
  2080  	if cldebug != 0 && foutput != nil {
  2081  		fmt.Fprintf(foutput, "\nState %v, nolook = %v\n", i, nolook)
  2082  		for u := 0; u < cwp; u++ {
  2083  			if wsets[u].flag != 0 {
  2084  				fmt.Fprintf(foutput, "flag set\n")
  2085  			}
  2086  			wsets[u].flag = 0
  2087  			fmt.Fprintf(foutput, "\t%v", writem(wsets[u].pitem))
  2088  			prlook(wsets[u].ws)
  2089  			fmt.Fprintf(foutput, "\n")
  2090  		}
  2091  	}
  2092  }
  2093  
  2094  //
  2095  // sorts last state,and sees if it equals earlier ones. returns state number
  2096  //
  2097  func state(c int) int {
  2098  	zzstate++
  2099  	p1 := pstate[nstate]
  2100  	p2 := pstate[nstate+1]
  2101  	if p1 == p2 {
  2102  		return 0 // null state
  2103  	}
  2104  
  2105  	// sort the items
  2106  	var k, l int
  2107  	for k = p1 + 1; k < p2; k++ { // make k the biggest
  2108  		for l = k; l > p1; l-- {
  2109  			if statemem[l].pitem.prodno < statemem[l-1].pitem.prodno ||
  2110  				statemem[l].pitem.prodno == statemem[l-1].pitem.prodno &&
  2111  					statemem[l].pitem.off < statemem[l-1].pitem.off {
  2112  				s := statemem[l]
  2113  				statemem[l] = statemem[l-1]
  2114  				statemem[l-1] = s
  2115  			} else {
  2116  				break
  2117  			}
  2118  		}
  2119  	}
  2120  
  2121  	size1 := p2 - p1 // size of state
  2122  
  2123  	var i int
  2124  	if c >= NTBASE {
  2125  		i = ntstates[c-NTBASE]
  2126  	} else {
  2127  		i = tstates[c]
  2128  	}
  2129  
  2130  look:
  2131  	for ; i != 0; i = mstates[i] {
  2132  		// get ith state
  2133  		q1 := pstate[i]
  2134  		q2 := pstate[i+1]
  2135  		size2 := q2 - q1
  2136  		if size1 != size2 {
  2137  			continue
  2138  		}
  2139  		k = p1
  2140  		for l = q1; l < q2; l++ {
  2141  			if aryeq(statemem[l].pitem.prod, statemem[k].pitem.prod) == 0 ||
  2142  				statemem[l].pitem.off != statemem[k].pitem.off {
  2143  				continue look
  2144  			}
  2145  			k++
  2146  		}
  2147  
  2148  		// found it
  2149  		pstate[nstate+1] = pstate[nstate] // delete last state
  2150  
  2151  		// fix up lookaheads
  2152  		if nolook != 0 {
  2153  			return i
  2154  		}
  2155  		k = p1
  2156  		for l = q1; l < q2; l++ {
  2157  			if setunion(statemem[l].look, statemem[k].look) != 0 {
  2158  				tystate[i] = MUSTDO
  2159  			}
  2160  			k++
  2161  		}
  2162  		return i
  2163  	}
  2164  
  2165  	// state is new
  2166  	zznewstate++
  2167  	if nolook != 0 {
  2168  		errorf("yacc state/nolook error")
  2169  	}
  2170  	pstate[nstate+2] = p2
  2171  	if nstate+1 >= NSTATES {
  2172  		errorf("too many states")
  2173  	}
  2174  	if c >= NTBASE {
  2175  		mstates[nstate] = ntstates[c-NTBASE]
  2176  		ntstates[c-NTBASE] = nstate
  2177  	} else {
  2178  		mstates[nstate] = tstates[c]
  2179  		tstates[c] = nstate
  2180  	}
  2181  	tystate[nstate] = MUSTDO
  2182  	nstate++
  2183  	return nstate - 1
  2184  }
  2185  
  2186  func putitem(p Pitem, set Lkset) {
  2187  	p.off++
  2188  	p.first = p.prod[p.off]
  2189  
  2190  	if pidebug != 0 && foutput != nil {
  2191  		fmt.Fprintf(foutput, "putitem(%v), state %v\n", writem(p), nstate)
  2192  	}
  2193  	j := pstate[nstate+1]
  2194  	if j >= len(statemem) {
  2195  		asm := make([]Item, j+STATEINC)
  2196  		copy(asm, statemem)
  2197  		statemem = asm
  2198  	}
  2199  	statemem[j].pitem = p
  2200  	if nolook == 0 {
  2201  		s := mkset()
  2202  		copy(s, set)
  2203  		statemem[j].look = s
  2204  	}
  2205  	j++
  2206  	pstate[nstate+1] = j
  2207  }
  2208  
  2209  //
  2210  // creates output string for item pointed to by pp
  2211  //
  2212  func writem(pp Pitem) string {
  2213  	var i int
  2214  
  2215  	p := pp.prod
  2216  	q := chcopy(nontrst[prdptr[pp.prodno][0]-NTBASE].name) + ": "
  2217  	npi := pp.off
  2218  
  2219  	pi := aryeq(p, prdptr[pp.prodno])
  2220  
  2221  	for {
  2222  		c := ' '
  2223  		if pi == npi {
  2224  			c = '.'
  2225  		}
  2226  		q += string(c)
  2227  
  2228  		i = p[pi]
  2229  		pi++
  2230  		if i <= 0 {
  2231  			break
  2232  		}
  2233  		q += chcopy(symnam(i))
  2234  	}
  2235  
  2236  	// an item calling for a reduction
  2237  	i = p[npi]
  2238  	if i < 0 {
  2239  		q += fmt.Sprintf("    (%v)", -i)
  2240  	}
  2241  
  2242  	return q
  2243  }
  2244  
  2245  //
  2246  // pack state i from temp1 into amem
  2247  //
  2248  func apack(p []int, n int) int {
  2249  	//
  2250  	// we don't need to worry about checking because
  2251  	// we will only look at entries known to be there...
  2252  	// eliminate leading and trailing 0's
  2253  	//
  2254  	off := 0
  2255  	pp := 0
  2256  	for ; pp <= n && p[pp] == 0; pp++ {
  2257  		off--
  2258  	}
  2259  
  2260  	// no actions
  2261  	if pp > n {
  2262  		return 0
  2263  	}
  2264  	for ; n > pp && p[n] == 0; n-- {
  2265  	}
  2266  	p = p[pp : n+1]
  2267  
  2268  	// now, find a place for the elements from p to q, inclusive
  2269  	r := len(amem) - len(p)
  2270  
  2271  nextk:
  2272  	for rr := 0; rr <= r; rr++ {
  2273  		qq := rr
  2274  		for pp = 0; pp < len(p); pp++ {
  2275  			if p[pp] != 0 {
  2276  				if p[pp] != amem[qq] && amem[qq] != 0 {
  2277  					continue nextk
  2278  				}
  2279  			}
  2280  			qq++
  2281  		}
  2282  
  2283  		// we have found an acceptable k
  2284  		if pkdebug != 0 && foutput != nil {
  2285  			fmt.Fprintf(foutput, "off = %v, k = %v\n", off+rr, rr)
  2286  		}
  2287  		qq = rr
  2288  		for pp = 0; pp < len(p); pp++ {
  2289  			if p[pp] != 0 {
  2290  				if qq > memp {
  2291  					memp = qq
  2292  				}
  2293  				amem[qq] = p[pp]
  2294  			}
  2295  			qq++
  2296  		}
  2297  		if pkdebug != 0 && foutput != nil {
  2298  			for pp = 0; pp <= memp; pp += 10 {
  2299  				fmt.Fprintf(foutput, "\n")
  2300  				for qq = pp; qq <= pp+9; qq++ {
  2301  					fmt.Fprintf(foutput, "%v ", amem[qq])
  2302  				}
  2303  				fmt.Fprintf(foutput, "\n")
  2304  			}
  2305  		}
  2306  		return off + rr
  2307  	}
  2308  	errorf("no space in action table")
  2309  	return 0
  2310  }
  2311  
  2312  //
  2313  // print the output for the states
  2314  //
  2315  func output() {
  2316  	var c, u, v int
  2317  
  2318  	if !lflag {
  2319  		fmt.Fprintf(ftable, "\n//line yacctab:1")
  2320  	}
  2321  	fmt.Fprintf(ftable, "\nvar %sExca = [...]int{\n", prefix)
  2322  
  2323  	if len(errors) > 0 {
  2324  		stateTable = make([]Row, nstate)
  2325  	}
  2326  
  2327  	noset := mkset()
  2328  
  2329  	// output the stuff for state i
  2330  	for i := 0; i < nstate; i++ {
  2331  		nolook = 0
  2332  		if tystate[i] != MUSTLOOKAHEAD {
  2333  			nolook = 1
  2334  		}
  2335  		closure(i)
  2336  
  2337  		// output actions
  2338  		nolook = 1
  2339  		aryfil(temp1, ntokens+nnonter+1, 0)
  2340  		for u = 0; u < cwp; u++ {
  2341  			c = wsets[u].pitem.first
  2342  			if c > 1 && c < NTBASE && temp1[c] == 0 {
  2343  				for v = u; v < cwp; v++ {
  2344  					if c == wsets[v].pitem.first {
  2345  						putitem(wsets[v].pitem, noset)
  2346  					}
  2347  				}
  2348  				temp1[c] = state(c)
  2349  			} else if c > NTBASE {
  2350  				c -= NTBASE
  2351  				if temp1[c+ntokens] == 0 {
  2352  					temp1[c+ntokens] = amem[indgo[i]+c]
  2353  				}
  2354  			}
  2355  		}
  2356  		if i == 1 {
  2357  			temp1[1] = ACCEPTCODE
  2358  		}
  2359  
  2360  		// now, we have the shifts; look at the reductions
  2361  		lastred = 0
  2362  		for u = 0; u < cwp; u++ {
  2363  			c = wsets[u].pitem.first
  2364  
  2365  			// reduction
  2366  			if c > 0 {
  2367  				continue
  2368  			}
  2369  			lastred = -c
  2370  			us := wsets[u].ws
  2371  			for k := 0; k <= ntokens; k++ {
  2372  				if bitset(us, k) == 0 {
  2373  					continue
  2374  				}
  2375  				if temp1[k] == 0 {
  2376  					temp1[k] = c
  2377  				} else if temp1[k] < 0 { // reduce/reduce conflict
  2378  					if foutput != nil {
  2379  						fmt.Fprintf(foutput,
  2380  							"\n %v: reduce/reduce conflict  (red'ns "+
  2381  								"%v and %v) on %v",
  2382  							i, -temp1[k], lastred, symnam(k))
  2383  					}
  2384  					if -temp1[k] > lastred {
  2385  						temp1[k] = -lastred
  2386  					}
  2387  					zzrrconf++
  2388  				} else {
  2389  					// potential shift/reduce conflict
  2390  					precftn(lastred, k, i)
  2391  				}
  2392  			}
  2393  		}
  2394  		wract(i)
  2395  	}
  2396  
  2397  	fmt.Fprintf(ftable, "}\n")
  2398  	ftable.WriteRune('\n')
  2399  	fmt.Fprintf(ftable, "const %sPrivate = %v\n", prefix, PRIVATE)
  2400  }
  2401  
  2402  //
  2403  // decide a shift/reduce conflict by precedence.
  2404  // r is a rule number, t a token number
  2405  // the conflict is in state s
  2406  // temp1[t] is changed to reflect the action
  2407  //
  2408  func precftn(r, t, s int) {
  2409  	var action int
  2410  
  2411  	lp := levprd[r]
  2412  	lt := toklev[t]
  2413  	if PLEVEL(lt) == 0 || PLEVEL(lp) == 0 {
  2414  		// conflict
  2415  		if foutput != nil {
  2416  			fmt.Fprintf(foutput,
  2417  				"\n%v: shift/reduce conflict (shift %v(%v), red'n %v(%v)) on %v",
  2418  				s, temp1[t], PLEVEL(lt), r, PLEVEL(lp), symnam(t))
  2419  		}
  2420  		zzsrconf++
  2421  		return
  2422  	}
  2423  	if PLEVEL(lt) == PLEVEL(lp) {
  2424  		action = ASSOC(lt)
  2425  	} else if PLEVEL(lt) > PLEVEL(lp) {
  2426  		action = RASC // shift
  2427  	} else {
  2428  		action = LASC
  2429  	} // reduce
  2430  	switch action {
  2431  	case BASC: // error action
  2432  		temp1[t] = ERRCODE
  2433  	case LASC: // reduce
  2434  		temp1[t] = -r
  2435  	}
  2436  }
  2437  
  2438  //
  2439  // output state i
  2440  // temp1 has the actions, lastred the default
  2441  //
  2442  func wract(i int) {
  2443  	var p, p1 int
  2444  
  2445  	// find the best choice for lastred
  2446  	lastred = 0
  2447  	ntimes := 0
  2448  	for j := 0; j <= ntokens; j++ {
  2449  		if temp1[j] >= 0 {
  2450  			continue
  2451  		}
  2452  		if temp1[j]+lastred == 0 {
  2453  			continue
  2454  		}
  2455  		// count the number of appearances of temp1[j]
  2456  		count := 0
  2457  		tred := -temp1[j]
  2458  		levprd[tred] |= REDFLAG
  2459  		for p = 0; p <= ntokens; p++ {
  2460  			if temp1[p]+tred == 0 {
  2461  				count++
  2462  			}
  2463  		}
  2464  		if count > ntimes {
  2465  			lastred = tred
  2466  			ntimes = count
  2467  		}
  2468  	}
  2469  
  2470  	//
  2471  	// for error recovery, arrange that, if there is a shift on the
  2472  	// error recovery token, `error', that the default be the error action
  2473  	//
  2474  	if temp1[2] > 0 {
  2475  		lastred = 0
  2476  	}
  2477  
  2478  	// clear out entries in temp1 which equal lastred
  2479  	// count entries in optst table
  2480  	n := 0
  2481  	for p = 0; p <= ntokens; p++ {
  2482  		p1 = temp1[p]
  2483  		if p1+lastred == 0 {
  2484  			temp1[p] = 0
  2485  			p1 = 0
  2486  		}
  2487  		if p1 > 0 && p1 != ACCEPTCODE && p1 != ERRCODE {
  2488  			n++
  2489  		}
  2490  	}
  2491  
  2492  	wrstate(i)
  2493  	defact[i] = lastred
  2494  	flag := 0
  2495  	os := make([]int, n*2)
  2496  	n = 0
  2497  	for p = 0; p <= ntokens; p++ {
  2498  		p1 = temp1[p]
  2499  		if p1 != 0 {
  2500  			if p1 < 0 {
  2501  				p1 = -p1
  2502  			} else if p1 == ACCEPTCODE {
  2503  				p1 = -1
  2504  			} else if p1 == ERRCODE {
  2505  				p1 = 0
  2506  			} else {
  2507  				os[n] = p
  2508  				n++
  2509  				os[n] = p1
  2510  				n++
  2511  				zzacent++
  2512  				continue
  2513  			}
  2514  			if flag == 0 {
  2515  				fmt.Fprintf(ftable, "\t-1, %v,\n", i)
  2516  			}
  2517  			flag++
  2518  			fmt.Fprintf(ftable, "\t%v, %v,\n", p, p1)
  2519  			zzexcp++
  2520  		}
  2521  	}
  2522  	if flag != 0 {
  2523  		defact[i] = -2
  2524  		fmt.Fprintf(ftable, "\t-2, %v,\n", lastred)
  2525  	}
  2526  	optst[i] = os
  2527  }
  2528  
  2529  //
  2530  // writes state i
  2531  //
  2532  func wrstate(i int) {
  2533  	var j0, j1, u int
  2534  	var pp, qq int
  2535  
  2536  	if len(errors) > 0 {
  2537  		actions := append([]int(nil), temp1...)
  2538  		defaultAction := ERRCODE
  2539  		if lastred != 0 {
  2540  			defaultAction = -lastred
  2541  		}
  2542  		stateTable[i] = Row{actions, defaultAction}
  2543  	}
  2544  
  2545  	if foutput == nil {
  2546  		return
  2547  	}
  2548  	fmt.Fprintf(foutput, "\nstate %v\n", i)
  2549  	qq = pstate[i+1]
  2550  	for pp = pstate[i]; pp < qq; pp++ {
  2551  		fmt.Fprintf(foutput, "\t%v\n", writem(statemem[pp].pitem))
  2552  	}
  2553  	if tystate[i] == MUSTLOOKAHEAD {
  2554  		// print out empty productions in closure
  2555  		for u = pstate[i+1] - pstate[i]; u < cwp; u++ {
  2556  			if wsets[u].pitem.first < 0 {
  2557  				fmt.Fprintf(foutput, "\t%v\n", writem(wsets[u].pitem))
  2558  			}
  2559  		}
  2560  	}
  2561  
  2562  	// check for state equal to another
  2563  	for j0 = 0; j0 <= ntokens; j0++ {
  2564  		j1 = temp1[j0]
  2565  		if j1 != 0 {
  2566  			fmt.Fprintf(foutput, "\n\t%v  ", symnam(j0))
  2567  
  2568  			// shift, error, or accept
  2569  			if j1 > 0 {
  2570  				if j1 == ACCEPTCODE {
  2571  					fmt.Fprintf(foutput, "accept")
  2572  				} else if j1 == ERRCODE {
  2573  					fmt.Fprintf(foutput, "error")
  2574  				} else {
  2575  					fmt.Fprintf(foutput, "shift %v", j1)
  2576  				}
  2577  			} else {
  2578  				fmt.Fprintf(foutput, "reduce %v (src line %v)", -j1, rlines[-j1])
  2579  			}
  2580  		}
  2581  	}
  2582  
  2583  	// output the final production
  2584  	if lastred != 0 {
  2585  		fmt.Fprintf(foutput, "\n\t.  reduce %v (src line %v)\n\n",
  2586  			lastred, rlines[lastred])
  2587  	} else {
  2588  		fmt.Fprintf(foutput, "\n\t.  error\n\n")
  2589  	}
  2590  
  2591  	// now, output nonterminal actions
  2592  	j1 = ntokens
  2593  	for j0 = 1; j0 <= nnonter; j0++ {
  2594  		j1++
  2595  		if temp1[j1] != 0 {
  2596  			fmt.Fprintf(foutput, "\t%v  goto %v\n", symnam(j0+NTBASE), temp1[j1])
  2597  		}
  2598  	}
  2599  }
  2600  
  2601  //
  2602  // output the gotos for the nontermninals
  2603  //
  2604  func go2out() {
  2605  	for i := 1; i <= nnonter; i++ {
  2606  		go2gen(i)
  2607  
  2608  		// find the best one to make default
  2609  		best := -1
  2610  		times := 0
  2611  
  2612  		// is j the most frequent
  2613  		for j := 0; j < nstate; j++ {
  2614  			if tystate[j] == 0 {
  2615  				continue
  2616  			}
  2617  			if tystate[j] == best {
  2618  				continue
  2619  			}
  2620  
  2621  			// is tystate[j] the most frequent
  2622  			count := 0
  2623  			cbest := tystate[j]
  2624  			for k := j; k < nstate; k++ {
  2625  				if tystate[k] == cbest {
  2626  					count++
  2627  				}
  2628  			}
  2629  			if count > times {
  2630  				best = cbest
  2631  				times = count
  2632  			}
  2633  		}
  2634  
  2635  		// best is now the default entry
  2636  		zzgobest += times - 1
  2637  		n := 0
  2638  		for j := 0; j < nstate; j++ {
  2639  			if tystate[j] != 0 && tystate[j] != best {
  2640  				n++
  2641  			}
  2642  		}
  2643  		goent := make([]int, 2*n+1)
  2644  		n = 0
  2645  		for j := 0; j < nstate; j++ {
  2646  			if tystate[j] != 0 && tystate[j] != best {
  2647  				goent[n] = j
  2648  				n++
  2649  				goent[n] = tystate[j]
  2650  				n++
  2651  				zzgoent++
  2652  			}
  2653  		}
  2654  
  2655  		// now, the default
  2656  		if best == -1 {
  2657  			best = 0
  2658  		}
  2659  
  2660  		zzgoent++
  2661  		goent[n] = best
  2662  		yypgo[i] = goent
  2663  	}
  2664  }
  2665  
  2666  //
  2667  // output the gotos for nonterminal c
  2668  //
  2669  func go2gen(c int) {
  2670  	var i, cc, p, q int
  2671  
  2672  	// first, find nonterminals with gotos on c
  2673  	aryfil(temp1, nnonter+1, 0)
  2674  	temp1[c] = 1
  2675  	work := 1
  2676  	for work != 0 {
  2677  		work = 0
  2678  		for i = 0; i < nprod; i++ {
  2679  			// cc is a nonterminal with a goto on c
  2680  			cc = prdptr[i][1] - NTBASE
  2681  			if cc >= 0 && temp1[cc] != 0 {
  2682  				// thus, the left side of production i does too
  2683  				cc = prdptr[i][0] - NTBASE
  2684  				if temp1[cc] == 0 {
  2685  					work = 1
  2686  					temp1[cc] = 1
  2687  				}
  2688  			}
  2689  		}
  2690  	}
  2691  
  2692  	// now, we have temp1[c] = 1 if a goto on c in closure of cc
  2693  	if g2debug != 0 && foutput != nil {
  2694  		fmt.Fprintf(foutput, "%v: gotos on ", nontrst[c].name)
  2695  		for i = 0; i <= nnonter; i++ {
  2696  			if temp1[i] != 0 {
  2697  				fmt.Fprintf(foutput, "%v ", nontrst[i].name)
  2698  			}
  2699  		}
  2700  		fmt.Fprintf(foutput, "\n")
  2701  	}
  2702  
  2703  	// now, go through and put gotos into tystate
  2704  	aryfil(tystate, nstate, 0)
  2705  	for i = 0; i < nstate; i++ {
  2706  		q = pstate[i+1]
  2707  		for p = pstate[i]; p < q; p++ {
  2708  			cc = statemem[p].pitem.first
  2709  			if cc >= NTBASE {
  2710  				// goto on c is possible
  2711  				if temp1[cc-NTBASE] != 0 {
  2712  					tystate[i] = amem[indgo[i]+c]
  2713  					break
  2714  				}
  2715  			}
  2716  		}
  2717  	}
  2718  }
  2719  
  2720  //
  2721  // in order to free up the mem and amem arrays for the optimizer,
  2722  // and still be able to output yyr1, etc., after the sizes of
  2723  // the action array is known, we hide the nonterminals
  2724  // derived by productions in levprd.
  2725  //
  2726  func hideprod() {
  2727  	nred := 0
  2728  	levprd[0] = 0
  2729  	for i := 1; i < nprod; i++ {
  2730  		if (levprd[i] & REDFLAG) == 0 {
  2731  			if foutput != nil {
  2732  				fmt.Fprintf(foutput, "Rule not reduced: %v\n",
  2733  					writem(Pitem{prdptr[i], 0, 0, i}))
  2734  			}
  2735  			fmt.Printf("rule %v never reduced\n", writem(Pitem{prdptr[i], 0, 0, i}))
  2736  			nred++
  2737  		}
  2738  		levprd[i] = prdptr[i][0] - NTBASE
  2739  	}
  2740  	if nred != 0 {
  2741  		fmt.Printf("%v rules never reduced\n", nred)
  2742  	}
  2743  }
  2744  
  2745  func callopt() {
  2746  	var j, k, p, q, i int
  2747  	var v []int
  2748  
  2749  	pgo = make([]int, nnonter+1)
  2750  	pgo[0] = 0
  2751  	maxoff = 0
  2752  	maxspr = 0
  2753  	for i = 0; i < nstate; i++ {
  2754  		k = 32000
  2755  		j = 0
  2756  		v = optst[i]
  2757  		q = len(v)
  2758  		for p = 0; p < q; p += 2 {
  2759  			if v[p] > j {
  2760  				j = v[p]
  2761  			}
  2762  			if v[p] < k {
  2763  				k = v[p]
  2764  			}
  2765  		}
  2766  
  2767  		// nontrivial situation
  2768  		if k <= j {
  2769  			// j is now the range
  2770  			//			j -= k;			// call scj
  2771  			if k > maxoff {
  2772  				maxoff = k
  2773  			}
  2774  		}
  2775  		tystate[i] = q + 2*j
  2776  		if j > maxspr {
  2777  			maxspr = j
  2778  		}
  2779  	}
  2780  
  2781  	// initialize ggreed table
  2782  	ggreed = make([]int, nnonter+1)
  2783  	for i = 1; i <= nnonter; i++ {
  2784  		ggreed[i] = 1
  2785  		j = 0
  2786  
  2787  		// minimum entry index is always 0
  2788  		v = yypgo[i]
  2789  		q = len(v) - 1
  2790  		for p = 0; p < q; p += 2 {
  2791  			ggreed[i] += 2
  2792  			if v[p] > j {
  2793  				j = v[p]
  2794  			}
  2795  		}
  2796  		ggreed[i] = ggreed[i] + 2*j
  2797  		if j > maxoff {
  2798  			maxoff = j
  2799  		}
  2800  	}
  2801  
  2802  	// now, prepare to put the shift actions into the amem array
  2803  	for i = 0; i < ACTSIZE; i++ {
  2804  		amem[i] = 0
  2805  	}
  2806  	maxa = 0
  2807  	for i = 0; i < nstate; i++ {
  2808  		if tystate[i] == 0 && adb > 1 {
  2809  			fmt.Fprintf(ftable, "State %v: null\n", i)
  2810  		}
  2811  		indgo[i] = yyFlag
  2812  	}
  2813  
  2814  	i = nxti()
  2815  	for i != NOMORE {
  2816  		if i >= 0 {
  2817  			stin(i)
  2818  		} else {
  2819  			gin(-i)
  2820  		}
  2821  		i = nxti()
  2822  	}
  2823  
  2824  	// print amem array
  2825  	if adb > 2 {
  2826  		for p = 0; p <= maxa; p += 10 {
  2827  			fmt.Fprintf(ftable, "%v  ", p)
  2828  			for i = 0; i < 10; i++ {
  2829  				fmt.Fprintf(ftable, "%v  ", amem[p+i])
  2830  			}
  2831  			ftable.WriteRune('\n')
  2832  		}
  2833  	}
  2834  
  2835  	aoutput()
  2836  	osummary()
  2837  }
  2838  
  2839  //
  2840  // finds the next i
  2841  //
  2842  func nxti() int {
  2843  	max := 0
  2844  	maxi := 0
  2845  	for i := 1; i <= nnonter; i++ {
  2846  		if ggreed[i] >= max {
  2847  			max = ggreed[i]
  2848  			maxi = -i
  2849  		}
  2850  	}
  2851  	for i := 0; i < nstate; i++ {
  2852  		if tystate[i] >= max {
  2853  			max = tystate[i]
  2854  			maxi = i
  2855  		}
  2856  	}
  2857  	if max == 0 {
  2858  		return NOMORE
  2859  	}
  2860  	return maxi
  2861  }
  2862  
  2863  func gin(i int) {
  2864  	var s int
  2865  
  2866  	// enter gotos on nonterminal i into array amem
  2867  	ggreed[i] = 0
  2868  
  2869  	q := yypgo[i]
  2870  	nq := len(q) - 1
  2871  
  2872  	// now, find amem place for it
  2873  nextgp:
  2874  	for p := 0; p < ACTSIZE; p++ {
  2875  		if amem[p] != 0 {
  2876  			continue
  2877  		}
  2878  		for r := 0; r < nq; r += 2 {
  2879  			s = p + q[r] + 1
  2880  			if s > maxa {
  2881  				maxa = s
  2882  				if maxa >= ACTSIZE {
  2883  					errorf("a array overflow")
  2884  				}
  2885  			}
  2886  			if amem[s] != 0 {
  2887  				continue nextgp
  2888  			}
  2889  		}
  2890  
  2891  		// we have found amem spot
  2892  		amem[p] = q[nq]
  2893  		if p > maxa {
  2894  			maxa = p
  2895  		}
  2896  		for r := 0; r < nq; r += 2 {
  2897  			s = p + q[r] + 1
  2898  			amem[s] = q[r+1]
  2899  		}
  2900  		pgo[i] = p
  2901  		if adb > 1 {
  2902  			fmt.Fprintf(ftable, "Nonterminal %v, entry at %v\n", i, pgo[i])
  2903  		}
  2904  		return
  2905  	}
  2906  	errorf("cannot place goto %v\n", i)
  2907  }
  2908  
  2909  func stin(i int) {
  2910  	var s int
  2911  
  2912  	tystate[i] = 0
  2913  
  2914  	// enter state i into the amem array
  2915  	q := optst[i]
  2916  	nq := len(q)
  2917  
  2918  nextn:
  2919  	// find an acceptable place
  2920  	for n := -maxoff; n < ACTSIZE; n++ {
  2921  		flag := 0
  2922  		for r := 0; r < nq; r += 2 {
  2923  			s = q[r] + n
  2924  			if s < 0 || s > ACTSIZE {
  2925  				continue nextn
  2926  			}
  2927  			if amem[s] == 0 {
  2928  				flag++
  2929  			} else if amem[s] != q[r+1] {
  2930  				continue nextn
  2931  			}
  2932  		}
  2933  
  2934  		// check the position equals another only if the states are identical
  2935  		for j := 0; j < nstate; j++ {
  2936  			if indgo[j] == n {
  2937  
  2938  				// we have some disagreement
  2939  				if flag != 0 {
  2940  					continue nextn
  2941  				}
  2942  				if nq == len(optst[j]) {
  2943  
  2944  					// states are equal
  2945  					indgo[i] = n
  2946  					if adb > 1 {
  2947  						fmt.Fprintf(ftable, "State %v: entry at"+
  2948  							"%v equals state %v\n",
  2949  							i, n, j)
  2950  					}
  2951  					return
  2952  				}
  2953  
  2954  				// we have some disagreement
  2955  				continue nextn
  2956  			}
  2957  		}
  2958  
  2959  		for r := 0; r < nq; r += 2 {
  2960  			s = q[r] + n
  2961  			if s > maxa {
  2962  				maxa = s
  2963  			}
  2964  			if amem[s] != 0 && amem[s] != q[r+1] {
  2965  				errorf("clobber of a array, pos'n %v, by %v", s, q[r+1])
  2966  			}
  2967  			amem[s] = q[r+1]
  2968  		}
  2969  		indgo[i] = n
  2970  		if adb > 1 {
  2971  			fmt.Fprintf(ftable, "State %v: entry at %v\n", i, indgo[i])
  2972  		}
  2973  		return
  2974  	}
  2975  	errorf("Error; failure to place state %v", i)
  2976  }
  2977  
  2978  //
  2979  // this version is for limbo
  2980  // write out the optimized parser
  2981  //
  2982  func aoutput() {
  2983  	ftable.WriteRune('\n')
  2984  	fmt.Fprintf(ftable, "const %sLast = %v\n", prefix, maxa+1)
  2985  	arout("Act", amem, maxa+1)
  2986  	arout("Pact", indgo, nstate)
  2987  	arout("Pgo", pgo, nnonter+1)
  2988  }
  2989  
  2990  //
  2991  // put out other arrays, copy the parsers
  2992  //
  2993  func others() {
  2994  	var i, j int
  2995  
  2996  	arout("R1", levprd, nprod)
  2997  	aryfil(temp1, nprod, 0)
  2998  
  2999  	//
  3000  	//yyr2 is the number of rules for each production
  3001  	//
  3002  	for i = 1; i < nprod; i++ {
  3003  		temp1[i] = len(prdptr[i]) - 2
  3004  	}
  3005  	arout("R2", temp1, nprod)
  3006  
  3007  	aryfil(temp1, nstate, -1000)
  3008  	for i = 0; i <= ntokens; i++ {
  3009  		for j := tstates[i]; j != 0; j = mstates[j] {
  3010  			temp1[j] = i
  3011  		}
  3012  	}
  3013  	for i = 0; i <= nnonter; i++ {
  3014  		for j = ntstates[i]; j != 0; j = mstates[j] {
  3015  			temp1[j] = -i
  3016  		}
  3017  	}
  3018  	arout("Chk", temp1, nstate)
  3019  	arout("Def", defact, nstate)
  3020  
  3021  	// put out token translation tables
  3022  	// table 1 has 0-256
  3023  	aryfil(temp1, 256, 0)
  3024  	c := 0
  3025  	for i = 1; i <= ntokens; i++ {
  3026  		j = tokset[i].value
  3027  		if j >= 0 && j < 256 {
  3028  			if temp1[j] != 0 {
  3029  				fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n")
  3030  				fmt.Printf("	%s and %s\n", tokset[i].name, tokset[temp1[j]].name)
  3031  				nerrors++
  3032  			}
  3033  			temp1[j] = i
  3034  			if j > c {
  3035  				c = j
  3036  			}
  3037  		}
  3038  	}
  3039  	for i = 0; i <= c; i++ {
  3040  		if temp1[i] == 0 {
  3041  			temp1[i] = YYLEXUNK
  3042  		}
  3043  	}
  3044  	arout("Tok1", temp1, c+1)
  3045  
  3046  	// table 2 has PRIVATE-PRIVATE+256
  3047  	aryfil(temp1, 256, 0)
  3048  	c = 0
  3049  	for i = 1; i <= ntokens; i++ {
  3050  		j = tokset[i].value - PRIVATE
  3051  		if j >= 0 && j < 256 {
  3052  			if temp1[j] != 0 {
  3053  				fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n")
  3054  				fmt.Printf("	%s and %s\n", tokset[i].name, tokset[temp1[j]].name)
  3055  				nerrors++
  3056  			}
  3057  			temp1[j] = i
  3058  			if j > c {
  3059  				c = j
  3060  			}
  3061  		}
  3062  	}
  3063  	arout("Tok2", temp1, c+1)
  3064  
  3065  	// table 3 has everything else
  3066  	ftable.WriteRune('\n')
  3067  	fmt.Fprintf(ftable, "var %sTok3 = [...]int{\n\t", prefix)
  3068  	c = 0
  3069  	for i = 1; i <= ntokens; i++ {
  3070  		j = tokset[i].value
  3071  		if j >= 0 && j < 256 {
  3072  			continue
  3073  		}
  3074  		if j >= PRIVATE && j < 256+PRIVATE {
  3075  			continue
  3076  		}
  3077  
  3078  		if c%5 != 0 {
  3079  			ftable.WriteRune(' ')
  3080  		}
  3081  		fmt.Fprintf(ftable, "%d, %d,", j, i)
  3082  		c++
  3083  		if c%5 == 0 {
  3084  			fmt.Fprint(ftable, "\n\t")
  3085  		}
  3086  	}
  3087  	if c%5 != 0 {
  3088  		ftable.WriteRune(' ')
  3089  	}
  3090  	fmt.Fprintf(ftable, "%d,\n}\n", 0)
  3091  
  3092  	// Custom error messages.
  3093  	fmt.Fprintf(ftable, "\n")
  3094  	fmt.Fprintf(ftable, "var %sErrorMessages = [...]struct {\n", prefix)
  3095  	fmt.Fprintf(ftable, "\tstate int\n")
  3096  	fmt.Fprintf(ftable, "\ttoken int\n")
  3097  	fmt.Fprintf(ftable, "\tmsg   string\n")
  3098  	fmt.Fprintf(ftable, "}{\n")
  3099  	for _, error := range errors {
  3100  		lineno = error.lineno
  3101  		state, token := runMachine(error.tokens)
  3102  		fmt.Fprintf(ftable, "\t{%v, %v, %s},\n", state, token, error.msg)
  3103  	}
  3104  	fmt.Fprintf(ftable, "}\n")
  3105  
  3106  	// copy parser text
  3107  	ch := getrune(finput)
  3108  	for ch != EOF {
  3109  		ftable.WriteRune(ch)
  3110  		ch = getrune(finput)
  3111  	}
  3112  
  3113  	// copy yaccpar
  3114  	if !lflag {
  3115  		fmt.Fprintf(ftable, "\n//line yaccpar:1\n")
  3116  	}
  3117  
  3118  	parts := strings.SplitN(yaccpar, prefix+"run()", 2)
  3119  	fmt.Fprintf(ftable, "%v", parts[0])
  3120  	ftable.Write(fcode.Bytes())
  3121  	fmt.Fprintf(ftable, "%v", parts[1])
  3122  }
  3123  
  3124  func runMachine(tokens []string) (state, token int) {
  3125  	var stack []int
  3126  	i := 0
  3127  	token = -1
  3128  
  3129  Loop:
  3130  	if token < 0 {
  3131  		token = chfind(2, tokens[i])
  3132  		i++
  3133  	}
  3134  
  3135  	row := stateTable[state]
  3136  
  3137  	c := token
  3138  	if token >= NTBASE {
  3139  		c = token - NTBASE + ntokens
  3140  	}
  3141  	action := row.actions[c]
  3142  	if action == 0 {
  3143  		action = row.defaultAction
  3144  	}
  3145  
  3146  	switch {
  3147  	case action == ACCEPTCODE:
  3148  		errorf("tokens are accepted")
  3149  		return
  3150  	case action == ERRCODE:
  3151  		if token >= NTBASE {
  3152  			errorf("error at non-terminal token %s", symnam(token))
  3153  		}
  3154  		return
  3155  	case action > 0:
  3156  		// Shift to state action.
  3157  		stack = append(stack, state)
  3158  		state = action
  3159  		token = -1
  3160  		goto Loop
  3161  	default:
  3162  		// Reduce by production -action.
  3163  		prod := prdptr[-action]
  3164  		if rhsLen := len(prod) - 2; rhsLen > 0 {
  3165  			n := len(stack) - rhsLen
  3166  			state = stack[n]
  3167  			stack = stack[:n]
  3168  		}
  3169  		if token >= 0 {
  3170  			i--
  3171  		}
  3172  		token = prod[0]
  3173  		goto Loop
  3174  	}
  3175  }
  3176  
  3177  func arout(s string, v []int, n int) {
  3178  	s = prefix + s
  3179  	ftable.WriteRune('\n')
  3180  	fmt.Fprintf(ftable, "var %v = [...]int{", s)
  3181  	for i := 0; i < n; i++ {
  3182  		if i%10 == 0 {
  3183  			fmt.Fprintf(ftable, "\n\t")
  3184  		} else {
  3185  			ftable.WriteRune(' ')
  3186  		}
  3187  		fmt.Fprintf(ftable, "%d,", v[i])
  3188  	}
  3189  	fmt.Fprintf(ftable, "\n}\n")
  3190  }
  3191  
  3192  //
  3193  // output the summary on y.output
  3194  //
  3195  func summary() {
  3196  	if foutput != nil {
  3197  		fmt.Fprintf(foutput, "\n%v terminals, %v nonterminals\n", ntokens, nnonter+1)
  3198  		fmt.Fprintf(foutput, "%v grammar rules, %v/%v states\n", nprod, nstate, NSTATES)
  3199  		fmt.Fprintf(foutput, "%v shift/reduce, %v reduce/reduce conflicts reported\n", zzsrconf, zzrrconf)
  3200  		fmt.Fprintf(foutput, "%v working sets used\n", len(wsets))
  3201  		fmt.Fprintf(foutput, "memory: parser %v/%v\n", memp, ACTSIZE)
  3202  		fmt.Fprintf(foutput, "%v extra closures\n", zzclose-2*nstate)
  3203  		fmt.Fprintf(foutput, "%v shift entries, %v exceptions\n", zzacent, zzexcp)
  3204  		fmt.Fprintf(foutput, "%v goto entries\n", zzgoent)
  3205  		fmt.Fprintf(foutput, "%v entries saved by goto default\n", zzgobest)
  3206  	}
  3207  	if zzsrconf != 0 || zzrrconf != 0 {
  3208  		fmt.Printf("\nconflicts: ")
  3209  		if zzsrconf != 0 {
  3210  			fmt.Printf("%v shift/reduce", zzsrconf)
  3211  		}
  3212  		if zzsrconf != 0 && zzrrconf != 0 {
  3213  			fmt.Printf(", ")
  3214  		}
  3215  		if zzrrconf != 0 {
  3216  			fmt.Printf("%v reduce/reduce", zzrrconf)
  3217  		}
  3218  		fmt.Printf("\n")
  3219  	}
  3220  }
  3221  
  3222  //
  3223  // write optimizer summary
  3224  //
  3225  func osummary() {
  3226  	if foutput == nil {
  3227  		return
  3228  	}
  3229  	i := 0
  3230  	for p := maxa; p >= 0; p-- {
  3231  		if amem[p] == 0 {
  3232  			i++
  3233  		}
  3234  	}
  3235  
  3236  	fmt.Fprintf(foutput, "Optimizer space used: output %v/%v\n", maxa+1, ACTSIZE)
  3237  	fmt.Fprintf(foutput, "%v table entries, %v zero\n", maxa+1, i)
  3238  	fmt.Fprintf(foutput, "maximum spread: %v, maximum offset: %v\n", maxspr, maxoff)
  3239  }
  3240  
  3241  //
  3242  // copies and protects "'s in q
  3243  //
  3244  func chcopy(q string) string {
  3245  	s := ""
  3246  	i := 0
  3247  	j := 0
  3248  	for i = 0; i < len(q); i++ {
  3249  		if q[i] == '"' {
  3250  			s += q[j:i] + "\\"
  3251  			j = i
  3252  		}
  3253  	}
  3254  	return s + q[j:i]
  3255  }
  3256  
  3257  func usage() {
  3258  	fmt.Fprintf(stderr, "usage: yacc [-o output] [-v parsetable] input\n")
  3259  	exit(1)
  3260  }
  3261  
  3262  func bitset(set Lkset, bit int) int { return set[bit>>5] & (1 << uint(bit&31)) }
  3263  
  3264  func setbit(set Lkset, bit int) { set[bit>>5] |= (1 << uint(bit&31)) }
  3265  
  3266  func mkset() Lkset { return make([]int, tbitset) }
  3267  
  3268  //
  3269  // set a to the union of a and b
  3270  // return 1 if b is not a subset of a, 0 otherwise
  3271  //
  3272  func setunion(a, b []int) int {
  3273  	sub := 0
  3274  	for i := 0; i < tbitset; i++ {
  3275  		x := a[i]
  3276  		y := x | b[i]
  3277  		a[i] = y
  3278  		if y != x {
  3279  			sub = 1
  3280  		}
  3281  	}
  3282  	return sub
  3283  }
  3284  
  3285  func prlook(p Lkset) {
  3286  	if p == nil {
  3287  		fmt.Fprintf(foutput, "\tNULL")
  3288  		return
  3289  	}
  3290  	fmt.Fprintf(foutput, " { ")
  3291  	for j := 0; j <= ntokens; j++ {
  3292  		if bitset(p, j) != 0 {
  3293  			fmt.Fprintf(foutput, "%v ", symnam(j))
  3294  		}
  3295  	}
  3296  	fmt.Fprintf(foutput, "}")
  3297  }
  3298  
  3299  //
  3300  // utility routines
  3301  //
  3302  var peekrune rune
  3303  
  3304  func isdigit(c rune) bool { return c >= '0' && c <= '9' }
  3305  
  3306  func isword(c rune) bool {
  3307  	return c >= 0xa0 || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
  3308  }
  3309  
  3310  //
  3311  // return 1 if 2 arrays are equal
  3312  // return 0 if not equal
  3313  //
  3314  func aryeq(a []int, b []int) int {
  3315  	n := len(a)
  3316  	if len(b) != n {
  3317  		return 0
  3318  	}
  3319  	for ll := 0; ll < n; ll++ {
  3320  		if a[ll] != b[ll] {
  3321  			return 0
  3322  		}
  3323  	}
  3324  	return 1
  3325  }
  3326  
  3327  func getrune(f *bufio.Reader) rune {
  3328  	var r rune
  3329  
  3330  	if peekrune != 0 {
  3331  		if peekrune == EOF {
  3332  			return EOF
  3333  		}
  3334  		r = peekrune
  3335  		peekrune = 0
  3336  		return r
  3337  	}
  3338  
  3339  	c, n, err := f.ReadRune()
  3340  	if n == 0 {
  3341  		return EOF
  3342  	}
  3343  	if err != nil {
  3344  		errorf("read error: %v", err)
  3345  	}
  3346  	//fmt.Printf("rune = %v n=%v\n", string(c), n);
  3347  	return c
  3348  }
  3349  
  3350  func ungetrune(f *bufio.Reader, c rune) {
  3351  	if f != finput {
  3352  		panic("ungetc - not finput")
  3353  	}
  3354  	if peekrune != 0 {
  3355  		panic("ungetc - 2nd unget")
  3356  	}
  3357  	peekrune = c
  3358  }
  3359  
  3360  func open(s string) *bufio.Reader {
  3361  	fi, err := os.Open(s)
  3362  	if err != nil {
  3363  		errorf("error opening %v: %v", s, err)
  3364  	}
  3365  	//fmt.Printf("open %v\n", s);
  3366  	return bufio.NewReader(fi)
  3367  }
  3368  
  3369  func create(s string) *bufio.Writer {
  3370  	fo, err := os.Create(s)
  3371  	if err != nil {
  3372  		errorf("error creating %v: %v", s, err)
  3373  	}
  3374  	//fmt.Printf("create %v mode %v\n", s);
  3375  	return bufio.NewWriter(fo)
  3376  }
  3377  
  3378  //
  3379  // write out error comment
  3380  //
  3381  func lerrorf(lineno int, s string, v ...interface{}) {
  3382  	nerrors++
  3383  	fmt.Fprintf(stderr, s, v...)
  3384  	fmt.Fprintf(stderr, ": %v:%v\n", infile, lineno)
  3385  	if fatfl != 0 {
  3386  		summary()
  3387  		exit(1)
  3388  	}
  3389  }
  3390  
  3391  func errorf(s string, v ...interface{}) {
  3392  	lerrorf(lineno, s, v...)
  3393  }
  3394  
  3395  func exit(status int) {
  3396  	if ftable != nil {
  3397  		ftable.Flush()
  3398  		ftable = nil
  3399  		gofmt()
  3400  	}
  3401  	if foutput != nil {
  3402  		foutput.Flush()
  3403  		foutput = nil
  3404  	}
  3405  	if stderr != nil {
  3406  		stderr.Flush()
  3407  		stderr = nil
  3408  	}
  3409  	os.Exit(status)
  3410  }
  3411  
  3412  func gofmt() {
  3413  	src, err := os.ReadFile(oflag)
  3414  	if err != nil {
  3415  		return
  3416  	}
  3417  	src, err = format.Source(src)
  3418  	if err != nil {
  3419  		return
  3420  	}
  3421  	os.WriteFile(oflag, src, 0666)
  3422  }
  3423  
  3424  var yaccpar string // will be processed version of yaccpartext: s/$$/prefix/g
  3425  var yaccpartext = `
  3426  /*	parser for yacc output	*/
  3427  
  3428  func $$Iaddr(v interface{}) __yyunsafe__.Pointer {
  3429  	type h struct {
  3430  		t __yyunsafe__.Pointer
  3431  		p __yyunsafe__.Pointer
  3432  	}
  3433  	return (*h)(__yyunsafe__.Pointer(&v)).p
  3434  }
  3435  
  3436  var (
  3437  	$$Debug        = 0
  3438  	$$ErrorVerbose = false
  3439  )
  3440  
  3441  type $$Lexer interface {
  3442  	Lex(lval *$$SymType) int
  3443  	Error(s string)
  3444  }
  3445  
  3446  type $$Parser interface {
  3447  	Parse($$Lexer) int
  3448  	Lookahead() int
  3449  }
  3450  
  3451  type $$ParserImpl struct {
  3452  	lval  $$SymType
  3453  	stack [$$InitialStackSize]$$SymType
  3454  	char  int
  3455  }
  3456  
  3457  func (p *$$ParserImpl) Lookahead() int {
  3458  	return p.char
  3459  }
  3460  
  3461  func $$NewParser() $$Parser {
  3462  	return &$$ParserImpl{}
  3463  }
  3464  
  3465  const $$Flag = -1000
  3466  
  3467  func $$Tokname(c int) string {
  3468  	if c >= 1 && c-1 < len($$Toknames) {
  3469  		if $$Toknames[c-1] != "" {
  3470  			return $$Toknames[c-1]
  3471  		}
  3472  	}
  3473  	return __yyfmt__.Sprintf("tok-%v", c)
  3474  }
  3475  
  3476  func $$Statname(s int) string {
  3477  	if s >= 0 && s < len($$Statenames) {
  3478  		if $$Statenames[s] != "" {
  3479  			return $$Statenames[s]
  3480  		}
  3481  	}
  3482  	return __yyfmt__.Sprintf("state-%v", s)
  3483  }
  3484  
  3485  func $$ErrorMessage(state, lookAhead int) string {
  3486  	const TOKSTART = 4
  3487  
  3488  	if !$$ErrorVerbose {
  3489  		return "syntax error"
  3490  	}
  3491  
  3492  	for _, e := range $$ErrorMessages {
  3493  		if e.state == state && e.token == lookAhead {
  3494  			return "syntax error: " + e.msg
  3495  		}
  3496  	}
  3497  
  3498  	res := "syntax error: unexpected " + $$Tokname(lookAhead)
  3499  
  3500  	// To match Bison, suggest at most four expected tokens.
  3501  	expected := make([]int, 0, 4)
  3502  
  3503  	// Look for shiftable tokens.
  3504  	base := $$Pact[state]
  3505  	for tok := TOKSTART; tok-1 < len($$Toknames); tok++ {
  3506  		if n := base + tok; n >= 0 && n < $$Last && $$Chk[$$Act[n]] == tok {
  3507  			if len(expected) == cap(expected) {
  3508  				return res
  3509  			}
  3510  			expected = append(expected, tok)
  3511  		}
  3512  	}
  3513  
  3514  	if $$Def[state] == -2 {
  3515  		i := 0
  3516  		for $$Exca[i] != -1 || $$Exca[i+1] != state {
  3517  			i += 2
  3518  		}
  3519  
  3520  		// Look for tokens that we accept or reduce.
  3521  		for i += 2; $$Exca[i] >= 0; i += 2 {
  3522  			tok := $$Exca[i]
  3523  			if tok < TOKSTART || $$Exca[i+1] == 0 {
  3524  				continue
  3525  			}
  3526  			if len(expected) == cap(expected) {
  3527  				return res
  3528  			}
  3529  			expected = append(expected, tok)
  3530  		}
  3531  
  3532  		// If the default action is to accept or reduce, give up.
  3533  		if $$Exca[i+1] != 0 {
  3534  			return res
  3535  		}
  3536  	}
  3537  
  3538  	for i, tok := range expected {
  3539  		if i == 0 {
  3540  			res += ", expecting "
  3541  		} else {
  3542  			res += " or "
  3543  		}
  3544  		res += $$Tokname(tok)
  3545  	}
  3546  	return res
  3547  }
  3548  
  3549  func $$lex1(lex $$Lexer, lval *$$SymType) (char, token int) {
  3550  	token = 0
  3551  	char = lex.Lex(lval)
  3552  	if char <= 0 {
  3553  		token = $$Tok1[0]
  3554  		goto out
  3555  	}
  3556  	if char < len($$Tok1) {
  3557  		token = $$Tok1[char]
  3558  		goto out
  3559  	}
  3560  	if char >= $$Private {
  3561  		if char < $$Private+len($$Tok2) {
  3562  			token = $$Tok2[char-$$Private]
  3563  			goto out
  3564  		}
  3565  	}
  3566  	for i := 0; i < len($$Tok3); i += 2 {
  3567  		token = $$Tok3[i+0]
  3568  		if token == char {
  3569  			token = $$Tok3[i+1]
  3570  			goto out
  3571  		}
  3572  	}
  3573  
  3574  out:
  3575  	if token == 0 {
  3576  		token = $$Tok2[1] /* unknown char */
  3577  	}
  3578  	if $$Debug >= 3 {
  3579  		__yyfmt__.Printf("lex %s(%d)\n", $$Tokname(token), uint(char))
  3580  	}
  3581  	return char, token
  3582  }
  3583  
  3584  func $$Parse($$lex $$Lexer) int {
  3585  	return $$NewParser().Parse($$lex)
  3586  }
  3587  
  3588  func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int {
  3589  	var $$n int
  3590  	var $$VAL $$SymType
  3591  	var $$Dollar []$$SymType
  3592  	_ = $$Dollar // silence set and not used
  3593  	$$S := $$rcvr.stack[:]
  3594  
  3595  	Nerrs := 0   /* number of errors */
  3596  	Errflag := 0 /* error recovery flag */
  3597  	$$state := 0
  3598  	$$rcvr.char = -1
  3599  	$$token := -1 // $$rcvr.char translated into internal numbering
  3600  	defer func() {
  3601  		// Make sure we report no lookahead when not parsing.
  3602  		$$state = -1
  3603  		$$rcvr.char = -1
  3604  		$$token = -1
  3605  	}()
  3606  	$$p := -1
  3607  	goto $$stack
  3608  
  3609  ret0:
  3610  	return 0
  3611  
  3612  ret1:
  3613  	return 1
  3614  
  3615  $$stack:
  3616  	/* put a state and value onto the stack */
  3617  	if $$Debug >= 4 {
  3618  		__yyfmt__.Printf("char %v in %v\n", $$Tokname($$token), $$Statname($$state))
  3619  	}
  3620  
  3621  	$$p++
  3622  	if $$p >= len($$S) {
  3623  		nyys := make([]$$SymType, len($$S)*2)
  3624  		copy(nyys, $$S)
  3625  		$$S = nyys
  3626  	}
  3627  	$$S[$$p] = $$VAL
  3628  	$$S[$$p].yys = $$state
  3629  
  3630  $$newstate:
  3631  	$$n = $$Pact[$$state]
  3632  	if $$n <= $$Flag {
  3633  		goto $$default /* simple state */
  3634  	}
  3635  	if $$rcvr.char < 0 {
  3636  		$$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)
  3637  	}
  3638  	$$n += $$token
  3639  	if $$n < 0 || $$n >= $$Last {
  3640  		goto $$default
  3641  	}
  3642  	$$n = $$Act[$$n]
  3643  	if $$Chk[$$n] == $$token { /* valid shift */
  3644  		$$rcvr.char = -1
  3645  		$$token = -1
  3646  		$$VAL = $$rcvr.lval
  3647  		$$state = $$n
  3648  		if Errflag > 0 {
  3649  			Errflag--
  3650  		}
  3651  		goto $$stack
  3652  	}
  3653  
  3654  $$default:
  3655  	/* default state action */
  3656  	$$n = $$Def[$$state]
  3657  	if $$n == -2 {
  3658  		if $$rcvr.char < 0 {
  3659  			$$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)
  3660  		}
  3661  
  3662  		/* look through exception table */
  3663  		xi := 0
  3664  		for {
  3665  			if $$Exca[xi+0] == -1 && $$Exca[xi+1] == $$state {
  3666  				break
  3667  			}
  3668  			xi += 2
  3669  		}
  3670  		for xi += 2; ; xi += 2 {
  3671  			$$n = $$Exca[xi+0]
  3672  			if $$n < 0 || $$n == $$token {
  3673  				break
  3674  			}
  3675  		}
  3676  		$$n = $$Exca[xi+1]
  3677  		if $$n < 0 {
  3678  			goto ret0
  3679  		}
  3680  	}
  3681  	if $$n == 0 {
  3682  		/* error ... attempt to resume parsing */
  3683  		switch Errflag {
  3684  		case 0: /* brand new error */
  3685  			$$lex.Error($$ErrorMessage($$state, $$token))
  3686  			Nerrs++
  3687  			if $$Debug >= 1 {
  3688  				__yyfmt__.Printf("%s", $$Statname($$state))
  3689  				__yyfmt__.Printf(" saw %s\n", $$Tokname($$token))
  3690  			}
  3691  			fallthrough
  3692  
  3693  		case 1, 2: /* incompletely recovered error ... try again */
  3694  			Errflag = 3
  3695  
  3696  			/* find a state where "error" is a legal shift action */
  3697  			for $$p >= 0 {
  3698  				$$n = $$Pact[$$S[$$p].yys] + $$ErrCode
  3699  				if $$n >= 0 && $$n < $$Last {
  3700  					$$state = $$Act[$$n] /* simulate a shift of "error" */
  3701  					if $$Chk[$$state] == $$ErrCode {
  3702  						goto $$stack
  3703  					}
  3704  				}
  3705  
  3706  				/* the current p has no shift on "error", pop stack */
  3707  				if $$Debug >= 2 {
  3708  					__yyfmt__.Printf("error recovery pops state %d\n", $$S[$$p].yys)
  3709  				}
  3710  				$$p--
  3711  			}
  3712  			/* there is no state on the stack with an error shift ... abort */
  3713  			goto ret1
  3714  
  3715  		case 3: /* no shift yet; clobber input char */
  3716  			if $$Debug >= 2 {
  3717  				__yyfmt__.Printf("error recovery discards %s\n", $$Tokname($$token))
  3718  			}
  3719  			if $$token == $$EofCode {
  3720  				goto ret1
  3721  			}
  3722  			$$rcvr.char = -1
  3723  			$$token = -1
  3724  			goto $$newstate /* try again in the same state */
  3725  		}
  3726  	}
  3727  
  3728  	/* reduction by production $$n */
  3729  	if $$Debug >= 2 {
  3730  		__yyfmt__.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
  3731  	}
  3732  
  3733  	$$nt := $$n
  3734  	$$pt := $$p
  3735  	_ = $$pt // guard against "declared and not used"
  3736  
  3737  	$$p -= $$R2[$$n]
  3738  	// $$p is now the index of $0. Perform the default action. Iff the
  3739  	// reduced production is ε, $1 is possibly out of range.
  3740  	if $$p+1 >= len($$S) {
  3741  		nyys := make([]$$SymType, len($$S)*2)
  3742  		copy(nyys, $$S)
  3743  		$$S = nyys
  3744  	}
  3745  	$$VAL = $$S[$$p+1]
  3746  
  3747  	/* consult goto table to find next state */
  3748  	$$n = $$R1[$$n]
  3749  	$$g := $$Pgo[$$n]
  3750  	$$j := $$g + $$S[$$p].yys + 1
  3751  
  3752  	if $$j >= $$Last {
  3753  		$$state = $$Act[$$g]
  3754  	} else {
  3755  		$$state = $$Act[$$j]
  3756  		if $$Chk[$$state] != -$$n {
  3757  			$$state = $$Act[$$g]
  3758  		}
  3759  	}
  3760  	// dummy call; replaced with literal code
  3761  	$$run()
  3762  	goto $$stack /* stack new state and value */
  3763  }
  3764  `