github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/yacc/yacc.go (about)

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