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