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