github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/cmd/goyacc/yacc.go (about)

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