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