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