github.com/jgarto/itcv@v0.0.0-20180826224514-4eea09c1aa0d/_vendor/src/golang.org/x/tools/cmd/goyacc/yacc.go (about)

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