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