github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/cmd/yacc/yacc.go (about)

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