github.com/letsencrypt/go@v0.0.0-20160714163537-4054769a31f6/src/cmd/yacc/yacc.go (about)

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