github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/cmd/yacc/yacc.go (about)

     1  /*
     2  Derived from Inferno's utils/iyacc/yacc.c
     3  http://code.google.com/p/inferno-os/source/browse/utils/iyacc/yacc.c
     4  
     5  This copyright NOTICE applies to all files in this directory and
     6  subdirectories, unless another copyright notice appears in a given
     7  file or subdirectory.  If you take substantial code from this software to use in
     8  other programs, you must somehow include with it an appropriate
     9  copyright notice that includes the copyright notice and the other
    10  notices below.  It is fine (and often tidier) to do that in a separate
    11  file such as NOTICE, LICENCE or COPYING.
    12  
    13  	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
    14  	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
    15  	Portions Copyright © 1997-1999 Vita Nuova Limited
    16  	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
    17  	Portions Copyright © 2004,2006 Bruce Ellis
    18  	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    19  	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    20  	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    21  
    22  Permission is hereby granted, free of charge, to any person obtaining a copy
    23  of this software and associated documentation files (the "Software"), to deal
    24  in the Software without restriction, including without limitation the rights
    25  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    26  copies of the Software, and to permit persons to whom the Software is
    27  furnished to do so, subject to the following conditions:
    28  
    29  The above copyright notice and this permission notice shall be included in
    30  all copies or substantial portions of the Software.
    31  
    32  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    33  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    34  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    35  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    36  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    37  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    38  THE SOFTWARE.
    39  */
    40  
    41  package main
    42  
    43  // yacc
    44  // major difference is lack of stem ("y" variable)
    45  //
    46  
    47  import (
    48  	"bufio"
    49  	"bytes"
    50  	"flag"
    51  	"fmt"
    52  	"go/format"
    53  	"io/ioutil"
    54  	"os"
    55  	"strconv"
    56  	"strings"
    57  	"unicode"
    58  )
    59  
    60  // the following are adjustable
    61  // according to memory size
    62  const (
    63  	ACTSIZE  = 30000
    64  	NSTATES  = 2000
    65  	TEMPSIZE = 2000
    66  
    67  	SYMINC   = 50  // increase for non-term or term
    68  	RULEINC  = 50  // increase for max rule length prodptr[i]
    69  	PRODINC  = 100 // increase for productions     prodptr
    70  	WSETINC  = 50  // increase for working sets    wsets
    71  	STATEINC = 200 // increase for states          statemem
    72  
    73  	NAMESIZE = 50
    74  	NTYPES   = 63
    75  	ISIZE    = 400
    76  
    77  	PRIVATE = 0xE000 // unicode private use
    78  
    79  	// relationships which must hold:
    80  	//	TEMPSIZE >= NTERMS + NNONTERM + 1;
    81  	//	TEMPSIZE >= NSTATES;
    82  	//
    83  
    84  	NTBASE     = 010000
    85  	ERRCODE    = 8190
    86  	ACCEPTCODE = 8191
    87  	YYLEXUNK   = 3
    88  	TOKSTART   = 4 //index of first defined token
    89  )
    90  
    91  // no, left, right, binary assoc.
    92  const (
    93  	NOASC = iota
    94  	LASC
    95  	RASC
    96  	BASC
    97  )
    98  
    99  // flags for state generation
   100  const (
   101  	DONE = iota
   102  	MUSTDO
   103  	MUSTLOOKAHEAD
   104  )
   105  
   106  // flags for a rule having an action, and being reduced
   107  const (
   108  	ACTFLAG = 1 << (iota + 2)
   109  	REDFLAG
   110  )
   111  
   112  // output parser flags
   113  const yyFlag = -1000
   114  
   115  // parse tokens
   116  const (
   117  	IDENTIFIER = PRIVATE + iota
   118  	MARK
   119  	TERM
   120  	LEFT
   121  	RIGHT
   122  	BINARY
   123  	PREC
   124  	LCURLY
   125  	IDENTCOLON
   126  	NUMBER
   127  	START
   128  	TYPEDEF
   129  	TYPENAME
   130  	UNION
   131  	ERROR
   132  )
   133  
   134  const ENDFILE = 0
   135  const EMPTY = 1
   136  const WHOKNOWS = 0
   137  const OK = 1
   138  const NOMORE = -1000
   139  
   140  // macros for getting associativity and precedence levels
   141  func ASSOC(i int) int { return i & 3 }
   142  
   143  func PLEVEL(i int) int { return (i >> 4) & 077 }
   144  
   145  func TYPE(i int) int { return (i >> 10) & 077 }
   146  
   147  // macros for setting associativity and precedence levels
   148  func SETASC(i, j int) int { return i | j }
   149  
   150  func SETPLEV(i, j int) int { return i | (j << 4) }
   151  
   152  func SETTYPE(i, j int) int { return i | (j << 10) }
   153  
   154  // I/O descriptors
   155  var finput *bufio.Reader // input file
   156  var stderr *bufio.Writer
   157  var ftable *bufio.Writer    // y.go file
   158  var fcode = &bytes.Buffer{} // saved code
   159  var foutput *bufio.Writer   // y.output file
   160  
   161  var fmtImported bool // output file has recorded an import of "fmt"
   162  
   163  var oflag string  // -o [y.go]		- y.go file
   164  var vflag string  // -v [y.output]	- y.output file
   165  var lflag bool    // -l			- disable line directives
   166  var prefix string // name prefix for identifiers, default yy
   167  
   168  func init() {
   169  	flag.StringVar(&oflag, "o", "y.go", "parser output")
   170  	flag.StringVar(&prefix, "p", "yy", "name prefix to use in generated code")
   171  	flag.StringVar(&vflag, "v", "y.output", "create parsing tables")
   172  	flag.BoolVar(&lflag, "l", false, "disable line directives")
   173  }
   174  
   175  var initialstacksize = 16
   176  
   177  // communication variables between various I/O routines
   178  var infile string  // input file name
   179  var numbval int    // value of an input number
   180  var tokname string // input token name, slop for runes and 0
   181  var tokflag = false
   182  
   183  // structure declarations
   184  type Lkset []int
   185  
   186  type Pitem struct {
   187  	prod   []int
   188  	off    int // offset within the production
   189  	first  int // first term or non-term in item
   190  	prodno int // production number for sorting
   191  }
   192  
   193  type Item struct {
   194  	pitem Pitem
   195  	look  Lkset
   196  }
   197  
   198  type Symb struct {
   199  	name    string
   200  	noconst bool
   201  	value   int
   202  }
   203  
   204  type Wset struct {
   205  	pitem Pitem
   206  	flag  int
   207  	ws    Lkset
   208  }
   209  
   210  // storage of types
   211  var ntypes int             // number of types defined
   212  var typeset [NTYPES]string // pointers to type tags
   213  
   214  // token information
   215  
   216  var ntokens = 0 // number of tokens
   217  var tokset []Symb
   218  var toklev []int // vector with the precedence of the terminals
   219  
   220  // nonterminal information
   221  
   222  var nnonter = -1 // the number of nonterminals
   223  var nontrst []Symb
   224  var start int // start symbol
   225  
   226  // state information
   227  
   228  var nstate = 0                      // number of states
   229  var pstate = make([]int, NSTATES+2) // index into statemem to the descriptions of the states
   230  var statemem []Item
   231  var tystate = make([]int, NSTATES) // contains type information about the states
   232  var tstates []int                  // states generated by terminal gotos
   233  var ntstates []int                 // states generated by nonterminal gotos
   234  var mstates = make([]int, NSTATES) // chain of overflows of term/nonterm generation lists
   235  var lastred int                    // number of last reduction of a state
   236  var defact = make([]int, NSTATES)  // default actions of states
   237  
   238  // lookahead set information
   239  
   240  var nolook = 0  // flag to turn off lookahead computations
   241  var tbitset = 0 // size of lookahead sets
   242  var clset Lkset // temporary storage for lookahead computations
   243  
   244  // working set information
   245  
   246  var wsets []Wset
   247  var cwp int
   248  
   249  // storage for action table
   250  
   251  var amem []int                   // action table storage
   252  var memp int                     // next free action table position
   253  var indgo = make([]int, NSTATES) // index to the stored goto table
   254  
   255  // temporary vector, indexable by states, terms, or ntokens
   256  
   257  var temp1 = make([]int, TEMPSIZE) // temporary storage, indexed by terms + ntokens or states
   258  var lineno = 1                    // current input line number
   259  var fatfl = 1                     // if on, error is fatal
   260  var nerrors = 0                   // number of errors
   261  
   262  // assigned token type values
   263  
   264  var extval = 0
   265  
   266  // grammar rule information
   267  
   268  var nprod = 1      // number of productions
   269  var prdptr [][]int // pointers to descriptions of productions
   270  var levprd []int   // precedence levels for the productions
   271  var rlines []int   // line number for this rule
   272  
   273  // statistics collection variables
   274  
   275  var zzgoent = 0
   276  var zzgobest = 0
   277  var zzacent = 0
   278  var zzexcp = 0
   279  var zzclose = 0
   280  var zzrrconf = 0
   281  var zzsrconf = 0
   282  var zzstate = 0
   283  
   284  // optimizer arrays
   285  
   286  var yypgo [][]int
   287  var optst [][]int
   288  var ggreed []int
   289  var pgo []int
   290  
   291  var maxspr int // maximum spread of any entry
   292  var maxoff int // maximum offset into a array
   293  var maxa int
   294  
   295  // storage for information about the nonterminals
   296  
   297  var pres [][][]int // vector of pointers to productions yielding each nonterminal
   298  var pfirst []Lkset
   299  var pempty []int // vector of nonterminals nontrivially deriving e
   300  
   301  // random stuff picked out from between functions
   302  
   303  var indebug = 0 // debugging flag for cpfir
   304  var pidebug = 0 // debugging flag for putitem
   305  var gsdebug = 0 // debugging flag for stagen
   306  var cldebug = 0 // debugging flag for closure
   307  var pkdebug = 0 // debugging flag for apack
   308  var g2debug = 0 // debugging for go2gen
   309  var adb = 0     // debugging for callopt
   310  
   311  type Resrv struct {
   312  	name  string
   313  	value int
   314  }
   315  
   316  var resrv = []Resrv{
   317  	{"binary", BINARY},
   318  	{"left", LEFT},
   319  	{"nonassoc", BINARY},
   320  	{"prec", PREC},
   321  	{"right", RIGHT},
   322  	{"start", START},
   323  	{"term", TERM},
   324  	{"token", TERM},
   325  	{"type", TYPEDEF},
   326  	{"union", UNION},
   327  	{"struct", UNION},
   328  	{"error", ERROR},
   329  }
   330  
   331  type Error struct {
   332  	lineno int
   333  	tokens []string
   334  	msg    string
   335  }
   336  
   337  var errors []Error
   338  
   339  type Row struct {
   340  	actions       []int
   341  	defaultAction int
   342  }
   343  
   344  var stateTable []Row
   345  
   346  var zznewstate = 0
   347  
   348  const EOF = -1
   349  
   350  func main() {
   351  
   352  	setup() // initialize and read productions
   353  
   354  	tbitset = (ntokens + 32) / 32
   355  	cpres()  // make table of which productions yield a given nonterminal
   356  	cempty() // make a table of which nonterminals can match the empty string
   357  	cpfir()  // make a table of firsts of nonterminals
   358  
   359  	stagen() // generate the states
   360  
   361  	yypgo = make([][]int, nnonter+1)
   362  	optst = make([][]int, nstate)
   363  	output() // write the states and the tables
   364  	go2out()
   365  
   366  	hideprod()
   367  	summary()
   368  
   369  	callopt()
   370  
   371  	others()
   372  
   373  	exit(0)
   374  }
   375  
   376  func setup() {
   377  	var j, ty int
   378  
   379  	stderr = bufio.NewWriter(os.Stderr)
   380  	foutput = nil
   381  
   382  	flag.Parse()
   383  	if flag.NArg() != 1 {
   384  		usage()
   385  	}
   386  	if initialstacksize < 1 {
   387  		// never set so cannot happen
   388  		fmt.Fprintf(stderr, "yacc: stack size too small\n")
   389  		usage()
   390  	}
   391  	yaccpar = strings.Replace(yaccpartext, "$$", prefix, -1)
   392  	openup()
   393  
   394  	defin(0, "$end")
   395  	extval = PRIVATE // tokens start in unicode 'private use'
   396  	defin(0, "error")
   397  	defin(1, "$accept")
   398  	defin(0, "$unk")
   399  	i := 0
   400  
   401  	t := gettok()
   402  
   403  outer:
   404  	for {
   405  		switch t {
   406  		default:
   407  			errorf("syntax error tok=%v", t-PRIVATE)
   408  
   409  		case MARK, ENDFILE:
   410  			break outer
   411  
   412  		case ';':
   413  
   414  		case START:
   415  			t = gettok()
   416  			if t != IDENTIFIER {
   417  				errorf("bad %%start construction")
   418  			}
   419  			start = chfind(1, tokname)
   420  
   421  		case ERROR:
   422  			lno := lineno
   423  			var tokens []string
   424  			for {
   425  				t := gettok()
   426  				if t == ':' {
   427  					break
   428  				}
   429  				if t != IDENTIFIER && t != IDENTCOLON {
   430  					errorf("bad syntax in %%error")
   431  				}
   432  				tokens = append(tokens, tokname)
   433  				if t == IDENTCOLON {
   434  					break
   435  				}
   436  			}
   437  			if gettok() != IDENTIFIER {
   438  				errorf("bad syntax in %%error")
   439  			}
   440  			errors = append(errors, Error{lno, tokens, tokname})
   441  
   442  		case TYPEDEF:
   443  			t = gettok()
   444  			if t != TYPENAME {
   445  				errorf("bad syntax in %%type")
   446  			}
   447  			ty = numbval
   448  			for {
   449  				t = gettok()
   450  				switch t {
   451  				case IDENTIFIER:
   452  					t = chfind(1, tokname)
   453  					if t < NTBASE {
   454  						j = TYPE(toklev[t])
   455  						if j != 0 && j != ty {
   456  							errorf("type redeclaration of token %s",
   457  								tokset[t].name)
   458  						} else {
   459  							toklev[t] = SETTYPE(toklev[t], ty)
   460  						}
   461  					} else {
   462  						j = nontrst[t-NTBASE].value
   463  						if j != 0 && j != ty {
   464  							errorf("type redeclaration of nonterminal %v",
   465  								nontrst[t-NTBASE].name)
   466  						} else {
   467  							nontrst[t-NTBASE].value = ty
   468  						}
   469  					}
   470  					continue
   471  
   472  				case ',':
   473  					continue
   474  				}
   475  				break
   476  			}
   477  			continue
   478  
   479  		case UNION:
   480  			cpyunion()
   481  
   482  		case LEFT, BINARY, RIGHT, TERM:
   483  			// nonzero means new prec. and assoc.
   484  			lev := t - TERM
   485  			if lev != 0 {
   486  				i++
   487  			}
   488  			ty = 0
   489  
   490  			// get identifiers so defined
   491  			t = gettok()
   492  
   493  			// there is a type defined
   494  			if t == TYPENAME {
   495  				ty = numbval
   496  				t = gettok()
   497  			}
   498  			for {
   499  				switch t {
   500  				case ',':
   501  					t = gettok()
   502  					continue
   503  
   504  				case ';':
   505  					break
   506  
   507  				case IDENTIFIER:
   508  					j = chfind(0, tokname)
   509  					if j >= NTBASE {
   510  						errorf("%v defined earlier as nonterminal", tokname)
   511  					}
   512  					if lev != 0 {
   513  						if ASSOC(toklev[j]) != 0 {
   514  							errorf("redeclaration of precedence of %v", tokname)
   515  						}
   516  						toklev[j] = SETASC(toklev[j], lev)
   517  						toklev[j] = SETPLEV(toklev[j], i)
   518  					}
   519  					if ty != 0 {
   520  						if TYPE(toklev[j]) != 0 {
   521  							errorf("redeclaration of type of %v", tokname)
   522  						}
   523  						toklev[j] = SETTYPE(toklev[j], ty)
   524  					}
   525  					t = gettok()
   526  					if t == NUMBER {
   527  						tokset[j].value = numbval
   528  						t = gettok()
   529  					}
   530  
   531  					continue
   532  				}
   533  				break
   534  			}
   535  			continue
   536  
   537  		case LCURLY:
   538  			cpycode()
   539  		}
   540  		t = gettok()
   541  	}
   542  
   543  	if t == ENDFILE {
   544  		errorf("unexpected EOF before %%")
   545  	}
   546  
   547  	fmt.Fprintf(fcode, "switch %snt {\n", prefix)
   548  
   549  	moreprod()
   550  	prdptr[0] = []int{NTBASE, start, 1, 0}
   551  
   552  	nprod = 1
   553  	curprod := make([]int, RULEINC)
   554  	t = gettok()
   555  	if t != IDENTCOLON {
   556  		errorf("bad syntax on first rule")
   557  	}
   558  
   559  	if start == 0 {
   560  		prdptr[0][1] = chfind(1, tokname)
   561  	}
   562  
   563  	// read rules
   564  	// put into prdptr array in the format
   565  	// target
   566  	// followed by id's of terminals and non-terminals
   567  	// followed by -nprod
   568  
   569  	for t != MARK && t != ENDFILE {
   570  		mem := 0
   571  
   572  		// process a rule
   573  		rlines[nprod] = lineno
   574  		ruleline := lineno
   575  		if t == '|' {
   576  			curprod[mem] = prdptr[nprod-1][0]
   577  			mem++
   578  		} else if t == IDENTCOLON {
   579  			curprod[mem] = chfind(1, tokname)
   580  			if curprod[mem] < NTBASE {
   581  				lerrorf(ruleline, "token illegal on LHS of grammar rule")
   582  			}
   583  			mem++
   584  		} else {
   585  			lerrorf(ruleline, "illegal rule: missing semicolon or | ?")
   586  		}
   587  
   588  		// read rule body
   589  		t = gettok()
   590  		for {
   591  			for t == IDENTIFIER {
   592  				curprod[mem] = chfind(1, tokname)
   593  				if curprod[mem] < NTBASE {
   594  					levprd[nprod] = toklev[curprod[mem]]
   595  				}
   596  				mem++
   597  				if mem >= len(curprod) {
   598  					ncurprod := make([]int, mem+RULEINC)
   599  					copy(ncurprod, curprod)
   600  					curprod = ncurprod
   601  				}
   602  				t = gettok()
   603  			}
   604  			if t == PREC {
   605  				if gettok() != IDENTIFIER {
   606  					lerrorf(ruleline, "illegal %%prec syntax")
   607  				}
   608  				j = chfind(2, tokname)
   609  				if j >= NTBASE {
   610  					lerrorf(ruleline, "nonterminal "+nontrst[j-NTBASE].name+" illegal after %%prec")
   611  				}
   612  				levprd[nprod] = toklev[j]
   613  				t = gettok()
   614  			}
   615  			if t != '=' {
   616  				break
   617  			}
   618  			levprd[nprod] |= ACTFLAG
   619  			fmt.Fprintf(fcode, "\n\tcase %v:", nprod)
   620  			fmt.Fprintf(fcode, "\n\t\t%sDollar = %sS[%spt-%v:%spt+1]", prefix, prefix, prefix, mem-1, prefix)
   621  			cpyact(curprod, mem)
   622  
   623  			// action within rule...
   624  			t = gettok()
   625  			if t == IDENTIFIER {
   626  				// make it a nonterminal
   627  				j = chfind(1, fmt.Sprintf("$$%v", nprod))
   628  
   629  				//
   630  				// the current rule will become rule number nprod+1
   631  				// enter null production for action
   632  				//
   633  				prdptr[nprod] = make([]int, 2)
   634  				prdptr[nprod][0] = j
   635  				prdptr[nprod][1] = -nprod
   636  
   637  				// update the production information
   638  				nprod++
   639  				moreprod()
   640  				levprd[nprod] = levprd[nprod-1] & ^ACTFLAG
   641  				levprd[nprod-1] = ACTFLAG
   642  				rlines[nprod] = lineno
   643  
   644  				// make the action appear in the original rule
   645  				curprod[mem] = j
   646  				mem++
   647  				if mem >= len(curprod) {
   648  					ncurprod := make([]int, mem+RULEINC)
   649  					copy(ncurprod, curprod)
   650  					curprod = ncurprod
   651  				}
   652  			}
   653  		}
   654  
   655  		for t == ';' {
   656  			t = gettok()
   657  		}
   658  		curprod[mem] = -nprod
   659  		mem++
   660  
   661  		// check that default action is reasonable
   662  		if ntypes != 0 && (levprd[nprod]&ACTFLAG) == 0 &&
   663  			nontrst[curprod[0]-NTBASE].value != 0 {
   664  			// no explicit action, LHS has value
   665  			tempty := curprod[1]
   666  			if tempty < 0 {
   667  				lerrorf(ruleline, "must return a value, since LHS has a type")
   668  			}
   669  			if tempty >= NTBASE {
   670  				tempty = nontrst[tempty-NTBASE].value
   671  			} else {
   672  				tempty = TYPE(toklev[tempty])
   673  			}
   674  			if tempty != nontrst[curprod[0]-NTBASE].value {
   675  				lerrorf(ruleline, "default action causes potential type clash")
   676  			}
   677  		}
   678  		moreprod()
   679  		prdptr[nprod] = make([]int, mem)
   680  		copy(prdptr[nprod], curprod)
   681  		nprod++
   682  		moreprod()
   683  		levprd[nprod] = 0
   684  	}
   685  
   686  	//
   687  	// end of all rules
   688  	// dump out the prefix code
   689  	//
   690  
   691  	fmt.Fprintf(fcode, "\n\t}")
   692  
   693  	// put out non-literal terminals
   694  	for i := TOKSTART; i <= ntokens; i++ {
   695  		// non-literals
   696  		if !tokset[i].noconst {
   697  			fmt.Fprintf(ftable, "const %v = %v\n", tokset[i].name, tokset[i].value)
   698  		}
   699  	}
   700  
   701  	// put out names of tokens
   702  	ftable.WriteRune('\n')
   703  	fmt.Fprintf(ftable, "var %sToknames = [...]string{\n", prefix)
   704  	for i := 1; i <= ntokens; i++ {
   705  		fmt.Fprintf(ftable, "\t%q,\n", tokset[i].name)
   706  	}
   707  	fmt.Fprintf(ftable, "}\n")
   708  
   709  	// put out names of states.
   710  	// commented out to avoid a huge table just for debugging.
   711  	// re-enable to have the names in the binary.
   712  	fmt.Fprintf(ftable, "var %sStatenames = [...]string{", prefix)
   713  	//	for i:=TOKSTART; i<=ntokens; i++ {
   714  	//		fmt.Fprintf(ftable, "\t%q,\n", tokset[i].name);
   715  	//	}
   716  	fmt.Fprintf(ftable, "}\n")
   717  
   718  	ftable.WriteRune('\n')
   719  	fmt.Fprintf(ftable, "const %sEofCode = 1\n", prefix)
   720  	fmt.Fprintf(ftable, "const %sErrCode = 2\n", prefix)
   721  	fmt.Fprintf(ftable, "const %sInitialStackSize = %v\n", prefix, initialstacksize)
   722  
   723  	//
   724  	// copy any postfix code
   725  	//
   726  	if t == MARK {
   727  		if !lflag {
   728  			fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
   729  		}
   730  		for {
   731  			c := getrune(finput)
   732  			if c == EOF {
   733  				break
   734  			}
   735  			ftable.WriteRune(c)
   736  		}
   737  	}
   738  }
   739  
   740  //
   741  // allocate enough room to hold another production
   742  //
   743  func moreprod() {
   744  	n := len(prdptr)
   745  	if nprod >= n {
   746  		nn := n + PRODINC
   747  		aprod := make([][]int, nn)
   748  		alevprd := make([]int, nn)
   749  		arlines := make([]int, nn)
   750  
   751  		copy(aprod, prdptr)
   752  		copy(alevprd, levprd)
   753  		copy(arlines, rlines)
   754  
   755  		prdptr = aprod
   756  		levprd = alevprd
   757  		rlines = arlines
   758  	}
   759  }
   760  
   761  //
   762  // define s to be a terminal if nt==0
   763  // or a nonterminal if nt==1
   764  //
   765  func defin(nt int, s string) int {
   766  	val := 0
   767  	if nt != 0 {
   768  		nnonter++
   769  		if nnonter >= len(nontrst) {
   770  			anontrst := make([]Symb, nnonter+SYMINC)
   771  			copy(anontrst, nontrst)
   772  			nontrst = anontrst
   773  		}
   774  		nontrst[nnonter] = Symb{name: s}
   775  		return NTBASE + nnonter
   776  	}
   777  
   778  	// must be a token
   779  	ntokens++
   780  	if ntokens >= len(tokset) {
   781  		nn := ntokens + SYMINC
   782  		atokset := make([]Symb, nn)
   783  		atoklev := make([]int, nn)
   784  
   785  		copy(atoklev, toklev)
   786  		copy(atokset, tokset)
   787  
   788  		tokset = atokset
   789  		toklev = atoklev
   790  	}
   791  	tokset[ntokens].name = s
   792  	toklev[ntokens] = 0
   793  
   794  	// establish value for token
   795  	// single character literal
   796  	if s[0] == '\'' || s[0] == '"' {
   797  		q, err := strconv.Unquote(s)
   798  		if err != nil {
   799  			errorf("invalid token: %s", err)
   800  		}
   801  		rq := []rune(q)
   802  		if len(rq) != 1 {
   803  			errorf("character token too long: %s", s)
   804  		}
   805  		val = int(rq[0])
   806  		if val == 0 {
   807  			errorf("token value 0 is illegal")
   808  		}
   809  		tokset[ntokens].noconst = true
   810  	} else {
   811  		val = extval
   812  		extval++
   813  		if s[0] == '$' {
   814  			tokset[ntokens].noconst = true
   815  		}
   816  	}
   817  
   818  	tokset[ntokens].value = val
   819  	return ntokens
   820  }
   821  
   822  var peekline = 0
   823  
   824  func gettok() int {
   825  	var i int
   826  	var match, c rune
   827  
   828  	tokname = ""
   829  	for {
   830  		lineno += peekline
   831  		peekline = 0
   832  		c = getrune(finput)
   833  		for c == ' ' || c == '\n' || c == '\t' || c == '\v' || c == '\r' {
   834  			if c == '\n' {
   835  				lineno++
   836  			}
   837  			c = getrune(finput)
   838  		}
   839  
   840  		// skip comment -- fix
   841  		if c != '/' {
   842  			break
   843  		}
   844  		lineno += skipcom()
   845  	}
   846  
   847  	switch c {
   848  	case EOF:
   849  		if tokflag {
   850  			fmt.Printf(">>> ENDFILE %v\n", lineno)
   851  		}
   852  		return ENDFILE
   853  
   854  	case '{':
   855  		ungetrune(finput, c)
   856  		if tokflag {
   857  			fmt.Printf(">>> ={ %v\n", lineno)
   858  		}
   859  		return '='
   860  
   861  	case '<':
   862  		// get, and look up, a type name (union member name)
   863  		c = getrune(finput)
   864  		for c != '>' && c != EOF && c != '\n' {
   865  			tokname += string(c)
   866  			c = getrune(finput)
   867  		}
   868  
   869  		if c != '>' {
   870  			errorf("unterminated < ... > clause")
   871  		}
   872  
   873  		for i = 1; i <= ntypes; i++ {
   874  			if typeset[i] == tokname {
   875  				numbval = i
   876  				if tokflag {
   877  					fmt.Printf(">>> TYPENAME old <%v> %v\n", tokname, lineno)
   878  				}
   879  				return TYPENAME
   880  			}
   881  		}
   882  		ntypes++
   883  		numbval = ntypes
   884  		typeset[numbval] = tokname
   885  		if tokflag {
   886  			fmt.Printf(">>> TYPENAME new <%v> %v\n", tokname, lineno)
   887  		}
   888  		return TYPENAME
   889  
   890  	case '"', '\'':
   891  		match = c
   892  		tokname = string(c)
   893  		for {
   894  			c = getrune(finput)
   895  			if c == '\n' || c == EOF {
   896  				errorf("illegal or missing ' or \"")
   897  			}
   898  			if c == '\\' {
   899  				tokname += string('\\')
   900  				c = getrune(finput)
   901  			} else if c == match {
   902  				if tokflag {
   903  					fmt.Printf(">>> IDENTIFIER \"%v\" %v\n", tokname, lineno)
   904  				}
   905  				tokname += string(c)
   906  				return IDENTIFIER
   907  			}
   908  			tokname += string(c)
   909  		}
   910  
   911  	case '%':
   912  		c = getrune(finput)
   913  		switch c {
   914  		case '%':
   915  			if tokflag {
   916  				fmt.Printf(">>> MARK %%%% %v\n", lineno)
   917  			}
   918  			return MARK
   919  		case '=':
   920  			if tokflag {
   921  				fmt.Printf(">>> PREC %%= %v\n", lineno)
   922  			}
   923  			return PREC
   924  		case '{':
   925  			if tokflag {
   926  				fmt.Printf(">>> LCURLY %%{ %v\n", lineno)
   927  			}
   928  			return LCURLY
   929  		}
   930  
   931  		getword(c)
   932  		// find a reserved word
   933  		for i := range resrv {
   934  			if tokname == resrv[i].name {
   935  				if tokflag {
   936  					fmt.Printf(">>> %%%v %v %v\n", tokname,
   937  						resrv[i].value-PRIVATE, lineno)
   938  				}
   939  				return resrv[i].value
   940  			}
   941  		}
   942  		errorf("invalid escape, or illegal reserved word: %v", tokname)
   943  
   944  	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   945  		numbval = int(c - '0')
   946  		for {
   947  			c = getrune(finput)
   948  			if !isdigit(c) {
   949  				break
   950  			}
   951  			numbval = numbval*10 + int(c-'0')
   952  		}
   953  		ungetrune(finput, c)
   954  		if tokflag {
   955  			fmt.Printf(">>> NUMBER %v %v\n", numbval, lineno)
   956  		}
   957  		return NUMBER
   958  
   959  	default:
   960  		if isword(c) || c == '.' || c == '$' {
   961  			getword(c)
   962  			break
   963  		}
   964  		if tokflag {
   965  			fmt.Printf(">>> OPERATOR %v %v\n", string(c), lineno)
   966  		}
   967  		return int(c)
   968  	}
   969  
   970  	// look ahead to distinguish IDENTIFIER from IDENTCOLON
   971  	c = getrune(finput)
   972  	for c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\r' || c == '/' {
   973  		if c == '\n' {
   974  			peekline++
   975  		}
   976  		// look for comments
   977  		if c == '/' {
   978  			peekline += skipcom()
   979  		}
   980  		c = getrune(finput)
   981  	}
   982  	if c == ':' {
   983  		if tokflag {
   984  			fmt.Printf(">>> IDENTCOLON %v: %v\n", tokname, lineno)
   985  		}
   986  		return IDENTCOLON
   987  	}
   988  
   989  	ungetrune(finput, c)
   990  	if tokflag {
   991  		fmt.Printf(">>> IDENTIFIER %v %v\n", tokname, lineno)
   992  	}
   993  	return IDENTIFIER
   994  }
   995  
   996  func getword(c rune) {
   997  	tokname = ""
   998  	for isword(c) || isdigit(c) || c == '.' || c == '$' {
   999  		tokname += string(c)
  1000  		c = getrune(finput)
  1001  	}
  1002  	ungetrune(finput, c)
  1003  }
  1004  
  1005  //
  1006  // determine the type of a symbol
  1007  //
  1008  func fdtype(t int) int {
  1009  	var v int
  1010  	var s string
  1011  
  1012  	if t >= NTBASE {
  1013  		v = nontrst[t-NTBASE].value
  1014  		s = nontrst[t-NTBASE].name
  1015  	} else {
  1016  		v = TYPE(toklev[t])
  1017  		s = tokset[t].name
  1018  	}
  1019  	if v <= 0 {
  1020  		errorf("must specify type for %v", s)
  1021  	}
  1022  	return v
  1023  }
  1024  
  1025  func chfind(t int, s string) int {
  1026  	if s[0] == '"' || s[0] == '\'' {
  1027  		t = 0
  1028  	}
  1029  	for i := 0; i <= ntokens; i++ {
  1030  		if s == tokset[i].name {
  1031  			return i
  1032  		}
  1033  	}
  1034  	for i := 0; i <= nnonter; i++ {
  1035  		if s == nontrst[i].name {
  1036  			return NTBASE + i
  1037  		}
  1038  	}
  1039  
  1040  	// cannot find name
  1041  	if t > 1 {
  1042  		errorf("%v should have been defined earlier", s)
  1043  	}
  1044  	return defin(t, s)
  1045  }
  1046  
  1047  //
  1048  // copy the union declaration to the output, and the define file if present
  1049  //
  1050  func cpyunion() {
  1051  
  1052  	if !lflag {
  1053  		fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
  1054  	}
  1055  	fmt.Fprintf(ftable, "type %sSymType struct", prefix)
  1056  
  1057  	level := 0
  1058  
  1059  out:
  1060  	for {
  1061  		c := getrune(finput)
  1062  		if c == EOF {
  1063  			errorf("EOF encountered while processing %%union")
  1064  		}
  1065  		ftable.WriteRune(c)
  1066  		switch c {
  1067  		case '\n':
  1068  			lineno++
  1069  		case '{':
  1070  			if level == 0 {
  1071  				fmt.Fprintf(ftable, "\n\tyys int")
  1072  			}
  1073  			level++
  1074  		case '}':
  1075  			level--
  1076  			if level == 0 {
  1077  				break out
  1078  			}
  1079  		}
  1080  	}
  1081  	fmt.Fprintf(ftable, "\n\n")
  1082  }
  1083  
  1084  //
  1085  // saves code between %{ and %}
  1086  // adds an import for __fmt__ the first time
  1087  //
  1088  func cpycode() {
  1089  	lno := lineno
  1090  
  1091  	c := getrune(finput)
  1092  	if c == '\n' {
  1093  		c = getrune(finput)
  1094  		lineno++
  1095  	}
  1096  	if !lflag {
  1097  		fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
  1098  	}
  1099  	// accumulate until %}
  1100  	code := make([]rune, 0, 1024)
  1101  	for c != EOF {
  1102  		if c == '%' {
  1103  			c = getrune(finput)
  1104  			if c == '}' {
  1105  				emitcode(code, lno+1)
  1106  				return
  1107  			}
  1108  			code = append(code, '%')
  1109  		}
  1110  		code = append(code, c)
  1111  		if c == '\n' {
  1112  			lineno++
  1113  		}
  1114  		c = getrune(finput)
  1115  	}
  1116  	lineno = lno
  1117  	errorf("eof before %%}")
  1118  }
  1119  
  1120  //
  1121  // emits code saved up from between %{ and %}
  1122  // called by cpycode
  1123  // adds an import for __yyfmt__ after the package clause
  1124  //
  1125  func emitcode(code []rune, lineno int) {
  1126  	for i, line := range lines(code) {
  1127  		writecode(line)
  1128  		if !fmtImported && isPackageClause(line) {
  1129  			fmt.Fprintln(ftable, `import __yyfmt__ "fmt"`)
  1130  			if !lflag {
  1131  				fmt.Fprintf(ftable, "//line %v:%v\n\t\t", infile, lineno+i)
  1132  			}
  1133  			fmtImported = true
  1134  		}
  1135  	}
  1136  }
  1137  
  1138  //
  1139  // does this line look like a package clause?  not perfect: might be confused by early comments.
  1140  //
  1141  func isPackageClause(line []rune) bool {
  1142  	line = skipspace(line)
  1143  
  1144  	// must be big enough.
  1145  	if len(line) < len("package X\n") {
  1146  		return false
  1147  	}
  1148  
  1149  	// must start with "package"
  1150  	for i, r := range []rune("package") {
  1151  		if line[i] != r {
  1152  			return false
  1153  		}
  1154  	}
  1155  	line = skipspace(line[len("package"):])
  1156  
  1157  	// must have another identifier.
  1158  	if len(line) == 0 || (!unicode.IsLetter(line[0]) && line[0] != '_') {
  1159  		return false
  1160  	}
  1161  	for len(line) > 0 {
  1162  		if !unicode.IsLetter(line[0]) && !unicode.IsDigit(line[0]) && line[0] != '_' {
  1163  			break
  1164  		}
  1165  		line = line[1:]
  1166  	}
  1167  	line = skipspace(line)
  1168  
  1169  	// eol, newline, or comment must follow
  1170  	if len(line) == 0 {
  1171  		return true
  1172  	}
  1173  	if line[0] == '\r' || line[0] == '\n' {
  1174  		return true
  1175  	}
  1176  	if len(line) >= 2 {
  1177  		return line[0] == '/' && (line[1] == '/' || line[1] == '*')
  1178  	}
  1179  	return false
  1180  }
  1181  
  1182  //
  1183  // skip initial spaces
  1184  //
  1185  func skipspace(line []rune) []rune {
  1186  	for len(line) > 0 {
  1187  		if line[0] != ' ' && line[0] != '\t' {
  1188  			break
  1189  		}
  1190  		line = line[1:]
  1191  	}
  1192  	return line
  1193  }
  1194  
  1195  //
  1196  // break code into lines
  1197  //
  1198  func lines(code []rune) [][]rune {
  1199  	l := make([][]rune, 0, 100)
  1200  	for len(code) > 0 {
  1201  		// one line per loop
  1202  		var i int
  1203  		for i = range code {
  1204  			if code[i] == '\n' {
  1205  				break
  1206  			}
  1207  		}
  1208  		l = append(l, code[:i+1])
  1209  		code = code[i+1:]
  1210  	}
  1211  	return l
  1212  }
  1213  
  1214  //
  1215  // writes code to ftable
  1216  //
  1217  func writecode(code []rune) {
  1218  	for _, r := range code {
  1219  		ftable.WriteRune(r)
  1220  	}
  1221  }
  1222  
  1223  //
  1224  // skip over comments
  1225  // skipcom is called after reading a '/'
  1226  //
  1227  func skipcom() int {
  1228  	var c rune
  1229  
  1230  	c = getrune(finput)
  1231  	if c == '/' {
  1232  		for c != EOF {
  1233  			if c == '\n' {
  1234  				return 1
  1235  			}
  1236  			c = getrune(finput)
  1237  		}
  1238  		errorf("EOF inside comment")
  1239  		return 0
  1240  	}
  1241  	if c != '*' {
  1242  		errorf("illegal comment")
  1243  	}
  1244  
  1245  	nl := 0 // lines skipped
  1246  	c = getrune(finput)
  1247  
  1248  l1:
  1249  	switch c {
  1250  	case '*':
  1251  		c = getrune(finput)
  1252  		if c == '/' {
  1253  			break
  1254  		}
  1255  		goto l1
  1256  
  1257  	case '\n':
  1258  		nl++
  1259  		fallthrough
  1260  
  1261  	default:
  1262  		c = getrune(finput)
  1263  		goto l1
  1264  	}
  1265  	return nl
  1266  }
  1267  
  1268  func dumpprod(curprod []int, max int) {
  1269  	fmt.Printf("\n")
  1270  	for i := 0; i < max; i++ {
  1271  		p := curprod[i]
  1272  		if p < 0 {
  1273  			fmt.Printf("[%v] %v\n", i, p)
  1274  		} else {
  1275  			fmt.Printf("[%v] %v\n", i, symnam(p))
  1276  		}
  1277  	}
  1278  }
  1279  
  1280  //
  1281  // copy action to the next ; or closing }
  1282  //
  1283  func cpyact(curprod []int, max int) {
  1284  
  1285  	if !lflag {
  1286  		fmt.Fprintf(fcode, "\n\t\t//line %v:%v", infile, lineno)
  1287  	}
  1288  	fmt.Fprint(fcode, "\n\t\t")
  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  //
  3188  // return 1 if 2 arrays are equal
  3189  // return 0 if not equal
  3190  //
  3191  func aryeq(a []int, b []int) int {
  3192  	n := len(a)
  3193  	if len(b) != n {
  3194  		return 0
  3195  	}
  3196  	for ll := 0; ll < n; ll++ {
  3197  		if a[ll] != b[ll] {
  3198  			return 0
  3199  		}
  3200  	}
  3201  	return 1
  3202  }
  3203  
  3204  func getrune(f *bufio.Reader) rune {
  3205  	var r rune
  3206  
  3207  	if peekrune != 0 {
  3208  		if peekrune == EOF {
  3209  			return EOF
  3210  		}
  3211  		r = peekrune
  3212  		peekrune = 0
  3213  		return r
  3214  	}
  3215  
  3216  	c, n, err := f.ReadRune()
  3217  	if n == 0 {
  3218  		return EOF
  3219  	}
  3220  	if err != nil {
  3221  		errorf("read error: %v", err)
  3222  	}
  3223  	//fmt.Printf("rune = %v n=%v\n", string(c), n);
  3224  	return c
  3225  }
  3226  
  3227  func ungetrune(f *bufio.Reader, c rune) {
  3228  	if f != finput {
  3229  		panic("ungetc - not finput")
  3230  	}
  3231  	if peekrune != 0 {
  3232  		panic("ungetc - 2nd unget")
  3233  	}
  3234  	peekrune = c
  3235  }
  3236  
  3237  func write(f *bufio.Writer, b []byte, n int) int {
  3238  	panic("write")
  3239  }
  3240  
  3241  func open(s string) *bufio.Reader {
  3242  	fi, err := os.Open(s)
  3243  	if err != nil {
  3244  		errorf("error opening %v: %v", s, err)
  3245  	}
  3246  	//fmt.Printf("open %v\n", s);
  3247  	return bufio.NewReader(fi)
  3248  }
  3249  
  3250  func create(s string) *bufio.Writer {
  3251  	fo, err := os.Create(s)
  3252  	if err != nil {
  3253  		errorf("error creating %v: %v", s, err)
  3254  	}
  3255  	//fmt.Printf("create %v mode %v\n", s);
  3256  	return bufio.NewWriter(fo)
  3257  }
  3258  
  3259  //
  3260  // write out error comment
  3261  //
  3262  func lerrorf(lineno int, s string, v ...interface{}) {
  3263  	nerrors++
  3264  	fmt.Fprintf(stderr, s, v...)
  3265  	fmt.Fprintf(stderr, ": %v:%v\n", infile, lineno)
  3266  	if fatfl != 0 {
  3267  		summary()
  3268  		exit(1)
  3269  	}
  3270  }
  3271  
  3272  func errorf(s string, v ...interface{}) {
  3273  	lerrorf(lineno, s, v...)
  3274  }
  3275  
  3276  func exit(status int) {
  3277  	if ftable != nil {
  3278  		ftable.Flush()
  3279  		ftable = nil
  3280  		gofmt()
  3281  	}
  3282  	if foutput != nil {
  3283  		foutput.Flush()
  3284  		foutput = nil
  3285  	}
  3286  	if stderr != nil {
  3287  		stderr.Flush()
  3288  		stderr = nil
  3289  	}
  3290  	os.Exit(status)
  3291  }
  3292  
  3293  func gofmt() {
  3294  	src, err := ioutil.ReadFile(oflag)
  3295  	if err != nil {
  3296  		return
  3297  	}
  3298  	src, err = format.Source(src)
  3299  	if err != nil {
  3300  		return
  3301  	}
  3302  	ioutil.WriteFile(oflag, src, 0666)
  3303  }
  3304  
  3305  var yaccpar string // will be processed version of yaccpartext: s/$$/prefix/g
  3306  var yaccpartext = `
  3307  /*	parser for yacc output	*/
  3308  
  3309  var (
  3310  	$$Debug        = 0
  3311  	$$ErrorVerbose = false
  3312  )
  3313  
  3314  type $$Lexer interface {
  3315  	Lex(lval *$$SymType) int
  3316  	Error(s string)
  3317  }
  3318  
  3319  type $$Parser interface {
  3320  	Parse($$Lexer) int
  3321  	Lookahead() int
  3322  }
  3323  
  3324  type $$ParserImpl struct {
  3325  	lval  $$SymType
  3326  	stack [$$InitialStackSize]$$SymType
  3327  	char  int
  3328  }
  3329  
  3330  func (p *$$ParserImpl) Lookahead() int {
  3331  	return p.char
  3332  }
  3333  
  3334  func $$NewParser() $$Parser {
  3335  	return &$$ParserImpl{}
  3336  }
  3337  
  3338  const $$Flag = -1000
  3339  
  3340  func $$Tokname(c int) string {
  3341  	if c >= 1 && c-1 < len($$Toknames) {
  3342  		if $$Toknames[c-1] != "" {
  3343  			return $$Toknames[c-1]
  3344  		}
  3345  	}
  3346  	return __yyfmt__.Sprintf("tok-%v", c)
  3347  }
  3348  
  3349  func $$Statname(s int) string {
  3350  	if s >= 0 && s < len($$Statenames) {
  3351  		if $$Statenames[s] != "" {
  3352  			return $$Statenames[s]
  3353  		}
  3354  	}
  3355  	return __yyfmt__.Sprintf("state-%v", s)
  3356  }
  3357  
  3358  func $$ErrorMessage(state, lookAhead int) string {
  3359  	const TOKSTART = 4
  3360  
  3361  	if !$$ErrorVerbose {
  3362  		return "syntax error"
  3363  	}
  3364  
  3365  	for _, e := range $$ErrorMessages {
  3366  		if e.state == state && e.token == lookAhead {
  3367  			return "syntax error: " + e.msg
  3368  		}
  3369  	}
  3370  
  3371  	res := "syntax error: unexpected " + $$Tokname(lookAhead)
  3372  
  3373  	// To match Bison, suggest at most four expected tokens.
  3374  	expected := make([]int, 0, 4)
  3375  
  3376  	// Look for shiftable tokens.
  3377  	base := $$Pact[state]
  3378  	for tok := TOKSTART; tok-1 < len($$Toknames); tok++ {
  3379  		if n := base + tok; n >= 0 && n < $$Last && $$Chk[$$Act[n]] == tok {
  3380  			if len(expected) == cap(expected) {
  3381  				return res
  3382  			}
  3383  			expected = append(expected, tok)
  3384  		}
  3385  	}
  3386  
  3387  	if $$Def[state] == -2 {
  3388  		i := 0
  3389  		for $$Exca[i] != -1 || $$Exca[i+1] != state {
  3390  			i += 2
  3391  		}
  3392  
  3393  		// Look for tokens that we accept or reduce.
  3394  		for i += 2; $$Exca[i] >= 0; i += 2 {
  3395  			tok := $$Exca[i]
  3396  			if tok < TOKSTART || $$Exca[i+1] == 0 {
  3397  				continue
  3398  			}
  3399  			if len(expected) == cap(expected) {
  3400  				return res
  3401  			}
  3402  			expected = append(expected, tok)
  3403  		}
  3404  
  3405  		// If the default action is to accept or reduce, give up.
  3406  		if $$Exca[i+1] != 0 {
  3407  			return res
  3408  		}
  3409  	}
  3410  
  3411  	for i, tok := range expected {
  3412  		if i == 0 {
  3413  			res += ", expecting "
  3414  		} else {
  3415  			res += " or "
  3416  		}
  3417  		res += $$Tokname(tok)
  3418  	}
  3419  	return res
  3420  }
  3421  
  3422  func $$lex1(lex $$Lexer, lval *$$SymType) (char, token int) {
  3423  	token = 0
  3424  	char = lex.Lex(lval)
  3425  	if char <= 0 {
  3426  		token = $$Tok1[0]
  3427  		goto out
  3428  	}
  3429  	if char < len($$Tok1) {
  3430  		token = $$Tok1[char]
  3431  		goto out
  3432  	}
  3433  	if char >= $$Private {
  3434  		if char < $$Private+len($$Tok2) {
  3435  			token = $$Tok2[char-$$Private]
  3436  			goto out
  3437  		}
  3438  	}
  3439  	for i := 0; i < len($$Tok3); i += 2 {
  3440  		token = $$Tok3[i+0]
  3441  		if token == char {
  3442  			token = $$Tok3[i+1]
  3443  			goto out
  3444  		}
  3445  	}
  3446  
  3447  out:
  3448  	if token == 0 {
  3449  		token = $$Tok2[1] /* unknown char */
  3450  	}
  3451  	if $$Debug >= 3 {
  3452  		__yyfmt__.Printf("lex %s(%d)\n", $$Tokname(token), uint(char))
  3453  	}
  3454  	return char, token
  3455  }
  3456  
  3457  func $$Parse($$lex $$Lexer) int {
  3458  	return $$NewParser().Parse($$lex)
  3459  }
  3460  
  3461  func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int {
  3462  	var $$n int
  3463  	var $$VAL $$SymType
  3464  	var $$Dollar []$$SymType
  3465  	_ = $$Dollar // silence set and not used
  3466  	$$S := $$rcvr.stack[:]
  3467  
  3468  	Nerrs := 0   /* number of errors */
  3469  	Errflag := 0 /* error recovery flag */
  3470  	$$state := 0
  3471  	$$rcvr.char = -1
  3472  	$$token := -1 // $$rcvr.char translated into internal numbering
  3473  	defer func() {
  3474  		// Make sure we report no lookahead when not parsing.
  3475  		$$state = -1
  3476  		$$rcvr.char = -1
  3477  		$$token = -1
  3478  	}()
  3479  	$$p := -1
  3480  	goto $$stack
  3481  
  3482  ret0:
  3483  	return 0
  3484  
  3485  ret1:
  3486  	return 1
  3487  
  3488  $$stack:
  3489  	/* put a state and value onto the stack */
  3490  	if $$Debug >= 4 {
  3491  		__yyfmt__.Printf("char %v in %v\n", $$Tokname($$token), $$Statname($$state))
  3492  	}
  3493  
  3494  	$$p++
  3495  	if $$p >= len($$S) {
  3496  		nyys := make([]$$SymType, len($$S)*2)
  3497  		copy(nyys, $$S)
  3498  		$$S = nyys
  3499  	}
  3500  	$$S[$$p] = $$VAL
  3501  	$$S[$$p].yys = $$state
  3502  
  3503  $$newstate:
  3504  	$$n = $$Pact[$$state]
  3505  	if $$n <= $$Flag {
  3506  		goto $$default /* simple state */
  3507  	}
  3508  	if $$rcvr.char < 0 {
  3509  		$$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)
  3510  	}
  3511  	$$n += $$token
  3512  	if $$n < 0 || $$n >= $$Last {
  3513  		goto $$default
  3514  	}
  3515  	$$n = $$Act[$$n]
  3516  	if $$Chk[$$n] == $$token { /* valid shift */
  3517  		$$rcvr.char = -1
  3518  		$$token = -1
  3519  		$$VAL = $$rcvr.lval
  3520  		$$state = $$n
  3521  		if Errflag > 0 {
  3522  			Errflag--
  3523  		}
  3524  		goto $$stack
  3525  	}
  3526  
  3527  $$default:
  3528  	/* default state action */
  3529  	$$n = $$Def[$$state]
  3530  	if $$n == -2 {
  3531  		if $$rcvr.char < 0 {
  3532  			$$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)
  3533  		}
  3534  
  3535  		/* look through exception table */
  3536  		xi := 0
  3537  		for {
  3538  			if $$Exca[xi+0] == -1 && $$Exca[xi+1] == $$state {
  3539  				break
  3540  			}
  3541  			xi += 2
  3542  		}
  3543  		for xi += 2; ; xi += 2 {
  3544  			$$n = $$Exca[xi+0]
  3545  			if $$n < 0 || $$n == $$token {
  3546  				break
  3547  			}
  3548  		}
  3549  		$$n = $$Exca[xi+1]
  3550  		if $$n < 0 {
  3551  			goto ret0
  3552  		}
  3553  	}
  3554  	if $$n == 0 {
  3555  		/* error ... attempt to resume parsing */
  3556  		switch Errflag {
  3557  		case 0: /* brand new error */
  3558  			$$lex.Error($$ErrorMessage($$state, $$token))
  3559  			Nerrs++
  3560  			if $$Debug >= 1 {
  3561  				__yyfmt__.Printf("%s", $$Statname($$state))
  3562  				__yyfmt__.Printf(" saw %s\n", $$Tokname($$token))
  3563  			}
  3564  			fallthrough
  3565  
  3566  		case 1, 2: /* incompletely recovered error ... try again */
  3567  			Errflag = 3
  3568  
  3569  			/* find a state where "error" is a legal shift action */
  3570  			for $$p >= 0 {
  3571  				$$n = $$Pact[$$S[$$p].yys] + $$ErrCode
  3572  				if $$n >= 0 && $$n < $$Last {
  3573  					$$state = $$Act[$$n] /* simulate a shift of "error" */
  3574  					if $$Chk[$$state] == $$ErrCode {
  3575  						goto $$stack
  3576  					}
  3577  				}
  3578  
  3579  				/* the current p has no shift on "error", pop stack */
  3580  				if $$Debug >= 2 {
  3581  					__yyfmt__.Printf("error recovery pops state %d\n", $$S[$$p].yys)
  3582  				}
  3583  				$$p--
  3584  			}
  3585  			/* there is no state on the stack with an error shift ... abort */
  3586  			goto ret1
  3587  
  3588  		case 3: /* no shift yet; clobber input char */
  3589  			if $$Debug >= 2 {
  3590  				__yyfmt__.Printf("error recovery discards %s\n", $$Tokname($$token))
  3591  			}
  3592  			if $$token == $$EofCode {
  3593  				goto ret1
  3594  			}
  3595  			$$rcvr.char = -1
  3596  			$$token = -1
  3597  			goto $$newstate /* try again in the same state */
  3598  		}
  3599  	}
  3600  
  3601  	/* reduction by production $$n */
  3602  	if $$Debug >= 2 {
  3603  		__yyfmt__.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
  3604  	}
  3605  
  3606  	$$nt := $$n
  3607  	$$pt := $$p
  3608  	_ = $$pt // guard against "declared and not used"
  3609  
  3610  	$$p -= $$R2[$$n]
  3611  	// $$p is now the index of $0. Perform the default action. Iff the
  3612  	// reduced production is ε, $1 is possibly out of range.
  3613  	if $$p+1 >= len($$S) {
  3614  		nyys := make([]$$SymType, len($$S)*2)
  3615  		copy(nyys, $$S)
  3616  		$$S = nyys
  3617  	}
  3618  	$$VAL = $$S[$$p+1]
  3619  
  3620  	/* consult goto table to find next state */
  3621  	$$n = $$R1[$$n]
  3622  	$$g := $$Pgo[$$n]
  3623  	$$j := $$g + $$S[$$p].yys + 1
  3624  
  3625  	if $$j >= $$Last {
  3626  		$$state = $$Act[$$g]
  3627  	} else {
  3628  		$$state = $$Act[$$j]
  3629  		if $$Chk[$$state] != -$$n {
  3630  			$$state = $$Act[$$g]
  3631  		}
  3632  	}
  3633  	// dummy call; replaced with literal code
  3634  	$$run()
  3635  	goto $$stack /* stack new state and value */
  3636  }
  3637  `