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