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