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