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