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