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