github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/yacc/yacc.go (about)

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