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