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