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