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