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