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