github.com/jgarto/itcv@v0.0.0-20180826224514-4eea09c1aa0d/_vendor/src/golang.org/x/tools/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 "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 = 120000 64 NSTATES = 8000 65 TEMPSIZE = 8000 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 defin(0, "$end") 391 extval = PRIVATE // tokens start in unicode 'private use' 392 defin(0, "error") 393 defin(1, "$accept") 394 defin(0, "$unk") 395 i := 0 396 397 t := gettok() 398 399 outer: 400 for { 401 switch t { 402 default: 403 errorf("syntax error tok=%v", t-PRIVATE) 404 405 case MARK, ENDFILE: 406 break outer 407 408 case ';': 409 // Do nothing. 410 411 case START: 412 t = gettok() 413 if t != IDENTIFIER { 414 errorf("bad %%start construction") 415 } 416 start = chfind(1, tokname) 417 418 case ERROR: 419 lno := lineno 420 var tokens []string 421 for { 422 t := gettok() 423 if t == ':' { 424 break 425 } 426 if t != IDENTIFIER && t != IDENTCOLON { 427 errorf("bad syntax in %%error") 428 } 429 tokens = append(tokens, tokname) 430 if t == IDENTCOLON { 431 break 432 } 433 } 434 if gettok() != IDENTIFIER { 435 errorf("bad syntax in %%error") 436 } 437 errors = append(errors, Error{lno, tokens, tokname}) 438 439 case TYPEDEF: 440 t = gettok() 441 if t != TYPENAME { 442 errorf("bad syntax in %%type") 443 } 444 ty = numbval 445 for { 446 t = gettok() 447 switch t { 448 case IDENTIFIER: 449 t = chfind(1, tokname) 450 if t < NTBASE { 451 j = TYPE(toklev[t]) 452 if j != 0 && j != ty { 453 errorf("type redeclaration of token %s", 454 tokset[t].name) 455 } else { 456 toklev[t] = SETTYPE(toklev[t], ty) 457 } 458 } else { 459 j = nontrst[t-NTBASE].value 460 if j != 0 && j != ty { 461 errorf("type redeclaration of nonterminal %v", 462 nontrst[t-NTBASE].name) 463 } else { 464 nontrst[t-NTBASE].value = ty 465 } 466 } 467 continue 468 469 case ',': 470 continue 471 } 472 break 473 } 474 continue 475 476 case UNION: 477 cpyunion() 478 479 case LEFT, BINARY, RIGHT, TERM: 480 // nonzero means new prec. and assoc. 481 lev := t - TERM 482 if lev != 0 { 483 i++ 484 } 485 ty = 0 486 487 // get identifiers so defined 488 t = gettok() 489 490 // there is a type defined 491 if t == TYPENAME { 492 ty = numbval 493 t = gettok() 494 } 495 for { 496 switch t { 497 case ',': 498 t = gettok() 499 continue 500 501 case ';': 502 // Do nothing. 503 504 case IDENTIFIER: 505 j = chfind(0, tokname) 506 if j >= NTBASE { 507 errorf("%v defined earlier as nonterminal", tokname) 508 } 509 if lev != 0 { 510 if ASSOC(toklev[j]) != 0 { 511 errorf("redeclaration of precedence of %v", tokname) 512 } 513 toklev[j] = SETASC(toklev[j], lev) 514 toklev[j] = SETPLEV(toklev[j], i) 515 } 516 if ty != 0 { 517 if TYPE(toklev[j]) != 0 { 518 errorf("redeclaration of type of %v", tokname) 519 } 520 toklev[j] = SETTYPE(toklev[j], ty) 521 } 522 t = gettok() 523 if t == NUMBER { 524 tokset[j].value = numbval 525 t = gettok() 526 } 527 528 continue 529 } 530 break 531 } 532 continue 533 534 case LCURLY: 535 cpycode() 536 } 537 t = gettok() 538 } 539 540 if t == ENDFILE { 541 errorf("unexpected EOF before %%") 542 } 543 544 fmt.Fprintf(fcode, "switch %snt {\n", prefix) 545 546 moreprod() 547 prdptr[0] = []int{NTBASE, start, 1, 0} 548 549 nprod = 1 550 curprod := make([]int, RULEINC) 551 t = gettok() 552 if t != IDENTCOLON { 553 errorf("bad syntax on first rule") 554 } 555 556 if start == 0 { 557 prdptr[0][1] = chfind(1, tokname) 558 } 559 560 // read rules 561 // put into prdptr array in the format 562 // target 563 // followed by id's of terminals and non-terminals 564 // followed by -nprod 565 566 for t != MARK && t != ENDFILE { 567 mem := 0 568 569 // process a rule 570 rlines[nprod] = lineno 571 ruleline := lineno 572 if t == '|' { 573 curprod[mem] = prdptr[nprod-1][0] 574 mem++ 575 } else if t == IDENTCOLON { 576 curprod[mem] = chfind(1, tokname) 577 if curprod[mem] < NTBASE { 578 lerrorf(ruleline, "token illegal on LHS of grammar rule") 579 } 580 mem++ 581 } else { 582 lerrorf(ruleline, "illegal rule: missing semicolon or | ?") 583 } 584 585 // read rule body 586 t = gettok() 587 for { 588 for t == IDENTIFIER { 589 curprod[mem] = chfind(1, tokname) 590 if curprod[mem] < NTBASE { 591 levprd[nprod] = toklev[curprod[mem]] 592 } 593 mem++ 594 if mem >= len(curprod) { 595 ncurprod := make([]int, mem+RULEINC) 596 copy(ncurprod, curprod) 597 curprod = ncurprod 598 } 599 t = gettok() 600 } 601 if t == PREC { 602 if gettok() != IDENTIFIER { 603 lerrorf(ruleline, "illegal %%prec syntax") 604 } 605 j = chfind(2, tokname) 606 if j >= NTBASE { 607 lerrorf(ruleline, "nonterminal "+nontrst[j-NTBASE].name+" illegal after %%prec") 608 } 609 levprd[nprod] = toklev[j] 610 t = gettok() 611 } 612 if t != '=' { 613 break 614 } 615 levprd[nprod] |= ACTFLAG 616 fmt.Fprintf(fcode, "\n\tcase %v:", nprod) 617 fmt.Fprintf(fcode, "\n\t\t%sDollar = %sS[%spt-%v:%spt+1]", prefix, prefix, prefix, mem-1, prefix) 618 cpyact(curprod, mem) 619 620 // action within rule... 621 t = gettok() 622 if t == IDENTIFIER { 623 // make it a nonterminal 624 j = chfind(1, fmt.Sprintf("$$%v", nprod)) 625 626 // 627 // the current rule will become rule number nprod+1 628 // enter null production for action 629 // 630 prdptr[nprod] = make([]int, 2) 631 prdptr[nprod][0] = j 632 prdptr[nprod][1] = -nprod 633 634 // update the production information 635 nprod++ 636 moreprod() 637 levprd[nprod] = levprd[nprod-1] & ^ACTFLAG 638 levprd[nprod-1] = ACTFLAG 639 rlines[nprod] = lineno 640 641 // make the action appear in the original rule 642 curprod[mem] = j 643 mem++ 644 if mem >= len(curprod) { 645 ncurprod := make([]int, mem+RULEINC) 646 copy(ncurprod, curprod) 647 curprod = ncurprod 648 } 649 } 650 } 651 652 for t == ';' { 653 t = gettok() 654 } 655 curprod[mem] = -nprod 656 mem++ 657 658 // check that default action is reasonable 659 if ntypes != 0 && (levprd[nprod]&ACTFLAG) == 0 && 660 nontrst[curprod[0]-NTBASE].value != 0 { 661 // no explicit action, LHS has value 662 tempty := curprod[1] 663 if tempty < 0 { 664 lerrorf(ruleline, "must return a value, since LHS has a type") 665 } 666 if tempty >= NTBASE { 667 tempty = nontrst[tempty-NTBASE].value 668 } else { 669 tempty = TYPE(toklev[tempty]) 670 } 671 if tempty != nontrst[curprod[0]-NTBASE].value { 672 lerrorf(ruleline, "default action causes potential type clash") 673 } 674 } 675 moreprod() 676 prdptr[nprod] = make([]int, mem) 677 copy(prdptr[nprod], curprod) 678 nprod++ 679 moreprod() 680 levprd[nprod] = 0 681 } 682 683 if TEMPSIZE < ntokens+nnonter+1 { 684 errorf("too many tokens (%d) or non-terminals (%d)", ntokens, nnonter) 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 %sInitialStackSize = %v\n", prefix, initialstacksize) 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 c := getrune(finput) 1230 if c == '/' { 1231 for c != EOF { 1232 if c == '\n' { 1233 return 1 1234 } 1235 c = getrune(finput) 1236 } 1237 errorf("EOF inside comment") 1238 return 0 1239 } 1240 if c != '*' { 1241 errorf("illegal comment") 1242 } 1243 1244 nl := 0 // lines skipped 1245 c = getrune(finput) 1246 1247 l1: 1248 switch c { 1249 case '*': 1250 c = getrune(finput) 1251 if c == '/' { 1252 break 1253 } 1254 goto l1 1255 1256 case '\n': 1257 nl++ 1258 fallthrough 1259 1260 default: 1261 c = getrune(finput) 1262 goto l1 1263 } 1264 return nl 1265 } 1266 1267 // 1268 // copy action to the next ; or closing } 1269 // 1270 func cpyact(curprod []int, max int) { 1271 1272 if !lflag { 1273 fmt.Fprintf(fcode, "\n\t\t//line %v:%v", infile, lineno) 1274 } 1275 fmt.Fprint(fcode, "\n\t\t") 1276 1277 lno := lineno 1278 brac := 0 1279 1280 loop: 1281 for { 1282 c := getrune(finput) 1283 1284 swt: 1285 switch c { 1286 case ';': 1287 if brac == 0 { 1288 fcode.WriteRune(c) 1289 return 1290 } 1291 1292 case '{': 1293 brac++ 1294 1295 case '$': 1296 s := 1 1297 tok := -1 1298 c = getrune(finput) 1299 1300 // type description 1301 if c == '<' { 1302 ungetrune(finput, c) 1303 if gettok() != TYPENAME { 1304 errorf("bad syntax on $<ident> clause") 1305 } 1306 tok = numbval 1307 c = getrune(finput) 1308 } 1309 if c == '$' { 1310 fmt.Fprintf(fcode, "%sVAL", prefix) 1311 1312 // put out the proper tag... 1313 if ntypes != 0 { 1314 if tok < 0 { 1315 tok = fdtype(curprod[0]) 1316 } 1317 fmt.Fprintf(fcode, ".%v", typeset[tok]) 1318 } 1319 continue loop 1320 } 1321 if c == '-' { 1322 s = -s 1323 c = getrune(finput) 1324 } 1325 j := 0 1326 if isdigit(c) { 1327 for isdigit(c) { 1328 j = j*10 + int(c-'0') 1329 c = getrune(finput) 1330 } 1331 ungetrune(finput, c) 1332 j = j * s 1333 if j >= max { 1334 errorf("Illegal use of $%v", j) 1335 } 1336 } else if isword(c) || c == '.' { 1337 // look for $name 1338 ungetrune(finput, c) 1339 if gettok() != IDENTIFIER { 1340 errorf("$ must be followed by an identifier") 1341 } 1342 tokn := chfind(2, tokname) 1343 fnd := -1 1344 c = getrune(finput) 1345 if c != '@' { 1346 ungetrune(finput, c) 1347 } else if gettok() != NUMBER { 1348 errorf("@ must be followed by number") 1349 } else { 1350 fnd = numbval 1351 } 1352 for j = 1; j < max; j++ { 1353 if tokn == curprod[j] { 1354 fnd-- 1355 if fnd <= 0 { 1356 break 1357 } 1358 } 1359 } 1360 if j >= max { 1361 errorf("$name or $name@number not found") 1362 } 1363 } else { 1364 fcode.WriteRune('$') 1365 if s < 0 { 1366 fcode.WriteRune('-') 1367 } 1368 ungetrune(finput, c) 1369 continue loop 1370 } 1371 fmt.Fprintf(fcode, "%sDollar[%v]", prefix, j) 1372 1373 // put out the proper tag 1374 if ntypes != 0 { 1375 if j <= 0 && tok < 0 { 1376 errorf("must specify type of $%v", j) 1377 } 1378 if tok < 0 { 1379 tok = fdtype(curprod[j]) 1380 } 1381 fmt.Fprintf(fcode, ".%v", typeset[tok]) 1382 } 1383 continue loop 1384 1385 case '}': 1386 brac-- 1387 if brac != 0 { 1388 break 1389 } 1390 fcode.WriteRune(c) 1391 return 1392 1393 case '/': 1394 nc := getrune(finput) 1395 if nc != '/' && nc != '*' { 1396 ungetrune(finput, nc) 1397 break 1398 } 1399 // a comment 1400 fcode.WriteRune(c) 1401 fcode.WriteRune(nc) 1402 c = getrune(finput) 1403 for c != EOF { 1404 switch { 1405 case c == '\n': 1406 lineno++ 1407 if nc == '/' { // end of // comment 1408 break swt 1409 } 1410 case c == '*' && nc == '*': // end of /* comment? 1411 nnc := getrune(finput) 1412 if nnc == '/' { 1413 fcode.WriteRune('*') 1414 fcode.WriteRune('/') 1415 c = getrune(finput) 1416 break swt 1417 } 1418 ungetrune(finput, nnc) 1419 } 1420 fcode.WriteRune(c) 1421 c = getrune(finput) 1422 } 1423 errorf("EOF inside comment") 1424 1425 case '\'', '"': 1426 // character string or constant 1427 match := c 1428 fcode.WriteRune(c) 1429 c = getrune(finput) 1430 for c != EOF { 1431 if c == '\\' { 1432 fcode.WriteRune(c) 1433 c = getrune(finput) 1434 if c == '\n' { 1435 lineno++ 1436 } 1437 } else if c == match { 1438 break swt 1439 } 1440 if c == '\n' { 1441 errorf("newline in string or char const") 1442 } 1443 fcode.WriteRune(c) 1444 c = getrune(finput) 1445 } 1446 errorf("EOF in string or character constant") 1447 1448 case EOF: 1449 lineno = lno 1450 errorf("action does not terminate") 1451 1452 case '\n': 1453 fmt.Fprint(fcode, "\n\t") 1454 lineno++ 1455 continue loop 1456 } 1457 1458 fcode.WriteRune(c) 1459 } 1460 } 1461 1462 func openup() { 1463 infile = flag.Arg(0) 1464 finput = open(infile) 1465 if finput == nil { 1466 errorf("cannot open %v", infile) 1467 } 1468 1469 foutput = nil 1470 if vflag != "" { 1471 foutput = create(vflag) 1472 if foutput == nil { 1473 errorf("can't create file %v", vflag) 1474 } 1475 } 1476 1477 ftable = nil 1478 if oflag == "" { 1479 oflag = "y.go" 1480 } 1481 ftable = create(oflag) 1482 if ftable == nil { 1483 errorf("can't create file %v", oflag) 1484 } 1485 1486 } 1487 1488 // 1489 // return a pointer to the name of symbol i 1490 // 1491 func symnam(i int) string { 1492 var s string 1493 1494 if i >= NTBASE { 1495 s = nontrst[i-NTBASE].name 1496 } else { 1497 s = tokset[i].name 1498 } 1499 return s 1500 } 1501 1502 // 1503 // set elements 0 through n-1 to c 1504 // 1505 func aryfil(v []int, n, c int) { 1506 for i := 0; i < n; i++ { 1507 v[i] = c 1508 } 1509 } 1510 1511 // 1512 // compute an array with the beginnings of productions yielding given nonterminals 1513 // The array pres points to these lists 1514 // the array pyield has the lists: the total size is only NPROD+1 1515 // 1516 func cpres() { 1517 pres = make([][][]int, nnonter+1) 1518 curres := make([][]int, nprod) 1519 1520 if false { 1521 for j := 0; j <= nnonter; j++ { 1522 fmt.Printf("nnonter[%v] = %v\n", j, nontrst[j].name) 1523 } 1524 for j := 0; j < nprod; j++ { 1525 fmt.Printf("prdptr[%v][0] = %v+NTBASE\n", j, prdptr[j][0]-NTBASE) 1526 } 1527 } 1528 1529 fatfl = 0 // make undefined symbols nonfatal 1530 for i := 0; i <= nnonter; i++ { 1531 n := 0 1532 c := i + NTBASE 1533 for j := 0; j < nprod; j++ { 1534 if prdptr[j][0] == c { 1535 curres[n] = prdptr[j][1:] 1536 n++ 1537 } 1538 } 1539 if n == 0 { 1540 errorf("nonterminal %v not defined", nontrst[i].name) 1541 continue 1542 } 1543 pres[i] = make([][]int, n) 1544 copy(pres[i], curres) 1545 } 1546 fatfl = 1 1547 if nerrors != 0 { 1548 summary() 1549 exit(1) 1550 } 1551 } 1552 1553 // 1554 // mark nonterminals which derive the empty string 1555 // also, look for nonterminals which don't derive any token strings 1556 // 1557 func cempty() { 1558 var i, p, np int 1559 var prd []int 1560 1561 pempty = make([]int, nnonter+1) 1562 1563 // first, use the array pempty to detect productions that can never be reduced 1564 // set pempty to WHONOWS 1565 aryfil(pempty, nnonter+1, WHOKNOWS) 1566 1567 // now, look at productions, marking nonterminals which derive something 1568 more: 1569 for { 1570 for i = 0; i < nprod; i++ { 1571 prd = prdptr[i] 1572 if pempty[prd[0]-NTBASE] != 0 { 1573 continue 1574 } 1575 np = len(prd) - 1 1576 for p = 1; p < np; p++ { 1577 if prd[p] >= NTBASE && pempty[prd[p]-NTBASE] == WHOKNOWS { 1578 break 1579 } 1580 } 1581 // production can be derived 1582 if p == np { 1583 pempty[prd[0]-NTBASE] = OK 1584 continue more 1585 } 1586 } 1587 break 1588 } 1589 1590 // now, look at the nonterminals, to see if they are all OK 1591 for i = 0; i <= nnonter; i++ { 1592 // the added production rises or falls as the start symbol ... 1593 if i == 0 { 1594 continue 1595 } 1596 if pempty[i] != OK { 1597 fatfl = 0 1598 errorf("nonterminal " + nontrst[i].name + " never derives any token string") 1599 } 1600 } 1601 1602 if nerrors != 0 { 1603 summary() 1604 exit(1) 1605 } 1606 1607 // now, compute the pempty array, to see which nonterminals derive the empty string 1608 // set pempty to WHOKNOWS 1609 aryfil(pempty, nnonter+1, WHOKNOWS) 1610 1611 // loop as long as we keep finding empty nonterminals 1612 1613 again: 1614 for { 1615 next: 1616 for i = 1; i < nprod; i++ { 1617 // not known to be empty 1618 prd = prdptr[i] 1619 if pempty[prd[0]-NTBASE] != WHOKNOWS { 1620 continue 1621 } 1622 np = len(prd) - 1 1623 for p = 1; p < np; p++ { 1624 if prd[p] < NTBASE || pempty[prd[p]-NTBASE] != EMPTY { 1625 continue next 1626 } 1627 } 1628 1629 // we have a nontrivially empty nonterminal 1630 pempty[prd[0]-NTBASE] = EMPTY 1631 1632 // got one ... try for another 1633 continue again 1634 } 1635 return 1636 } 1637 } 1638 1639 // 1640 // compute an array with the first of nonterminals 1641 // 1642 func cpfir() { 1643 var s, n, p, np, ch, i int 1644 var curres [][]int 1645 var prd []int 1646 1647 wsets = make([]Wset, nnonter+WSETINC) 1648 pfirst = make([]Lkset, nnonter+1) 1649 for i = 0; i <= nnonter; i++ { 1650 wsets[i].ws = mkset() 1651 pfirst[i] = mkset() 1652 curres = pres[i] 1653 n = len(curres) 1654 1655 // initially fill the sets 1656 for s = 0; s < n; s++ { 1657 prd = curres[s] 1658 np = len(prd) - 1 1659 for p = 0; p < np; p++ { 1660 ch = prd[p] 1661 if ch < NTBASE { 1662 setbit(pfirst[i], ch) 1663 break 1664 } 1665 if pempty[ch-NTBASE] == 0 { 1666 break 1667 } 1668 } 1669 } 1670 } 1671 1672 // now, reflect transitivity 1673 changes := 1 1674 for changes != 0 { 1675 changes = 0 1676 for i = 0; i <= nnonter; i++ { 1677 curres = pres[i] 1678 n = len(curres) 1679 for s = 0; s < n; s++ { 1680 prd = curres[s] 1681 np = len(prd) - 1 1682 for p = 0; p < np; p++ { 1683 ch = prd[p] - NTBASE 1684 if ch < 0 { 1685 break 1686 } 1687 changes |= setunion(pfirst[i], pfirst[ch]) 1688 if pempty[ch] == 0 { 1689 break 1690 } 1691 } 1692 } 1693 } 1694 } 1695 1696 if indebug == 0 { 1697 return 1698 } 1699 if foutput != nil { 1700 for i = 0; i <= nnonter; i++ { 1701 fmt.Fprintf(foutput, "\n%v: %v %v\n", 1702 nontrst[i].name, pfirst[i], pempty[i]) 1703 } 1704 } 1705 } 1706 1707 // 1708 // generate the states 1709 // 1710 func stagen() { 1711 // initialize 1712 nstate = 0 1713 tstates = make([]int, ntokens+1) // states generated by terminal gotos 1714 ntstates = make([]int, nnonter+1) // states generated by nonterminal gotos 1715 amem = make([]int, ACTSIZE) 1716 memp = 0 1717 1718 clset = mkset() 1719 pstate[0] = 0 1720 pstate[1] = 0 1721 aryfil(clset, tbitset, 0) 1722 putitem(Pitem{prdptr[0], 0, 0, 0}, clset) 1723 tystate[0] = MUSTDO 1724 nstate = 1 1725 pstate[2] = pstate[1] 1726 1727 // 1728 // now, the main state generation loop 1729 // first pass generates all of the states 1730 // later passes fix up lookahead 1731 // could be sped up a lot by remembering 1732 // results of the first pass rather than recomputing 1733 // 1734 first := 1 1735 for more := 1; more != 0; first = 0 { 1736 more = 0 1737 for i := 0; i < nstate; i++ { 1738 if tystate[i] != MUSTDO { 1739 continue 1740 } 1741 1742 tystate[i] = DONE 1743 aryfil(temp1, nnonter+1, 0) 1744 1745 // take state i, close it, and do gotos 1746 closure(i) 1747 1748 // generate goto's 1749 for p := 0; p < cwp; p++ { 1750 pi := wsets[p] 1751 if pi.flag != 0 { 1752 continue 1753 } 1754 wsets[p].flag = 1 1755 c := pi.pitem.first 1756 if c <= 1 { 1757 if pstate[i+1]-pstate[i] <= p { 1758 tystate[i] = MUSTLOOKAHEAD 1759 } 1760 continue 1761 } 1762 1763 // do a goto on c 1764 putitem(wsets[p].pitem, wsets[p].ws) 1765 for q := p + 1; q < cwp; q++ { 1766 // this item contributes to the goto 1767 if c == wsets[q].pitem.first { 1768 putitem(wsets[q].pitem, wsets[q].ws) 1769 wsets[q].flag = 1 1770 } 1771 } 1772 1773 if c < NTBASE { 1774 state(c) // register new state 1775 } else { 1776 temp1[c-NTBASE] = state(c) 1777 } 1778 } 1779 1780 if gsdebug != 0 && foutput != nil { 1781 fmt.Fprintf(foutput, "%v: ", i) 1782 for j := 0; j <= nnonter; j++ { 1783 if temp1[j] != 0 { 1784 fmt.Fprintf(foutput, "%v %v,", nontrst[j].name, temp1[j]) 1785 } 1786 } 1787 fmt.Fprintf(foutput, "\n") 1788 } 1789 1790 if first != 0 { 1791 indgo[i] = apack(temp1[1:], nnonter-1) - 1 1792 } 1793 1794 more++ 1795 } 1796 } 1797 } 1798 1799 // 1800 // generate the closure of state i 1801 // 1802 func closure(i int) { 1803 zzclose++ 1804 1805 // first, copy kernel of state i to wsets 1806 cwp = 0 1807 q := pstate[i+1] 1808 for p := pstate[i]; p < q; p++ { 1809 wsets[cwp].pitem = statemem[p].pitem 1810 wsets[cwp].flag = 1 // this item must get closed 1811 copy(wsets[cwp].ws, statemem[p].look) 1812 cwp++ 1813 } 1814 1815 // now, go through the loop, closing each item 1816 work := 1 1817 for work != 0 { 1818 work = 0 1819 for u := 0; u < cwp; u++ { 1820 if wsets[u].flag == 0 { 1821 continue 1822 } 1823 1824 // dot is before c 1825 c := wsets[u].pitem.first 1826 if c < NTBASE { 1827 wsets[u].flag = 0 1828 // only interesting case is where . is before nonterminal 1829 continue 1830 } 1831 1832 // compute the lookahead 1833 aryfil(clset, tbitset, 0) 1834 1835 // find items involving c 1836 for v := u; v < cwp; v++ { 1837 if wsets[v].flag != 1 || wsets[v].pitem.first != c { 1838 continue 1839 } 1840 pi := wsets[v].pitem.prod 1841 ipi := wsets[v].pitem.off + 1 1842 1843 wsets[v].flag = 0 1844 if nolook != 0 { 1845 continue 1846 } 1847 1848 ch := pi[ipi] 1849 ipi++ 1850 for ch > 0 { 1851 // terminal symbol 1852 if ch < NTBASE { 1853 setbit(clset, ch) 1854 break 1855 } 1856 1857 // nonterminal symbol 1858 setunion(clset, pfirst[ch-NTBASE]) 1859 if pempty[ch-NTBASE] == 0 { 1860 break 1861 } 1862 ch = pi[ipi] 1863 ipi++ 1864 } 1865 if ch <= 0 { 1866 setunion(clset, wsets[v].ws) 1867 } 1868 } 1869 1870 // 1871 // now loop over productions derived from c 1872 // 1873 curres := pres[c-NTBASE] 1874 n := len(curres) 1875 1876 nexts: 1877 // initially fill the sets 1878 for s := 0; s < n; s++ { 1879 prd := curres[s] 1880 1881 // 1882 // put these items into the closure 1883 // is the item there 1884 // 1885 for v := 0; v < cwp; v++ { 1886 // yes, it is there 1887 if wsets[v].pitem.off == 0 && 1888 aryeq(wsets[v].pitem.prod, prd) != 0 { 1889 if nolook == 0 && 1890 setunion(wsets[v].ws, clset) != 0 { 1891 wsets[v].flag = 1 1892 work = 1 1893 } 1894 continue nexts 1895 } 1896 } 1897 1898 // not there; make a new entry 1899 if cwp >= len(wsets) { 1900 awsets := make([]Wset, cwp+WSETINC) 1901 copy(awsets, wsets) 1902 wsets = awsets 1903 } 1904 wsets[cwp].pitem = Pitem{prd, 0, prd[0], -prd[len(prd)-1]} 1905 wsets[cwp].flag = 1 1906 wsets[cwp].ws = mkset() 1907 if nolook == 0 { 1908 work = 1 1909 copy(wsets[cwp].ws, clset) 1910 } 1911 cwp++ 1912 } 1913 } 1914 } 1915 1916 // have computed closure; flags are reset; return 1917 if cldebug != 0 && foutput != nil { 1918 fmt.Fprintf(foutput, "\nState %v, nolook = %v\n", i, nolook) 1919 for u := 0; u < cwp; u++ { 1920 if wsets[u].flag != 0 { 1921 fmt.Fprintf(foutput, "flag set\n") 1922 } 1923 wsets[u].flag = 0 1924 fmt.Fprintf(foutput, "\t%v", writem(wsets[u].pitem)) 1925 prlook(wsets[u].ws) 1926 fmt.Fprintf(foutput, "\n") 1927 } 1928 } 1929 } 1930 1931 // 1932 // sorts last state,and sees if it equals earlier ones. returns state number 1933 // 1934 func state(c int) int { 1935 zzstate++ 1936 p1 := pstate[nstate] 1937 p2 := pstate[nstate+1] 1938 if p1 == p2 { 1939 return 0 // null state 1940 } 1941 1942 // sort the items 1943 var k, l int 1944 for k = p1 + 1; k < p2; k++ { // make k the biggest 1945 for l = k; l > p1; l-- { 1946 if statemem[l].pitem.prodno < statemem[l-1].pitem.prodno || 1947 statemem[l].pitem.prodno == statemem[l-1].pitem.prodno && 1948 statemem[l].pitem.off < statemem[l-1].pitem.off { 1949 s := statemem[l] 1950 statemem[l] = statemem[l-1] 1951 statemem[l-1] = s 1952 } else { 1953 break 1954 } 1955 } 1956 } 1957 1958 size1 := p2 - p1 // size of state 1959 1960 var i int 1961 if c >= NTBASE { 1962 i = ntstates[c-NTBASE] 1963 } else { 1964 i = tstates[c] 1965 } 1966 1967 look: 1968 for ; i != 0; i = mstates[i] { 1969 // get ith state 1970 q1 := pstate[i] 1971 q2 := pstate[i+1] 1972 size2 := q2 - q1 1973 if size1 != size2 { 1974 continue 1975 } 1976 k = p1 1977 for l = q1; l < q2; l++ { 1978 if aryeq(statemem[l].pitem.prod, statemem[k].pitem.prod) == 0 || 1979 statemem[l].pitem.off != statemem[k].pitem.off { 1980 continue look 1981 } 1982 k++ 1983 } 1984 1985 // found it 1986 pstate[nstate+1] = pstate[nstate] // delete last state 1987 1988 // fix up lookaheads 1989 if nolook != 0 { 1990 return i 1991 } 1992 k = p1 1993 for l = q1; l < q2; l++ { 1994 if setunion(statemem[l].look, statemem[k].look) != 0 { 1995 tystate[i] = MUSTDO 1996 } 1997 k++ 1998 } 1999 return i 2000 } 2001 2002 // state is new 2003 zznewstate++ 2004 if nolook != 0 { 2005 errorf("yacc state/nolook error") 2006 } 2007 pstate[nstate+2] = p2 2008 if nstate+1 >= NSTATES { 2009 errorf("too many states") 2010 } 2011 if c >= NTBASE { 2012 mstates[nstate] = ntstates[c-NTBASE] 2013 ntstates[c-NTBASE] = nstate 2014 } else { 2015 mstates[nstate] = tstates[c] 2016 tstates[c] = nstate 2017 } 2018 tystate[nstate] = MUSTDO 2019 nstate++ 2020 return nstate - 1 2021 } 2022 2023 func putitem(p Pitem, set Lkset) { 2024 p.off++ 2025 p.first = p.prod[p.off] 2026 2027 if pidebug != 0 && foutput != nil { 2028 fmt.Fprintf(foutput, "putitem(%v), state %v\n", writem(p), nstate) 2029 } 2030 j := pstate[nstate+1] 2031 if j >= len(statemem) { 2032 asm := make([]Item, j+STATEINC) 2033 copy(asm, statemem) 2034 statemem = asm 2035 } 2036 statemem[j].pitem = p 2037 if nolook == 0 { 2038 s := mkset() 2039 copy(s, set) 2040 statemem[j].look = s 2041 } 2042 j++ 2043 pstate[nstate+1] = j 2044 } 2045 2046 // 2047 // creates output string for item pointed to by pp 2048 // 2049 func writem(pp Pitem) string { 2050 var i int 2051 2052 p := pp.prod 2053 q := chcopy(nontrst[prdptr[pp.prodno][0]-NTBASE].name) + ": " 2054 npi := pp.off 2055 2056 pi := aryeq(p, prdptr[pp.prodno]) 2057 2058 for { 2059 c := ' ' 2060 if pi == npi { 2061 c = '.' 2062 } 2063 q += string(c) 2064 2065 i = p[pi] 2066 pi++ 2067 if i <= 0 { 2068 break 2069 } 2070 q += chcopy(symnam(i)) 2071 } 2072 2073 // an item calling for a reduction 2074 i = p[npi] 2075 if i < 0 { 2076 q += fmt.Sprintf(" (%v)", -i) 2077 } 2078 2079 return q 2080 } 2081 2082 // 2083 // pack state i from temp1 into amem 2084 // 2085 func apack(p []int, n int) int { 2086 // 2087 // we don't need to worry about checking because 2088 // we will only look at entries known to be there... 2089 // eliminate leading and trailing 0's 2090 // 2091 off := 0 2092 pp := 0 2093 for ; pp <= n && p[pp] == 0; pp++ { 2094 off-- 2095 } 2096 2097 // no actions 2098 if pp > n { 2099 return 0 2100 } 2101 for ; n > pp && p[n] == 0; n-- { 2102 } 2103 p = p[pp : n+1] 2104 2105 // now, find a place for the elements from p to q, inclusive 2106 r := len(amem) - len(p) 2107 2108 nextk: 2109 for rr := 0; rr <= r; rr++ { 2110 qq := rr 2111 for pp = 0; pp < len(p); pp++ { 2112 if p[pp] != 0 { 2113 if p[pp] != amem[qq] && amem[qq] != 0 { 2114 continue nextk 2115 } 2116 } 2117 qq++ 2118 } 2119 2120 // we have found an acceptable k 2121 if pkdebug != 0 && foutput != nil { 2122 fmt.Fprintf(foutput, "off = %v, k = %v\n", off+rr, rr) 2123 } 2124 qq = rr 2125 for pp = 0; pp < len(p); pp++ { 2126 if p[pp] != 0 { 2127 if qq > memp { 2128 memp = qq 2129 } 2130 amem[qq] = p[pp] 2131 } 2132 qq++ 2133 } 2134 if pkdebug != 0 && foutput != nil { 2135 for pp = 0; pp <= memp; pp += 10 { 2136 fmt.Fprintf(foutput, "\n") 2137 for qq = pp; qq <= pp+9; qq++ { 2138 fmt.Fprintf(foutput, "%v ", amem[qq]) 2139 } 2140 fmt.Fprintf(foutput, "\n") 2141 } 2142 } 2143 return off + rr 2144 } 2145 errorf("no space in action table") 2146 return 0 2147 } 2148 2149 // 2150 // print the output for the states 2151 // 2152 func output() { 2153 var c, u, v int 2154 2155 if !lflag { 2156 fmt.Fprintf(ftable, "\n//line yacctab:1") 2157 } 2158 fmt.Fprintf(ftable, "\nvar %sExca = [...]int{\n", prefix) 2159 2160 if len(errors) > 0 { 2161 stateTable = make([]Row, nstate) 2162 } 2163 2164 noset := mkset() 2165 2166 // output the stuff for state i 2167 for i := 0; i < nstate; i++ { 2168 nolook = 0 2169 if tystate[i] != MUSTLOOKAHEAD { 2170 nolook = 1 2171 } 2172 closure(i) 2173 2174 // output actions 2175 nolook = 1 2176 aryfil(temp1, ntokens+nnonter+1, 0) 2177 for u = 0; u < cwp; u++ { 2178 c = wsets[u].pitem.first 2179 if c > 1 && c < NTBASE && temp1[c] == 0 { 2180 for v = u; v < cwp; v++ { 2181 if c == wsets[v].pitem.first { 2182 putitem(wsets[v].pitem, noset) 2183 } 2184 } 2185 temp1[c] = state(c) 2186 } else if c > NTBASE { 2187 c -= NTBASE 2188 if temp1[c+ntokens] == 0 { 2189 temp1[c+ntokens] = amem[indgo[i]+c] 2190 } 2191 } 2192 } 2193 if i == 1 { 2194 temp1[1] = ACCEPTCODE 2195 } 2196 2197 // now, we have the shifts; look at the reductions 2198 lastred = 0 2199 for u = 0; u < cwp; u++ { 2200 c = wsets[u].pitem.first 2201 2202 // reduction 2203 if c > 0 { 2204 continue 2205 } 2206 lastred = -c 2207 us := wsets[u].ws 2208 for k := 0; k <= ntokens; k++ { 2209 if bitset(us, k) == 0 { 2210 continue 2211 } 2212 if temp1[k] == 0 { 2213 temp1[k] = c 2214 } else if temp1[k] < 0 { // reduce/reduce conflict 2215 if foutput != nil { 2216 fmt.Fprintf(foutput, 2217 "\n %v: reduce/reduce conflict (red'ns "+ 2218 "%v and %v) on %v", 2219 i, -temp1[k], lastred, symnam(k)) 2220 } 2221 if -temp1[k] > lastred { 2222 temp1[k] = -lastred 2223 } 2224 zzrrconf++ 2225 } else { 2226 // potential shift/reduce conflict 2227 precftn(lastred, k, i) 2228 } 2229 } 2230 } 2231 wract(i) 2232 } 2233 2234 fmt.Fprintf(ftable, "}\n") 2235 ftable.WriteRune('\n') 2236 fmt.Fprintf(ftable, "const %sPrivate = %v\n", prefix, PRIVATE) 2237 } 2238 2239 // 2240 // decide a shift/reduce conflict by precedence. 2241 // r is a rule number, t a token number 2242 // the conflict is in state s 2243 // temp1[t] is changed to reflect the action 2244 // 2245 func precftn(r, t, s int) { 2246 action := NOASC 2247 2248 lp := levprd[r] 2249 lt := toklev[t] 2250 if PLEVEL(lt) == 0 || PLEVEL(lp) == 0 { 2251 // conflict 2252 if foutput != nil { 2253 fmt.Fprintf(foutput, 2254 "\n%v: shift/reduce conflict (shift %v(%v), red'n %v(%v)) on %v", 2255 s, temp1[t], PLEVEL(lt), r, PLEVEL(lp), symnam(t)) 2256 } 2257 zzsrconf++ 2258 return 2259 } 2260 if PLEVEL(lt) == PLEVEL(lp) { 2261 action = ASSOC(lt) 2262 } else if PLEVEL(lt) > PLEVEL(lp) { 2263 action = RASC // shift 2264 } else { 2265 action = LASC 2266 } // reduce 2267 switch action { 2268 case BASC: // error action 2269 temp1[t] = ERRCODE 2270 case LASC: // reduce 2271 temp1[t] = -r 2272 } 2273 } 2274 2275 // 2276 // output state i 2277 // temp1 has the actions, lastred the default 2278 // 2279 func wract(i int) { 2280 var p, p1 int 2281 2282 // find the best choice for lastred 2283 lastred = 0 2284 ntimes := 0 2285 for j := 0; j <= ntokens; j++ { 2286 if temp1[j] >= 0 { 2287 continue 2288 } 2289 if temp1[j]+lastred == 0 { 2290 continue 2291 } 2292 // count the number of appearances of temp1[j] 2293 count := 0 2294 tred := -temp1[j] 2295 levprd[tred] |= REDFLAG 2296 for p = 0; p <= ntokens; p++ { 2297 if temp1[p]+tred == 0 { 2298 count++ 2299 } 2300 } 2301 if count > ntimes { 2302 lastred = tred 2303 ntimes = count 2304 } 2305 } 2306 2307 // 2308 // for error recovery, arrange that, if there is a shift on the 2309 // error recovery token, `error', that the default be the error action 2310 // 2311 if temp1[2] > 0 { 2312 lastred = 0 2313 } 2314 2315 // clear out entries in temp1 which equal lastred 2316 // count entries in optst table 2317 n := 0 2318 for p = 0; p <= ntokens; p++ { 2319 p1 = temp1[p] 2320 if p1+lastred == 0 { 2321 temp1[p] = 0 2322 p1 = 0 2323 } 2324 if p1 > 0 && p1 != ACCEPTCODE && p1 != ERRCODE { 2325 n++ 2326 } 2327 } 2328 2329 wrstate(i) 2330 defact[i] = lastred 2331 flag := 0 2332 os := make([]int, n*2) 2333 n = 0 2334 for p = 0; p <= ntokens; p++ { 2335 p1 = temp1[p] 2336 if p1 != 0 { 2337 if p1 < 0 { 2338 p1 = -p1 2339 } else if p1 == ACCEPTCODE { 2340 p1 = -1 2341 } else if p1 == ERRCODE { 2342 p1 = 0 2343 } else { 2344 os[n] = p 2345 n++ 2346 os[n] = p1 2347 n++ 2348 zzacent++ 2349 continue 2350 } 2351 if flag == 0 { 2352 fmt.Fprintf(ftable, "\t-1, %v,\n", i) 2353 } 2354 flag++ 2355 fmt.Fprintf(ftable, "\t%v, %v,\n", p, p1) 2356 zzexcp++ 2357 } 2358 } 2359 if flag != 0 { 2360 defact[i] = -2 2361 fmt.Fprintf(ftable, "\t-2, %v,\n", lastred) 2362 } 2363 optst[i] = os 2364 } 2365 2366 // 2367 // writes state i 2368 // 2369 func wrstate(i int) { 2370 var j0, j1, u int 2371 var pp, qq int 2372 2373 if len(errors) > 0 { 2374 actions := append([]int(nil), temp1...) 2375 defaultAction := ERRCODE 2376 if lastred != 0 { 2377 defaultAction = -lastred 2378 } 2379 stateTable[i] = Row{actions, defaultAction} 2380 } 2381 2382 if foutput == nil { 2383 return 2384 } 2385 fmt.Fprintf(foutput, "\nstate %v\n", i) 2386 qq = pstate[i+1] 2387 for pp = pstate[i]; pp < qq; pp++ { 2388 fmt.Fprintf(foutput, "\t%v\n", writem(statemem[pp].pitem)) 2389 } 2390 if tystate[i] == MUSTLOOKAHEAD { 2391 // print out empty productions in closure 2392 for u = pstate[i+1] - pstate[i]; u < cwp; u++ { 2393 if wsets[u].pitem.first < 0 { 2394 fmt.Fprintf(foutput, "\t%v\n", writem(wsets[u].pitem)) 2395 } 2396 } 2397 } 2398 2399 // check for state equal to another 2400 for j0 = 0; j0 <= ntokens; j0++ { 2401 j1 = temp1[j0] 2402 if j1 != 0 { 2403 fmt.Fprintf(foutput, "\n\t%v ", symnam(j0)) 2404 2405 // shift, error, or accept 2406 if j1 > 0 { 2407 if j1 == ACCEPTCODE { 2408 fmt.Fprintf(foutput, "accept") 2409 } else if j1 == ERRCODE { 2410 fmt.Fprintf(foutput, "error") 2411 } else { 2412 fmt.Fprintf(foutput, "shift %v", j1) 2413 } 2414 } else { 2415 fmt.Fprintf(foutput, "reduce %v (src line %v)", -j1, rlines[-j1]) 2416 } 2417 } 2418 } 2419 2420 // output the final production 2421 if lastred != 0 { 2422 fmt.Fprintf(foutput, "\n\t. reduce %v (src line %v)\n\n", 2423 lastred, rlines[lastred]) 2424 } else { 2425 fmt.Fprintf(foutput, "\n\t. error\n\n") 2426 } 2427 2428 // now, output nonterminal actions 2429 j1 = ntokens 2430 for j0 = 1; j0 <= nnonter; j0++ { 2431 j1++ 2432 if temp1[j1] != 0 { 2433 fmt.Fprintf(foutput, "\t%v goto %v\n", symnam(j0+NTBASE), temp1[j1]) 2434 } 2435 } 2436 } 2437 2438 // 2439 // output the gotos for the nontermninals 2440 // 2441 func go2out() { 2442 for i := 1; i <= nnonter; i++ { 2443 go2gen(i) 2444 2445 // find the best one to make default 2446 best := -1 2447 times := 0 2448 2449 // is j the most frequent 2450 for j := 0; j < nstate; j++ { 2451 if tystate[j] == 0 { 2452 continue 2453 } 2454 if tystate[j] == best { 2455 continue 2456 } 2457 2458 // is tystate[j] the most frequent 2459 count := 0 2460 cbest := tystate[j] 2461 for k := j; k < nstate; k++ { 2462 if tystate[k] == cbest { 2463 count++ 2464 } 2465 } 2466 if count > times { 2467 best = cbest 2468 times = count 2469 } 2470 } 2471 2472 // best is now the default entry 2473 zzgobest += times - 1 2474 n := 0 2475 for j := 0; j < nstate; j++ { 2476 if tystate[j] != 0 && tystate[j] != best { 2477 n++ 2478 } 2479 } 2480 goent := make([]int, 2*n+1) 2481 n = 0 2482 for j := 0; j < nstate; j++ { 2483 if tystate[j] != 0 && tystate[j] != best { 2484 goent[n] = j 2485 n++ 2486 goent[n] = tystate[j] 2487 n++ 2488 zzgoent++ 2489 } 2490 } 2491 2492 // now, the default 2493 if best == -1 { 2494 best = 0 2495 } 2496 2497 zzgoent++ 2498 goent[n] = best 2499 yypgo[i] = goent 2500 } 2501 } 2502 2503 // 2504 // output the gotos for nonterminal c 2505 // 2506 func go2gen(c int) { 2507 var i, cc, p, q int 2508 2509 // first, find nonterminals with gotos on c 2510 aryfil(temp1, nnonter+1, 0) 2511 temp1[c] = 1 2512 work := 1 2513 for work != 0 { 2514 work = 0 2515 for i = 0; i < nprod; i++ { 2516 // cc is a nonterminal with a goto on c 2517 cc = prdptr[i][1] - NTBASE 2518 if cc >= 0 && temp1[cc] != 0 { 2519 // thus, the left side of production i does too 2520 cc = prdptr[i][0] - NTBASE 2521 if temp1[cc] == 0 { 2522 work = 1 2523 temp1[cc] = 1 2524 } 2525 } 2526 } 2527 } 2528 2529 // now, we have temp1[c] = 1 if a goto on c in closure of cc 2530 if g2debug != 0 && foutput != nil { 2531 fmt.Fprintf(foutput, "%v: gotos on ", nontrst[c].name) 2532 for i = 0; i <= nnonter; i++ { 2533 if temp1[i] != 0 { 2534 fmt.Fprintf(foutput, "%v ", nontrst[i].name) 2535 } 2536 } 2537 fmt.Fprintf(foutput, "\n") 2538 } 2539 2540 // now, go through and put gotos into tystate 2541 aryfil(tystate, nstate, 0) 2542 for i = 0; i < nstate; i++ { 2543 q = pstate[i+1] 2544 for p = pstate[i]; p < q; p++ { 2545 cc = statemem[p].pitem.first 2546 if cc >= NTBASE { 2547 // goto on c is possible 2548 if temp1[cc-NTBASE] != 0 { 2549 tystate[i] = amem[indgo[i]+c] 2550 break 2551 } 2552 } 2553 } 2554 } 2555 } 2556 2557 // 2558 // in order to free up the mem and amem arrays for the optimizer, 2559 // and still be able to output yyr1, etc., after the sizes of 2560 // the action array is known, we hide the nonterminals 2561 // derived by productions in levprd. 2562 // 2563 func hideprod() { 2564 nred := 0 2565 levprd[0] = 0 2566 for i := 1; i < nprod; i++ { 2567 if (levprd[i] & REDFLAG) == 0 { 2568 if foutput != nil { 2569 fmt.Fprintf(foutput, "Rule not reduced: %v\n", 2570 writem(Pitem{prdptr[i], 0, 0, i})) 2571 } 2572 fmt.Printf("rule %v never reduced\n", writem(Pitem{prdptr[i], 0, 0, i})) 2573 nred++ 2574 } 2575 levprd[i] = prdptr[i][0] - NTBASE 2576 } 2577 if nred != 0 { 2578 fmt.Printf("%v rules never reduced\n", nred) 2579 } 2580 } 2581 2582 func callopt() { 2583 var j, k, p, q, i int 2584 var v []int 2585 2586 pgo = make([]int, nnonter+1) 2587 pgo[0] = 0 2588 maxoff = 0 2589 maxspr = 0 2590 for i = 0; i < nstate; i++ { 2591 k = 32000 2592 j = 0 2593 v = optst[i] 2594 q = len(v) 2595 for p = 0; p < q; p += 2 { 2596 if v[p] > j { 2597 j = v[p] 2598 } 2599 if v[p] < k { 2600 k = v[p] 2601 } 2602 } 2603 2604 // nontrivial situation 2605 if k <= j { 2606 // j is now the range 2607 // j -= k; // call scj 2608 if k > maxoff { 2609 maxoff = k 2610 } 2611 } 2612 tystate[i] = q + 2*j 2613 if j > maxspr { 2614 maxspr = j 2615 } 2616 } 2617 2618 // initialize ggreed table 2619 ggreed = make([]int, nnonter+1) 2620 for i = 1; i <= nnonter; i++ { 2621 ggreed[i] = 1 2622 j = 0 2623 2624 // minimum entry index is always 0 2625 v = yypgo[i] 2626 q = len(v) - 1 2627 for p = 0; p < q; p += 2 { 2628 ggreed[i] += 2 2629 if v[p] > j { 2630 j = v[p] 2631 } 2632 } 2633 ggreed[i] = ggreed[i] + 2*j 2634 if j > maxoff { 2635 maxoff = j 2636 } 2637 } 2638 2639 // now, prepare to put the shift actions into the amem array 2640 for i = 0; i < ACTSIZE; i++ { 2641 amem[i] = 0 2642 } 2643 maxa = 0 2644 for i = 0; i < nstate; i++ { 2645 if tystate[i] == 0 && adb > 1 { 2646 fmt.Fprintf(ftable, "State %v: null\n", i) 2647 } 2648 indgo[i] = yyFlag 2649 } 2650 2651 i = nxti() 2652 for i != NOMORE { 2653 if i >= 0 { 2654 stin(i) 2655 } else { 2656 gin(-i) 2657 } 2658 i = nxti() 2659 } 2660 2661 // print amem array 2662 if adb > 2 { 2663 for p = 0; p <= maxa; p += 10 { 2664 fmt.Fprintf(ftable, "%v ", p) 2665 for i = 0; i < 10; i++ { 2666 fmt.Fprintf(ftable, "%v ", amem[p+i]) 2667 } 2668 ftable.WriteRune('\n') 2669 } 2670 } 2671 2672 aoutput() 2673 osummary() 2674 } 2675 2676 // 2677 // finds the next i 2678 // 2679 func nxti() int { 2680 max := 0 2681 maxi := 0 2682 for i := 1; i <= nnonter; i++ { 2683 if ggreed[i] >= max { 2684 max = ggreed[i] 2685 maxi = -i 2686 } 2687 } 2688 for i := 0; i < nstate; i++ { 2689 if tystate[i] >= max { 2690 max = tystate[i] 2691 maxi = i 2692 } 2693 } 2694 if max == 0 { 2695 return NOMORE 2696 } 2697 return maxi 2698 } 2699 2700 func gin(i int) { 2701 var s int 2702 2703 // enter gotos on nonterminal i into array amem 2704 ggreed[i] = 0 2705 2706 q := yypgo[i] 2707 nq := len(q) - 1 2708 2709 // now, find amem place for it 2710 nextgp: 2711 for p := 0; p < ACTSIZE; p++ { 2712 if amem[p] != 0 { 2713 continue 2714 } 2715 for r := 0; r < nq; r += 2 { 2716 s = p + q[r] + 1 2717 if s > maxa { 2718 maxa = s 2719 if maxa >= ACTSIZE { 2720 errorf("a array overflow") 2721 } 2722 } 2723 if amem[s] != 0 { 2724 continue nextgp 2725 } 2726 } 2727 2728 // we have found amem spot 2729 amem[p] = q[nq] 2730 if p > maxa { 2731 maxa = p 2732 } 2733 for r := 0; r < nq; r += 2 { 2734 s = p + q[r] + 1 2735 amem[s] = q[r+1] 2736 } 2737 pgo[i] = p 2738 if adb > 1 { 2739 fmt.Fprintf(ftable, "Nonterminal %v, entry at %v\n", i, pgo[i]) 2740 } 2741 return 2742 } 2743 errorf("cannot place goto %v\n", i) 2744 } 2745 2746 func stin(i int) { 2747 var s int 2748 2749 tystate[i] = 0 2750 2751 // enter state i into the amem array 2752 q := optst[i] 2753 nq := len(q) 2754 2755 nextn: 2756 // find an acceptable place 2757 for n := -maxoff; n < ACTSIZE; n++ { 2758 flag := 0 2759 for r := 0; r < nq; r += 2 { 2760 s = q[r] + n 2761 if s < 0 || s > ACTSIZE { 2762 continue nextn 2763 } 2764 if amem[s] == 0 { 2765 flag++ 2766 } else if amem[s] != q[r+1] { 2767 continue nextn 2768 } 2769 } 2770 2771 // check the position equals another only if the states are identical 2772 for j := 0; j < nstate; j++ { 2773 if indgo[j] == n { 2774 2775 // we have some disagreement 2776 if flag != 0 { 2777 continue nextn 2778 } 2779 if nq == len(optst[j]) { 2780 2781 // states are equal 2782 indgo[i] = n 2783 if adb > 1 { 2784 fmt.Fprintf(ftable, "State %v: entry at"+ 2785 "%v equals state %v\n", 2786 i, n, j) 2787 } 2788 return 2789 } 2790 2791 // we have some disagreement 2792 continue nextn 2793 } 2794 } 2795 2796 for r := 0; r < nq; r += 2 { 2797 s = q[r] + n 2798 if s > maxa { 2799 maxa = s 2800 } 2801 if amem[s] != 0 && amem[s] != q[r+1] { 2802 errorf("clobber of a array, pos'n %v, by %v", s, q[r+1]) 2803 } 2804 amem[s] = q[r+1] 2805 } 2806 indgo[i] = n 2807 if adb > 1 { 2808 fmt.Fprintf(ftable, "State %v: entry at %v\n", i, indgo[i]) 2809 } 2810 return 2811 } 2812 errorf("Error; failure to place state %v", i) 2813 } 2814 2815 // 2816 // this version is for limbo 2817 // write out the optimized parser 2818 // 2819 func aoutput() { 2820 ftable.WriteRune('\n') 2821 fmt.Fprintf(ftable, "const %sLast = %v\n\n", prefix, maxa+1) 2822 arout("Act", amem, maxa+1) 2823 arout("Pact", indgo, nstate) 2824 arout("Pgo", pgo, nnonter+1) 2825 } 2826 2827 // 2828 // put out other arrays, copy the parsers 2829 // 2830 func others() { 2831 var i, j int 2832 2833 arout("R1", levprd, nprod) 2834 aryfil(temp1, nprod, 0) 2835 2836 // 2837 //yyr2 is the number of rules for each production 2838 // 2839 for i = 1; i < nprod; i++ { 2840 temp1[i] = len(prdptr[i]) - 2 2841 } 2842 arout("R2", temp1, nprod) 2843 2844 aryfil(temp1, nstate, -1000) 2845 for i = 0; i <= ntokens; i++ { 2846 for j := tstates[i]; j != 0; j = mstates[j] { 2847 temp1[j] = i 2848 } 2849 } 2850 for i = 0; i <= nnonter; i++ { 2851 for j = ntstates[i]; j != 0; j = mstates[j] { 2852 temp1[j] = -i 2853 } 2854 } 2855 arout("Chk", temp1, nstate) 2856 arout("Def", defact, nstate) 2857 2858 // put out token translation tables 2859 // table 1 has 0-256 2860 aryfil(temp1, 256, 0) 2861 c := 0 2862 for i = 1; i <= ntokens; i++ { 2863 j = tokset[i].value 2864 if j >= 0 && j < 256 { 2865 if temp1[j] != 0 { 2866 fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n") 2867 fmt.Printf(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name) 2868 nerrors++ 2869 } 2870 temp1[j] = i 2871 if j > c { 2872 c = j 2873 } 2874 } 2875 } 2876 for i = 0; i <= c; i++ { 2877 if temp1[i] == 0 { 2878 temp1[i] = YYLEXUNK 2879 } 2880 } 2881 arout("Tok1", temp1, c+1) 2882 2883 // table 2 has PRIVATE-PRIVATE+256 2884 aryfil(temp1, 256, 0) 2885 c = 0 2886 for i = 1; i <= ntokens; i++ { 2887 j = tokset[i].value - PRIVATE 2888 if j >= 0 && j < 256 { 2889 if temp1[j] != 0 { 2890 fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n") 2891 fmt.Printf(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name) 2892 nerrors++ 2893 } 2894 temp1[j] = i 2895 if j > c { 2896 c = j 2897 } 2898 } 2899 } 2900 arout("Tok2", temp1, c+1) 2901 2902 // table 3 has everything else 2903 fmt.Fprintf(ftable, "var %sTok3 = [...]int{\n\t", prefix) 2904 c = 0 2905 for i = 1; i <= ntokens; i++ { 2906 j = tokset[i].value 2907 if j >= 0 && j < 256 { 2908 continue 2909 } 2910 if j >= PRIVATE && j < 256+PRIVATE { 2911 continue 2912 } 2913 2914 if c%5 != 0 { 2915 ftable.WriteRune(' ') 2916 } 2917 fmt.Fprintf(ftable, "%d, %d,", j, i) 2918 c++ 2919 if c%5 == 0 { 2920 fmt.Fprint(ftable, "\n\t") 2921 } 2922 } 2923 if c%5 != 0 { 2924 ftable.WriteRune(' ') 2925 } 2926 fmt.Fprintf(ftable, "%d,\n}\n", 0) 2927 2928 // Custom error messages. 2929 fmt.Fprintf(ftable, "\n") 2930 fmt.Fprintf(ftable, "var %sErrorMessages = [...]struct {\n", prefix) 2931 fmt.Fprintf(ftable, "\tstate int\n") 2932 fmt.Fprintf(ftable, "\ttoken int\n") 2933 fmt.Fprintf(ftable, "\tmsg string\n") 2934 fmt.Fprintf(ftable, "}{\n") 2935 for _, error := range errors { 2936 lineno = error.lineno 2937 state, token := runMachine(error.tokens) 2938 fmt.Fprintf(ftable, "\t{%v, %v, %s},\n", state, token, error.msg) 2939 } 2940 fmt.Fprintf(ftable, "}\n") 2941 2942 // copy parser text 2943 ch := getrune(finput) 2944 for ch != EOF { 2945 ftable.WriteRune(ch) 2946 ch = getrune(finput) 2947 } 2948 2949 // copy yaccpar 2950 if !lflag { 2951 fmt.Fprintf(ftable, "\n//line yaccpar:1\n") 2952 } 2953 2954 parts := strings.SplitN(yaccpar, prefix+"run()", 2) 2955 fmt.Fprintf(ftable, "%v", parts[0]) 2956 ftable.Write(fcode.Bytes()) 2957 fmt.Fprintf(ftable, "%v", parts[1]) 2958 } 2959 2960 func runMachine(tokens []string) (state, token int) { 2961 var stack []int 2962 i := 0 2963 token = -1 2964 2965 Loop: 2966 if token < 0 { 2967 token = chfind(2, tokens[i]) 2968 i++ 2969 } 2970 2971 row := stateTable[state] 2972 2973 c := token 2974 if token >= NTBASE { 2975 c = token - NTBASE + ntokens 2976 } 2977 action := row.actions[c] 2978 if action == 0 { 2979 action = row.defaultAction 2980 } 2981 2982 switch { 2983 case action == ACCEPTCODE: 2984 errorf("tokens are accepted") 2985 return 2986 case action == ERRCODE: 2987 if token >= NTBASE { 2988 errorf("error at non-terminal token %s", symnam(token)) 2989 } 2990 return 2991 case action > 0: 2992 // Shift to state action. 2993 stack = append(stack, state) 2994 state = action 2995 token = -1 2996 goto Loop 2997 default: 2998 // Reduce by production -action. 2999 prod := prdptr[-action] 3000 if rhsLen := len(prod) - 2; rhsLen > 0 { 3001 n := len(stack) - rhsLen 3002 state = stack[n] 3003 stack = stack[:n] 3004 } 3005 if token >= 0 { 3006 i-- 3007 } 3008 token = prod[0] 3009 goto Loop 3010 } 3011 } 3012 3013 func arout(s string, v []int, n int) { 3014 s = prefix + s 3015 fmt.Fprintf(ftable, "var %v = [...]int{\n", s) 3016 for i := 0; i < n; i++ { 3017 if i%10 == 0 { 3018 fmt.Fprintf(ftable, "\n\t") 3019 } else { 3020 ftable.WriteRune(' ') 3021 } 3022 fmt.Fprintf(ftable, "%d,", v[i]) 3023 } 3024 fmt.Fprintf(ftable, "\n}\n") 3025 } 3026 3027 // 3028 // output the summary on y.output 3029 // 3030 func summary() { 3031 if foutput != nil { 3032 fmt.Fprintf(foutput, "\n%v terminals, %v nonterminals\n", ntokens, nnonter+1) 3033 fmt.Fprintf(foutput, "%v grammar rules, %v/%v states\n", nprod, nstate, NSTATES) 3034 fmt.Fprintf(foutput, "%v shift/reduce, %v reduce/reduce conflicts reported\n", zzsrconf, zzrrconf) 3035 fmt.Fprintf(foutput, "%v working sets used\n", len(wsets)) 3036 fmt.Fprintf(foutput, "memory: parser %v/%v\n", memp, ACTSIZE) 3037 fmt.Fprintf(foutput, "%v extra closures\n", zzclose-2*nstate) 3038 fmt.Fprintf(foutput, "%v shift entries, %v exceptions\n", zzacent, zzexcp) 3039 fmt.Fprintf(foutput, "%v goto entries\n", zzgoent) 3040 fmt.Fprintf(foutput, "%v entries saved by goto default\n", zzgobest) 3041 } 3042 if zzsrconf != 0 || zzrrconf != 0 { 3043 fmt.Printf("\nconflicts: ") 3044 if zzsrconf != 0 { 3045 fmt.Printf("%v shift/reduce", zzsrconf) 3046 } 3047 if zzsrconf != 0 && zzrrconf != 0 { 3048 fmt.Printf(", ") 3049 } 3050 if zzrrconf != 0 { 3051 fmt.Printf("%v reduce/reduce", zzrrconf) 3052 } 3053 fmt.Printf("\n") 3054 } 3055 } 3056 3057 // 3058 // write optimizer summary 3059 // 3060 func osummary() { 3061 if foutput == nil { 3062 return 3063 } 3064 i := 0 3065 for p := maxa; p >= 0; p-- { 3066 if amem[p] == 0 { 3067 i++ 3068 } 3069 } 3070 3071 fmt.Fprintf(foutput, "Optimizer space used: output %v/%v\n", maxa+1, ACTSIZE) 3072 fmt.Fprintf(foutput, "%v table entries, %v zero\n", maxa+1, i) 3073 fmt.Fprintf(foutput, "maximum spread: %v, maximum offset: %v\n", maxspr, maxoff) 3074 } 3075 3076 // 3077 // copies and protects "'s in q 3078 // 3079 func chcopy(q string) string { 3080 s := "" 3081 i := 0 3082 j := 0 3083 for i = 0; i < len(q); i++ { 3084 if q[i] == '"' { 3085 s += q[j:i] + "\\" 3086 j = i 3087 } 3088 } 3089 return s + q[j:i] 3090 } 3091 3092 func usage() { 3093 fmt.Fprintf(stderr, "usage: yacc [-o output] [-v parsetable] input\n") 3094 exit(1) 3095 } 3096 3097 func bitset(set Lkset, bit int) int { return set[bit>>5] & (1 << uint(bit&31)) } 3098 3099 func setbit(set Lkset, bit int) { set[bit>>5] |= (1 << uint(bit&31)) } 3100 3101 func mkset() Lkset { return make([]int, tbitset) } 3102 3103 // 3104 // set a to the union of a and b 3105 // return 1 if b is not a subset of a, 0 otherwise 3106 // 3107 func setunion(a, b []int) int { 3108 sub := 0 3109 for i := 0; i < tbitset; i++ { 3110 x := a[i] 3111 y := x | b[i] 3112 a[i] = y 3113 if y != x { 3114 sub = 1 3115 } 3116 } 3117 return sub 3118 } 3119 3120 func prlook(p Lkset) { 3121 if p == nil { 3122 fmt.Fprintf(foutput, "\tNULL") 3123 return 3124 } 3125 fmt.Fprintf(foutput, " { ") 3126 for j := 0; j <= ntokens; j++ { 3127 if bitset(p, j) != 0 { 3128 fmt.Fprintf(foutput, "%v ", symnam(j)) 3129 } 3130 } 3131 fmt.Fprintf(foutput, "}") 3132 } 3133 3134 // 3135 // utility routines 3136 // 3137 var peekrune rune 3138 3139 func isdigit(c rune) bool { return c >= '0' && c <= '9' } 3140 3141 func isword(c rune) bool { 3142 return c >= 0xa0 || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') 3143 } 3144 3145 // 3146 // return 1 if 2 arrays are equal 3147 // return 0 if not equal 3148 // 3149 func aryeq(a []int, b []int) int { 3150 n := len(a) 3151 if len(b) != n { 3152 return 0 3153 } 3154 for ll := 0; ll < n; ll++ { 3155 if a[ll] != b[ll] { 3156 return 0 3157 } 3158 } 3159 return 1 3160 } 3161 3162 func getrune(f *bufio.Reader) rune { 3163 var r rune 3164 3165 if peekrune != 0 { 3166 if peekrune == EOF { 3167 return EOF 3168 } 3169 r = peekrune 3170 peekrune = 0 3171 return r 3172 } 3173 3174 c, n, err := f.ReadRune() 3175 if n == 0 { 3176 return EOF 3177 } 3178 if err != nil { 3179 errorf("read error: %v", err) 3180 } 3181 //fmt.Printf("rune = %v n=%v\n", string(c), n); 3182 return c 3183 } 3184 3185 func ungetrune(f *bufio.Reader, c rune) { 3186 if f != finput { 3187 panic("ungetc - not finput") 3188 } 3189 if peekrune != 0 { 3190 panic("ungetc - 2nd unget") 3191 } 3192 peekrune = c 3193 } 3194 3195 func open(s string) *bufio.Reader { 3196 fi, err := os.Open(s) 3197 if err != nil { 3198 errorf("error opening %v: %v", s, err) 3199 } 3200 //fmt.Printf("open %v\n", s); 3201 return bufio.NewReader(fi) 3202 } 3203 3204 func create(s string) *bufio.Writer { 3205 fo, err := os.Create(s) 3206 if err != nil { 3207 errorf("error creating %v: %v", s, err) 3208 } 3209 //fmt.Printf("create %v mode %v\n", s); 3210 return bufio.NewWriter(fo) 3211 } 3212 3213 // 3214 // write out error comment 3215 // 3216 func lerrorf(lineno int, s string, v ...interface{}) { 3217 nerrors++ 3218 fmt.Fprintf(stderr, s, v...) 3219 fmt.Fprintf(stderr, ": %v:%v\n", infile, lineno) 3220 if fatfl != 0 { 3221 summary() 3222 exit(1) 3223 } 3224 } 3225 3226 func errorf(s string, v ...interface{}) { 3227 lerrorf(lineno, s, v...) 3228 } 3229 3230 func exit(status int) { 3231 if ftable != nil { 3232 ftable.Flush() 3233 ftable = nil 3234 gofmt() 3235 } 3236 if foutput != nil { 3237 foutput.Flush() 3238 foutput = nil 3239 } 3240 if stderr != nil { 3241 stderr.Flush() 3242 stderr = nil 3243 } 3244 os.Exit(status) 3245 } 3246 3247 func gofmt() { 3248 src, err := ioutil.ReadFile(oflag) 3249 if err != nil { 3250 return 3251 } 3252 src, err = format.Source(src) 3253 if err != nil { 3254 return 3255 } 3256 ioutil.WriteFile(oflag, src, 0666) 3257 } 3258 3259 var yaccpar string // will be processed version of yaccpartext: s/$$/prefix/g 3260 var yaccpartext = ` 3261 /* parser for yacc output */ 3262 3263 var ( 3264 $$Debug = 0 3265 $$ErrorVerbose = false 3266 ) 3267 3268 type $$Lexer interface { 3269 Lex(lval *$$SymType) int 3270 Error(s string) 3271 } 3272 3273 type $$Parser interface { 3274 Parse($$Lexer) int 3275 Lookahead() int 3276 } 3277 3278 type $$ParserImpl struct { 3279 lval $$SymType 3280 stack [$$InitialStackSize]$$SymType 3281 char int 3282 } 3283 3284 func (p *$$ParserImpl) Lookahead() int { 3285 return p.char 3286 } 3287 3288 func $$NewParser() $$Parser { 3289 return &$$ParserImpl{} 3290 } 3291 3292 const $$Flag = -1000 3293 3294 func $$Tokname(c int) string { 3295 if c >= 1 && c-1 < len($$Toknames) { 3296 if $$Toknames[c-1] != "" { 3297 return $$Toknames[c-1] 3298 } 3299 } 3300 return __yyfmt__.Sprintf("tok-%v", c) 3301 } 3302 3303 func $$Statname(s int) string { 3304 if s >= 0 && s < len($$Statenames) { 3305 if $$Statenames[s] != "" { 3306 return $$Statenames[s] 3307 } 3308 } 3309 return __yyfmt__.Sprintf("state-%v", s) 3310 } 3311 3312 func $$ErrorMessage(state, lookAhead int) string { 3313 const TOKSTART = 4 3314 3315 if !$$ErrorVerbose { 3316 return "syntax error" 3317 } 3318 3319 for _, e := range $$ErrorMessages { 3320 if e.state == state && e.token == lookAhead { 3321 return "syntax error: " + e.msg 3322 } 3323 } 3324 3325 res := "syntax error: unexpected " + $$Tokname(lookAhead) 3326 3327 // To match Bison, suggest at most four expected tokens. 3328 expected := make([]int, 0, 4) 3329 3330 // Look for shiftable tokens. 3331 base := $$Pact[state] 3332 for tok := TOKSTART; tok-1 < len($$Toknames); tok++ { 3333 if n := base + tok; n >= 0 && n < $$Last && $$Chk[$$Act[n]] == tok { 3334 if len(expected) == cap(expected) { 3335 return res 3336 } 3337 expected = append(expected, tok) 3338 } 3339 } 3340 3341 if $$Def[state] == -2 { 3342 i := 0 3343 for $$Exca[i] != -1 || $$Exca[i+1] != state { 3344 i += 2 3345 } 3346 3347 // Look for tokens that we accept or reduce. 3348 for i += 2; $$Exca[i] >= 0; i += 2 { 3349 tok := $$Exca[i] 3350 if tok < TOKSTART || $$Exca[i+1] == 0 { 3351 continue 3352 } 3353 if len(expected) == cap(expected) { 3354 return res 3355 } 3356 expected = append(expected, tok) 3357 } 3358 3359 // If the default action is to accept or reduce, give up. 3360 if $$Exca[i+1] != 0 { 3361 return res 3362 } 3363 } 3364 3365 for i, tok := range expected { 3366 if i == 0 { 3367 res += ", expecting " 3368 } else { 3369 res += " or " 3370 } 3371 res += $$Tokname(tok) 3372 } 3373 return res 3374 } 3375 3376 func $$lex1(lex $$Lexer, lval *$$SymType) (char, token int) { 3377 token = 0 3378 char = lex.Lex(lval) 3379 if char <= 0 { 3380 token = $$Tok1[0] 3381 goto out 3382 } 3383 if char < len($$Tok1) { 3384 token = $$Tok1[char] 3385 goto out 3386 } 3387 if char >= $$Private { 3388 if char < $$Private+len($$Tok2) { 3389 token = $$Tok2[char-$$Private] 3390 goto out 3391 } 3392 } 3393 for i := 0; i < len($$Tok3); i += 2 { 3394 token = $$Tok3[i+0] 3395 if token == char { 3396 token = $$Tok3[i+1] 3397 goto out 3398 } 3399 } 3400 3401 out: 3402 if token == 0 { 3403 token = $$Tok2[1] /* unknown char */ 3404 } 3405 if $$Debug >= 3 { 3406 __yyfmt__.Printf("lex %s(%d)\n", $$Tokname(token), uint(char)) 3407 } 3408 return char, token 3409 } 3410 3411 func $$Parse($$lex $$Lexer) int { 3412 return $$NewParser().Parse($$lex) 3413 } 3414 3415 func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int { 3416 var $$n int 3417 var $$VAL $$SymType 3418 var $$Dollar []$$SymType 3419 _ = $$Dollar // silence set and not used 3420 $$S := $$rcvr.stack[:] 3421 3422 Nerrs := 0 /* number of errors */ 3423 Errflag := 0 /* error recovery flag */ 3424 $$state := 0 3425 $$rcvr.char = -1 3426 $$token := -1 // $$rcvr.char translated into internal numbering 3427 defer func() { 3428 // Make sure we report no lookahead when not parsing. 3429 $$state = -1 3430 $$rcvr.char = -1 3431 $$token = -1 3432 }() 3433 $$p := -1 3434 goto $$stack 3435 3436 ret0: 3437 return 0 3438 3439 ret1: 3440 return 1 3441 3442 $$stack: 3443 /* put a state and value onto the stack */ 3444 if $$Debug >= 4 { 3445 __yyfmt__.Printf("char %v in %v\n", $$Tokname($$token), $$Statname($$state)) 3446 } 3447 3448 $$p++ 3449 if $$p >= len($$S) { 3450 nyys := make([]$$SymType, len($$S)*2) 3451 copy(nyys, $$S) 3452 $$S = nyys 3453 } 3454 $$S[$$p] = $$VAL 3455 $$S[$$p].yys = $$state 3456 3457 $$newstate: 3458 $$n = $$Pact[$$state] 3459 if $$n <= $$Flag { 3460 goto $$default /* simple state */ 3461 } 3462 if $$rcvr.char < 0 { 3463 $$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval) 3464 } 3465 $$n += $$token 3466 if $$n < 0 || $$n >= $$Last { 3467 goto $$default 3468 } 3469 $$n = $$Act[$$n] 3470 if $$Chk[$$n] == $$token { /* valid shift */ 3471 $$rcvr.char = -1 3472 $$token = -1 3473 $$VAL = $$rcvr.lval 3474 $$state = $$n 3475 if Errflag > 0 { 3476 Errflag-- 3477 } 3478 goto $$stack 3479 } 3480 3481 $$default: 3482 /* default state action */ 3483 $$n = $$Def[$$state] 3484 if $$n == -2 { 3485 if $$rcvr.char < 0 { 3486 $$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval) 3487 } 3488 3489 /* look through exception table */ 3490 xi := 0 3491 for { 3492 if $$Exca[xi+0] == -1 && $$Exca[xi+1] == $$state { 3493 break 3494 } 3495 xi += 2 3496 } 3497 for xi += 2; ; xi += 2 { 3498 $$n = $$Exca[xi+0] 3499 if $$n < 0 || $$n == $$token { 3500 break 3501 } 3502 } 3503 $$n = $$Exca[xi+1] 3504 if $$n < 0 { 3505 goto ret0 3506 } 3507 } 3508 if $$n == 0 { 3509 /* error ... attempt to resume parsing */ 3510 switch Errflag { 3511 case 0: /* brand new error */ 3512 $$lex.Error($$ErrorMessage($$state, $$token)) 3513 Nerrs++ 3514 if $$Debug >= 1 { 3515 __yyfmt__.Printf("%s", $$Statname($$state)) 3516 __yyfmt__.Printf(" saw %s\n", $$Tokname($$token)) 3517 } 3518 fallthrough 3519 3520 case 1, 2: /* incompletely recovered error ... try again */ 3521 Errflag = 3 3522 3523 /* find a state where "error" is a legal shift action */ 3524 for $$p >= 0 { 3525 $$n = $$Pact[$$S[$$p].yys] + $$ErrCode 3526 if $$n >= 0 && $$n < $$Last { 3527 $$state = $$Act[$$n] /* simulate a shift of "error" */ 3528 if $$Chk[$$state] == $$ErrCode { 3529 goto $$stack 3530 } 3531 } 3532 3533 /* the current p has no shift on "error", pop stack */ 3534 if $$Debug >= 2 { 3535 __yyfmt__.Printf("error recovery pops state %d\n", $$S[$$p].yys) 3536 } 3537 $$p-- 3538 } 3539 /* there is no state on the stack with an error shift ... abort */ 3540 goto ret1 3541 3542 case 3: /* no shift yet; clobber input char */ 3543 if $$Debug >= 2 { 3544 __yyfmt__.Printf("error recovery discards %s\n", $$Tokname($$token)) 3545 } 3546 if $$token == $$EofCode { 3547 goto ret1 3548 } 3549 $$rcvr.char = -1 3550 $$token = -1 3551 goto $$newstate /* try again in the same state */ 3552 } 3553 } 3554 3555 /* reduction by production $$n */ 3556 if $$Debug >= 2 { 3557 __yyfmt__.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state)) 3558 } 3559 3560 $$nt := $$n 3561 $$pt := $$p 3562 _ = $$pt // guard against "declared and not used" 3563 3564 $$p -= $$R2[$$n] 3565 // $$p is now the index of $0. Perform the default action. Iff the 3566 // reduced production is ε, $1 is possibly out of range. 3567 if $$p+1 >= len($$S) { 3568 nyys := make([]$$SymType, len($$S)*2) 3569 copy(nyys, $$S) 3570 $$S = nyys 3571 } 3572 $$VAL = $$S[$$p+1] 3573 3574 /* consult goto table to find next state */ 3575 $$n = $$R1[$$n] 3576 $$g := $$Pgo[$$n] 3577 $$j := $$g + $$S[$$p].yys + 1 3578 3579 if $$j >= $$Last { 3580 $$state = $$Act[$$g] 3581 } else { 3582 $$state = $$Act[$$j] 3583 if $$Chk[$$state] != -$$n { 3584 $$state = $$Act[$$g] 3585 } 3586 } 3587 // dummy call; replaced with literal code 3588 $$run() 3589 goto $$stack /* stack new state and value */ 3590 } 3591 `