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