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