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