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 (at) 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 (at) 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\n\t\t", infile, lineno) 1288 } 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 func mktemp(t string) string { return t } 3188 3189 // 3190 // return 1 if 2 arrays are equal 3191 // return 0 if not equal 3192 // 3193 func aryeq(a []int, b []int) int { 3194 n := len(a) 3195 if len(b) != n { 3196 return 0 3197 } 3198 for ll := 0; ll < n; ll++ { 3199 if a[ll] != b[ll] { 3200 return 0 3201 } 3202 } 3203 return 1 3204 } 3205 3206 func putrune(f *bufio.Writer, c int) { 3207 s := string(c) 3208 for i := 0; i < len(s); i++ { 3209 f.WriteByte(s[i]) 3210 } 3211 } 3212 3213 func getrune(f *bufio.Reader) rune { 3214 var r rune 3215 3216 if peekrune != 0 { 3217 if peekrune == EOF { 3218 return EOF 3219 } 3220 r = peekrune 3221 peekrune = 0 3222 return r 3223 } 3224 3225 c, n, err := f.ReadRune() 3226 if n == 0 { 3227 return EOF 3228 } 3229 if err != nil { 3230 errorf("read error: %v", err) 3231 } 3232 //fmt.Printf("rune = %v n=%v\n", string(c), n); 3233 return c 3234 } 3235 3236 func ungetrune(f *bufio.Reader, c rune) { 3237 if f != finput { 3238 panic("ungetc - not finput") 3239 } 3240 if peekrune != 0 { 3241 panic("ungetc - 2nd unget") 3242 } 3243 peekrune = c 3244 } 3245 3246 func write(f *bufio.Writer, b []byte, n int) int { 3247 panic("write") 3248 } 3249 3250 func open(s string) *bufio.Reader { 3251 fi, err := os.Open(s) 3252 if err != nil { 3253 errorf("error opening %v: %v", s, err) 3254 } 3255 //fmt.Printf("open %v\n", s); 3256 return bufio.NewReader(fi) 3257 } 3258 3259 func create(s string) *bufio.Writer { 3260 fo, err := os.Create(s) 3261 if err != nil { 3262 errorf("error creating %v: %v", s, err) 3263 } 3264 //fmt.Printf("create %v mode %v\n", s); 3265 return bufio.NewWriter(fo) 3266 } 3267 3268 // 3269 // write out error comment 3270 // 3271 func lerrorf(lineno int, s string, v ...interface{}) { 3272 nerrors++ 3273 fmt.Fprintf(stderr, s, v...) 3274 fmt.Fprintf(stderr, ": %v:%v\n", infile, lineno) 3275 if fatfl != 0 { 3276 summary() 3277 exit(1) 3278 } 3279 } 3280 3281 func errorf(s string, v ...interface{}) { 3282 lerrorf(lineno, s, v...) 3283 } 3284 3285 func exit(status int) { 3286 if ftable != nil { 3287 ftable.Flush() 3288 ftable = nil 3289 gofmt() 3290 } 3291 if foutput != nil { 3292 foutput.Flush() 3293 foutput = nil 3294 } 3295 if stderr != nil { 3296 stderr.Flush() 3297 stderr = nil 3298 } 3299 os.Exit(status) 3300 } 3301 3302 func gofmt() { 3303 src, err := ioutil.ReadFile(oflag) 3304 if err != nil { 3305 return 3306 } 3307 src, err = format.Source(src) 3308 if err != nil { 3309 return 3310 } 3311 ioutil.WriteFile(oflag, src, 0666) 3312 } 3313 3314 var yaccpar string // will be processed version of yaccpartext: s/$$/prefix/g 3315 var yaccpartext = ` 3316 /* parser for yacc output */ 3317 3318 var ( 3319 $$Debug = 0 3320 $$ErrorVerbose = false 3321 ) 3322 3323 type $$Lexer interface { 3324 Lex(lval *$$SymType) int 3325 Error(s string) 3326 } 3327 3328 type $$Parser interface { 3329 Parse($$Lexer) int 3330 Lookahead() int 3331 } 3332 3333 type $$ParserImpl struct { 3334 lookahead func() int 3335 } 3336 3337 func (p *$$ParserImpl) Lookahead() int { 3338 return p.lookahead() 3339 } 3340 3341 func $$NewParser() $$Parser { 3342 p := &$$ParserImpl{ 3343 lookahead: func() int { return -1 }, 3344 } 3345 return p 3346 } 3347 3348 const $$Flag = -1000 3349 3350 func $$Tokname(c int) string { 3351 if c >= 1 && c-1 < len($$Toknames) { 3352 if $$Toknames[c-1] != "" { 3353 return $$Toknames[c-1] 3354 } 3355 } 3356 return __yyfmt__.Sprintf("tok-%v", c) 3357 } 3358 3359 func $$Statname(s int) string { 3360 if s >= 0 && s < len($$Statenames) { 3361 if $$Statenames[s] != "" { 3362 return $$Statenames[s] 3363 } 3364 } 3365 return __yyfmt__.Sprintf("state-%v", s) 3366 } 3367 3368 func $$ErrorMessage(state, lookAhead int) string { 3369 const TOKSTART = 4 3370 3371 if !$$ErrorVerbose { 3372 return "syntax error" 3373 } 3374 3375 for _, e := range $$ErrorMessages { 3376 if e.state == state && e.token == lookAhead { 3377 return "syntax error: " + e.msg 3378 } 3379 } 3380 3381 res := "syntax error: unexpected " + $$Tokname(lookAhead) 3382 3383 // To match Bison, suggest at most four expected tokens. 3384 expected := make([]int, 0, 4) 3385 3386 // Look for shiftable tokens. 3387 base := $$Pact[state] 3388 for tok := TOKSTART; tok-1 < len($$Toknames); tok++ { 3389 if n := base + tok; n >= 0 && n < $$Last && $$Chk[$$Act[n]] == tok { 3390 if len(expected) == cap(expected) { 3391 return res 3392 } 3393 expected = append(expected, tok) 3394 } 3395 } 3396 3397 if $$Def[state] == -2 { 3398 i := 0 3399 for $$Exca[i] != -1 || $$Exca[i+1] != state { 3400 i += 2 3401 } 3402 3403 // Look for tokens that we accept or reduce. 3404 for i += 2; $$Exca[i] >= 0; i += 2 { 3405 tok := $$Exca[i] 3406 if tok < TOKSTART || $$Exca[i+1] == 0 { 3407 continue 3408 } 3409 if len(expected) == cap(expected) { 3410 return res 3411 } 3412 expected = append(expected, tok) 3413 } 3414 3415 // If the default action is to accept or reduce, give up. 3416 if $$Exca[i+1] != 0 { 3417 return res 3418 } 3419 } 3420 3421 for i, tok := range expected { 3422 if i == 0 { 3423 res += ", expecting " 3424 } else { 3425 res += " or " 3426 } 3427 res += $$Tokname(tok) 3428 } 3429 return res 3430 } 3431 3432 func $$lex1(lex $$Lexer, lval *$$SymType) (char, token int) { 3433 token = 0 3434 char = lex.Lex(lval) 3435 if char <= 0 { 3436 token = $$Tok1[0] 3437 goto out 3438 } 3439 if char < len($$Tok1) { 3440 token = $$Tok1[char] 3441 goto out 3442 } 3443 if char >= $$Private { 3444 if char < $$Private+len($$Tok2) { 3445 token = $$Tok2[char-$$Private] 3446 goto out 3447 } 3448 } 3449 for i := 0; i < len($$Tok3); i += 2 { 3450 token = $$Tok3[i+0] 3451 if token == char { 3452 token = $$Tok3[i+1] 3453 goto out 3454 } 3455 } 3456 3457 out: 3458 if token == 0 { 3459 token = $$Tok2[1] /* unknown char */ 3460 } 3461 if $$Debug >= 3 { 3462 __yyfmt__.Printf("lex %s(%d)\n", $$Tokname(token), uint(char)) 3463 } 3464 return char, token 3465 } 3466 3467 func $$Parse($$lex $$Lexer) int { 3468 return $$NewParser().Parse($$lex) 3469 } 3470 3471 func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int { 3472 var $$n int 3473 var $$lval $$SymType 3474 var $$VAL $$SymType 3475 var $$Dollar []$$SymType 3476 _ = $$Dollar // silence set and not used 3477 $$S := make([]$$SymType, $$MaxDepth) 3478 3479 Nerrs := 0 /* number of errors */ 3480 Errflag := 0 /* error recovery flag */ 3481 $$state := 0 3482 $$char := -1 3483 $$token := -1 // $$char translated into internal numbering 3484 $$rcvr.lookahead = func() int { return $$char } 3485 defer func() { 3486 // Make sure we report no lookahead when not parsing. 3487 $$state = -1 3488 $$char = -1 3489 $$token = -1 3490 }() 3491 $$p := -1 3492 goto $$stack 3493 3494 ret0: 3495 return 0 3496 3497 ret1: 3498 return 1 3499 3500 $$stack: 3501 /* put a state and value onto the stack */ 3502 if $$Debug >= 4 { 3503 __yyfmt__.Printf("char %v in %v\n", $$Tokname($$token), $$Statname($$state)) 3504 } 3505 3506 $$p++ 3507 if $$p >= len($$S) { 3508 nyys := make([]$$SymType, len($$S)*2) 3509 copy(nyys, $$S) 3510 $$S = nyys 3511 } 3512 $$S[$$p] = $$VAL 3513 $$S[$$p].yys = $$state 3514 3515 $$newstate: 3516 $$n = $$Pact[$$state] 3517 if $$n <= $$Flag { 3518 goto $$default /* simple state */ 3519 } 3520 if $$char < 0 { 3521 $$char, $$token = $$lex1($$lex, &$$lval) 3522 } 3523 $$n += $$token 3524 if $$n < 0 || $$n >= $$Last { 3525 goto $$default 3526 } 3527 $$n = $$Act[$$n] 3528 if $$Chk[$$n] == $$token { /* valid shift */ 3529 $$char = -1 3530 $$token = -1 3531 $$VAL = $$lval 3532 $$state = $$n 3533 if Errflag > 0 { 3534 Errflag-- 3535 } 3536 goto $$stack 3537 } 3538 3539 $$default: 3540 /* default state action */ 3541 $$n = $$Def[$$state] 3542 if $$n == -2 { 3543 if $$char < 0 { 3544 $$char, $$token = $$lex1($$lex, &$$lval) 3545 } 3546 3547 /* look through exception table */ 3548 xi := 0 3549 for { 3550 if $$Exca[xi+0] == -1 && $$Exca[xi+1] == $$state { 3551 break 3552 } 3553 xi += 2 3554 } 3555 for xi += 2; ; xi += 2 { 3556 $$n = $$Exca[xi+0] 3557 if $$n < 0 || $$n == $$token { 3558 break 3559 } 3560 } 3561 $$n = $$Exca[xi+1] 3562 if $$n < 0 { 3563 goto ret0 3564 } 3565 } 3566 if $$n == 0 { 3567 /* error ... attempt to resume parsing */ 3568 switch Errflag { 3569 case 0: /* brand new error */ 3570 $$lex.Error($$ErrorMessage($$state, $$token)) 3571 Nerrs++ 3572 if $$Debug >= 1 { 3573 __yyfmt__.Printf("%s", $$Statname($$state)) 3574 __yyfmt__.Printf(" saw %s\n", $$Tokname($$token)) 3575 } 3576 fallthrough 3577 3578 case 1, 2: /* incompletely recovered error ... try again */ 3579 Errflag = 3 3580 3581 /* find a state where "error" is a legal shift action */ 3582 for $$p >= 0 { 3583 $$n = $$Pact[$$S[$$p].yys] + $$ErrCode 3584 if $$n >= 0 && $$n < $$Last { 3585 $$state = $$Act[$$n] /* simulate a shift of "error" */ 3586 if $$Chk[$$state] == $$ErrCode { 3587 goto $$stack 3588 } 3589 } 3590 3591 /* the current p has no shift on "error", pop stack */ 3592 if $$Debug >= 2 { 3593 __yyfmt__.Printf("error recovery pops state %d\n", $$S[$$p].yys) 3594 } 3595 $$p-- 3596 } 3597 /* there is no state on the stack with an error shift ... abort */ 3598 goto ret1 3599 3600 case 3: /* no shift yet; clobber input char */ 3601 if $$Debug >= 2 { 3602 __yyfmt__.Printf("error recovery discards %s\n", $$Tokname($$token)) 3603 } 3604 if $$token == $$EofCode { 3605 goto ret1 3606 } 3607 $$char = -1 3608 $$token = -1 3609 goto $$newstate /* try again in the same state */ 3610 } 3611 } 3612 3613 /* reduction by production $$n */ 3614 if $$Debug >= 2 { 3615 __yyfmt__.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state)) 3616 } 3617 3618 $$nt := $$n 3619 $$pt := $$p 3620 _ = $$pt // guard against "declared and not used" 3621 3622 $$p -= $$R2[$$n] 3623 // $$p is now the index of $0. Perform the default action. Iff the 3624 // reduced production is , $1 is possibly out of range. 3625 if $$p+1 >= len($$S) { 3626 nyys := make([]$$SymType, len($$S)*2) 3627 copy(nyys, $$S) 3628 $$S = nyys 3629 } 3630 $$VAL = $$S[$$p+1] 3631 3632 /* consult goto table to find next state */ 3633 $$n = $$R1[$$n] 3634 $$g := $$Pgo[$$n] 3635 $$j := $$g + $$S[$$p].yys + 1 3636 3637 if $$j >= $$Last { 3638 $$state = $$Act[$$g] 3639 } else { 3640 $$state = $$Act[$$j] 3641 if $$Chk[$$state] != -$$n { 3642 $$state = $$Act[$$g] 3643 } 3644 } 3645 // dummy call; replaced with literal code 3646 $$run() 3647 goto $$stack /* stack new state and value */ 3648 } 3649 ` 3650