github.com/vedadiyan/sqlparser@v1.0.0/pkg/sqlparser/goyacc/goyacc.go (about)

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