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