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