github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/qiuyesuifeng/goyacc/main.go (about) 1 // Copyright 2014 The goyacc Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This source code uses portions of code previously published in the Go tool 6 // yacc[0] program, the respective license can be found in the LICENSE-GO-YACC 7 // file. 8 9 // Goyacc is a version of yacc generating Go parsers. 10 // 11 // Usage 12 // 13 // Note: If no non flag arguments are given, goyacc reads standard input. 14 // 15 // goyacc [options] [input] 16 // 17 // options and (defaults) 18 // -c Report state closures. (false) 19 // -cr Check all states are reducible. (false) 20 // -dlval Debug value when runtime yyDebug >= 3. ("lval") 21 // -dlvalf Debug format of -dlval. ("%+v") 22 // -ex Explain how were conflicts resolved. (false) 23 // -l Disable line directives, for compatibility only - ignored. (false) 24 // -la Report all lookahead sets. (false) 25 // -o outputFile Parser output. ("y.go") 26 // -p prefix Name prefix to use in generated code. ("yy") 27 // -v reportFile Create grammar report. ("y.output") 28 // -xe examplesFile Generate error messages by examples. ("") 29 // -xegen examplesFile Generate a file suitable for -xe automatically from the grammar. 30 // The file must not exist. ("") 31 // 32 // 33 // 34 // Changelog 35 // 36 // 2015-03-24: The search for a custom error message is now extended to include 37 // also the last state that was shifted into, if any. This change resolves a 38 // problem in which a lookahead symbol is valid for a reduce action in state A, 39 // but the same symbol is later never accepted by any shift action in some 40 // state B which is popped from the state stack after the reduction is 41 // performed. The computed from example state is A but when the error is 42 // actually detected, the state is now B and the custom error was thus not 43 // used. 44 // 45 // 2015-02-23: Added -xegen flag. It can be used to automagically generate a 46 // skeleton errors by example file which can be, for example, edited and/or 47 // submited later as an argument of the -xe option. 48 // 49 // 2014-12-18: Support %precedence for better bison compatibility[3]. The 50 // actual changes are in packages goyacc is dependent on. Goyacc users should 51 // rebuild the binary: 52 // 53 // $ go get -u yougam/libraries/cznic/goyacc 54 // 55 // 2014-12-02: Added support for the optional yyLexerEx interface. The Reduced 56 // method can be useful for debugging and/or automatically producing examples 57 // by parsing code fragments. If it returns true the parser exits immediately 58 // with return value -1. 59 // 60 // Overview 61 // 62 // The generated parser is reentrant and mostly backwards compatible with 63 // parsers generated by go tool yacc[0]. yyParse expects to be given an 64 // argument that conforms to the following interface: 65 // 66 // type yyLexer interface { 67 // Lex(lval *yySymType) int 68 // Error(e string) 69 // } 70 // 71 // Optionally the argument to yyParse may implement the following interface: 72 // 73 // type yyLexerEx interface { 74 // yyLexer 75 // // Hook for recording a reduction. 76 // Reduced(rule, state int, lval *yySymType) (stop bool) // Client should copy *lval. 77 // } 78 // 79 // Lex should return the token identifier, and place other token information in 80 // lval (which replaces the usual yylval). Error is equivalent to yyerror in 81 // the original yacc. 82 // 83 // Code inside the parser may refer to the variable yylex, which holds the 84 // yyLexer passed to Parse. 85 // 86 // Multiple grammars compiled into a single program should be placed in 87 // distinct packages. If that is impossible, the "-p prefix" flag to yacc sets 88 // the prefix, by default yy, that begins the names of symbols, including 89 // types, the parser, and the lexer, generated and referenced by yacc's 90 // generated code. Setting it to distinct values allows multiple grammars to be 91 // placed in a single package. 92 // 93 // Differences wrt go tool yacc 94 // 95 // - goyacc implements ideas from "Generating LR Syntax Error Messages from 96 // Examples"[1]. Use the -xe flag to pass a name of the example file. For more 97 // details about the example format please see [2]. 98 // 99 // - The grammar report includes example token sequences leading to the 100 // particular state. Can help understanding conflicts. 101 // 102 // - Minor changes in parser debug output. 103 // 104 // Links 105 // 106 // Referenced from elsewhere: 107 // 108 // [0]: http://yougam/libraries/cmd/yacc/ 109 // [1]: http://people.via.ecp.fr/~stilgar/doc/compilo/parser/Generating%20LR%20Syntax%20Error%20Messages.pdf 110 // [2]: http://godoc.org/yougam/libraries/cznic/y#hdr-Error_Examples 111 // [3]: http://www.gnu.org/software/bison/manual/html_node/Precedence-Only.html#Precedence-Only 112 package main 113 114 import ( 115 "bufio" 116 "bytes" 117 "flag" 118 "fmt" 119 "go/format" 120 "go/scanner" 121 "go/token" 122 "io" 123 "io/ioutil" 124 "log" 125 "os" 126 "runtime" 127 "sort" 128 "strings" 129 130 "github.com/insionng/yougam/libraries/qiuyesuifeng/goyacc/Godeps/_workspace/src/yougam/libraries/cznic/mathutil" 131 "github.com/insionng/yougam/libraries/qiuyesuifeng/goyacc/Godeps/_workspace/src/yougam/libraries/cznic/parser/yacc" 132 "github.com/insionng/yougam/libraries/qiuyesuifeng/goyacc/Godeps/_workspace/src/yougam/libraries/cznic/sortutil" 133 "github.com/insionng/yougam/libraries/qiuyesuifeng/goyacc/Godeps/_workspace/src/yougam/libraries/cznic/strutil" 134 "github.com/insionng/yougam/libraries/qiuyesuifeng/goyacc/Godeps/_workspace/src/yougam/libraries/cznic/y" 135 ) 136 137 var ( 138 //oNoDefault = flag.Bool("nodefault", false, "disable generating $default actions") 139 oClosures = flag.Bool("c", false, "report state closures") 140 oReducible = flag.Bool("cr", false, "check all states are reducible") 141 oDlval = flag.String("dlval", "lval", "debug value (runtime yyDebug >= 3)") 142 oDlvalf = flag.String("dlvalf", "%+v", "debug format of -dlval (runtime yyDebug >= 3)") 143 oLA = flag.Bool("la", false, "report all lookahead sets") 144 oNoLines = flag.Bool("l", false, "disable line directives (for compatibility ony - ignored)") 145 oOut = flag.String("o", "y.go", "parser output") 146 oPref = flag.String("p", "yy", "name prefix to use in generated code") 147 oReport = flag.String("v", "y.output", "create grammar report") 148 oResolved = flag.Bool("ex", false, "explain how were conflicts resolved") 149 oXErrors = flag.String("xe", "", "generate eXtra errors from examples source file") 150 oXErrorsGen = flag.String("xegen", "", "generate error from examples source file automatically from the grammar") 151 ) 152 153 func main() { 154 log.SetFlags(0) 155 156 defer func() { 157 _, file, line, ok := runtime.Caller(2) 158 if e := recover(); e != nil { 159 switch { 160 case ok: 161 log.Fatalf("%s:%d: panic: %v", file, line, e) 162 default: 163 log.Fatalf("panic: %v", e) 164 } 165 } 166 }() 167 168 flag.Parse() 169 var in string 170 switch flag.NArg() { 171 case 0: 172 in = os.Stdin.Name() 173 case 1: 174 in = flag.Arg(0) 175 default: 176 log.Fatal("expected at most one non flag argument") 177 } 178 179 if err := main1(in); err != nil { 180 switch x := err.(type) { 181 case scanner.ErrorList: 182 for _, v := range x { 183 fmt.Fprintf(os.Stderr, "%v\n", v) 184 } 185 os.Exit(1) 186 default: 187 log.Fatal(err) 188 } 189 } 190 } 191 192 type symUsed struct { 193 sym *y.Symbol 194 used int 195 } 196 197 type symsUsed []symUsed 198 199 func (s symsUsed) Len() int { return len(s) } 200 func (s symsUsed) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 201 202 func (s symsUsed) Less(i, j int) bool { 203 if s[i].used > s[j].used { 204 return true 205 } 206 207 if s[i].used < s[j].used { 208 return false 209 } 210 211 return strings.ToLower(s[i].sym.Name) < strings.ToLower(s[j].sym.Name) 212 } 213 214 func main1(in string) (err error) { 215 var out io.Writer 216 if nm := *oOut; nm != "" { 217 var f *os.File 218 var e error 219 if f, err = os.Create(nm); err != nil { 220 return err 221 } 222 223 defer func() { 224 if e := f.Close(); e != nil && err == nil { 225 err = e 226 } 227 }() 228 w := bufio.NewWriter(f) 229 defer func() { 230 if e := w.Flush(); e != nil && err == nil { 231 err = e 232 } 233 }() 234 buf := bytes.NewBuffer(nil) 235 out = buf 236 defer func() { 237 var dest []byte 238 if dest, e = format.Source(buf.Bytes()); e != nil { 239 dest = buf.Bytes() 240 } 241 242 if _, e = w.Write(dest); e != nil && err == nil { 243 err = e 244 } 245 }() 246 } 247 248 var rep io.Writer 249 if nm := *oReport; nm != "" { 250 f, err := os.Create(nm) 251 if err != nil { 252 return err 253 } 254 255 defer func() { 256 if e := f.Close(); e != nil && err == nil { 257 err = e 258 } 259 }() 260 w := bufio.NewWriter(f) 261 defer func() { 262 if e := w.Flush(); e != nil && err == nil { 263 err = e 264 } 265 }() 266 rep = w 267 } 268 269 var xerrors []byte 270 if nm := *oXErrors; nm != "" { 271 b, err := ioutil.ReadFile(nm) 272 if err != nil { 273 return err 274 } 275 276 xerrors = b 277 } 278 279 p, err := y.ProcessFile(token.NewFileSet(), in, &y.Options{ 280 //NoDefault: *oNoDefault, 281 AllowConflicts: true, 282 Closures: *oClosures, 283 LA: *oLA, 284 Reducible: *oReducible, 285 Report: rep, 286 Resolved: *oResolved, 287 XErrorsName: *oXErrors, 288 XErrorsSrc: xerrors, 289 }) 290 if err != nil { 291 return err 292 } 293 294 if fn := *oXErrorsGen; fn != "" { 295 f, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0666) 296 if err != nil { 297 return err 298 } 299 300 b := bufio.NewWriter(f) 301 if err := p.SkeletonXErrors(b); err != nil { 302 return err 303 } 304 305 if err := b.Flush(); err != nil { 306 return err 307 } 308 309 if err := f.Close(); err != nil { 310 return err 311 } 312 } 313 314 msu := make(map[*y.Symbol]int, len(p.Syms)) // sym -> usage 315 for nm, sym := range p.Syms { 316 if nm == "" || nm == "ε" || nm == "$accept" || nm == "#" { 317 continue 318 } 319 320 msu[sym] = 0 321 } 322 var minArg, maxArg int 323 for _, state := range p.Table { 324 for _, act := range state { 325 msu[act.Sym]++ 326 k, arg := act.Kind() 327 if k == 'a' { 328 continue 329 } 330 331 if k == 'r' { 332 arg = -arg 333 } 334 minArg, maxArg = mathutil.Min(minArg, arg), mathutil.Max(maxArg, arg) 335 } 336 } 337 su := make(symsUsed, 0, len(msu)) 338 for sym, used := range msu { 339 su = append(su, symUsed{sym, used}) 340 } 341 sort.Sort(su) 342 343 // ----------------------------------------------------------- Prologue 344 f := strutil.IndentFormatter(out, "\t") 345 f.Format("// CAUTION: Generated file - DO NOT EDIT.\n\n") 346 f.Format("%s", injectImport(p.Prologue)) 347 f.Format(` 348 type %[1]sSymType %i%s%u 349 350 type %[1]sXError struct { 351 state, xsym int 352 } 353 `, *oPref, p.UnionSrc) 354 355 // ---------------------------------------------------------- Constants 356 nsyms := map[string]*y.Symbol{} 357 a := make([]string, 0, len(msu)) 358 maxTokName := 0 359 for sym := range msu { 360 nm := sym.Name 361 if nm == "$default" || nm == "$end" || sym.IsTerminal && nm[0] != '\'' && sym.Value > 0 { 362 maxTokName = mathutil.Max(maxTokName, len(nm)) 363 a = append(a, nm) 364 } 365 nsyms[nm] = sym 366 } 367 sort.Strings(a) 368 f.Format("\nconst (%i\n") 369 for _, v := range a { 370 nm := v 371 switch nm { 372 case "error": 373 nm = *oPref + "ErrCode" 374 case "$default": 375 nm = *oPref + "Default" 376 case "$end": 377 nm = *oPref + "EofCode" 378 } 379 f.Format("%s%s = %d\n", nm, strings.Repeat(" ", maxTokName-len(nm)+1), nsyms[v].Value) 380 } 381 minArg-- // eg: [-13, 42], minArg -14 maps -13 to 1 so zero cell values -> empty. 382 f.Format("\n%sMaxDepth = 200\n", *oPref) 383 f.Format("%sTabOfs = %d\n", *oPref, minArg) 384 f.Format("%u)") 385 386 // ---------------------------------------------------------- Variables 387 f.Format("\n\nvar (%i\n") 388 389 // Lex translation table 390 f.Format("%sXLAT = map[int]int{%i\n", *oPref) 391 xlat := make(map[int]int, len(su)) 392 var errSym int 393 for i, v := range su { 394 if v.sym.Name == "error" { 395 errSym = i 396 } 397 xlat[v.sym.Value] = i 398 f.Format("%6d: %3d, // %s (%dx)\n", v.sym.Value, i, v.sym.Name, msu[v.sym]) 399 } 400 f.Format("%u}\n") 401 402 // Symbol names 403 f.Format("\n%sSymNames = []string{%i\n", *oPref) 404 for _, v := range su { 405 f.Format("%q,\n", v.sym.Name) 406 } 407 f.Format("%u}\n") 408 409 // Reduction table 410 f.Format("\n%sReductions = map[int]struct{xsym, components int}{%i\n", *oPref) 411 for r, rule := range p.Rules { 412 f.Format("%d: {%d, %d},\n", r, xlat[rule.Sym.Value], len(rule.Components)) 413 } 414 f.Format("%u}\n") 415 416 // XError table 417 f.Format("\n%[1]sXErrors = map[%[1]sXError]string{%i\n", *oPref) 418 for _, xerr := range p.XErrors { 419 state := xerr.Stack[len(xerr.Stack)-1] 420 xsym := -1 421 if xerr.Lookahead != nil { 422 xsym = xlat[xerr.Lookahead.Value] 423 } 424 f.Format("%[1]sXError{%d, %d}: \"%s\",\n", *oPref, state, xsym, xerr.Msg) 425 } 426 f.Format("%u}\n\n") 427 428 // Parse table 429 tbits := 32 430 switch n := mathutil.BitLen(maxArg - minArg + 1); { 431 case n < 8: 432 tbits = 8 433 case n < 16: 434 tbits = 16 435 } 436 f.Format("%sParseTab = [%d][]uint%d{%i\n", *oPref, len(p.Table), tbits) 437 nCells := 0 438 var tabRow sortutil.Uint64Slice 439 for si, state := range p.Table { 440 tabRow = tabRow[:0] 441 max := 0 442 for _, act := range state { 443 sym := act.Sym 444 xsym, ok := xlat[sym.Value] 445 if !ok { 446 panic("internal error 001") 447 } 448 449 max = mathutil.Max(max, xsym) 450 kind, arg := act.Kind() 451 switch kind { 452 case 'a': 453 arg = 0 454 case 'r': 455 arg *= -1 456 } 457 tabRow = append(tabRow, uint64(xsym)<<32|uint64(arg-minArg)) 458 } 459 nCells += max 460 tabRow.Sort() 461 col := -1 462 if si%5 == 0 { 463 f.Format("// %d\n", si) 464 } 465 f.Format("{") 466 for i, v := range tabRow { 467 xsym := int(uint32(v >> 32)) 468 arg := int(uint32(v)) 469 if col+1 != xsym { 470 f.Format("%d: ", xsym) 471 } 472 switch { 473 case i == len(tabRow)-1: 474 f.Format("%d", arg) 475 default: 476 f.Format("%d, ", arg) 477 } 478 col = xsym 479 } 480 f.Format("},\n") 481 } 482 f.Format("%u}\n") 483 fmt.Fprintf(os.Stderr, "Parse table entries: %d of %d, x %d bits == %d bytes\n", nCells, len(p.Table)*len(msu), tbits, nCells*tbits/8) 484 if n := p.ConflictsSR; n != 0 { 485 fmt.Fprintf(os.Stderr, "conflicts: %d shift/reduce\n", n) 486 } 487 if n := p.ConflictsRR; n != 0 { 488 fmt.Fprintf(os.Stderr, "conflicts: %d reduce/reduce\n", n) 489 } 490 491 f.Format(`%u) 492 493 var %[1]sDebug = 0 494 495 type %[1]sLexer interface { 496 Lex(lval *%[1]sSymType) int 497 Error(s string) 498 } 499 500 type %[1]sLexerEx interface { 501 %[1]sLexer 502 Reduced(rule, state int, lval *%[1]sSymType) bool 503 } 504 505 func %[1]sSymName(c int) (s string) { 506 x, ok := %[1]sXLAT[c] 507 if ok { 508 return %[1]sSymNames[x] 509 } 510 511 return __yyfmt__.Sprintf("%%d", c) 512 } 513 514 func %[1]slex1(yylex %[1]sLexer, lval *%[1]sSymType) (n int) { 515 n = yylex.Lex(lval) 516 if n <= 0 { 517 n = %[1]sEofCode 518 } 519 if %[1]sDebug >= 3 { 520 __yyfmt__.Printf("\nlex %%s(%%#x %%d), %[4]s: %[3]s\n", %[1]sSymName(n), n, n, %[4]s) 521 } 522 return n 523 } 524 525 func %[1]sParse(yylex %[1]sLexer) int { 526 const yyError = %[2]d 527 528 yyEx, _ := yylex.(%[1]sLexerEx) 529 var yyn int 530 var yylval %[1]sSymType 531 var yyVAL %[1]sSymType 532 yyS := make([]%[1]sSymType, 200) 533 534 Nerrs := 0 /* number of errors */ 535 Errflag := 0 /* error recovery flag */ 536 yyerrok := func() { 537 if %[1]sDebug >= 2 { 538 __yyfmt__.Printf("yyerrok()\n") 539 } 540 Errflag = 0 541 } 542 _ = yyerrok 543 yystate := 0 544 yychar := -1 545 var yyxchar int 546 var yyshift int 547 yyp := -1 548 goto yystack 549 550 ret0: 551 return 0 552 553 ret1: 554 return 1 555 556 yystack: 557 /* put a state and value onto the stack */ 558 yyp++ 559 if yyp >= len(yyS) { 560 nyys := make([]%[1]sSymType, len(yyS)*2) 561 copy(nyys, yyS) 562 yyS = nyys 563 } 564 yyS[yyp] = yyVAL 565 yyS[yyp].yys = yystate 566 567 yynewstate: 568 if yychar < 0 { 569 yychar = %[1]slex1(yylex, &yylval) 570 var ok bool 571 if yyxchar, ok = %[1]sXLAT[yychar]; !ok { 572 yyxchar = len(%[1]sSymNames) // > tab width 573 } 574 } 575 if %[1]sDebug >= 4 { 576 var a []int 577 for _, v := range yyS[:yyp+1] { 578 a = append(a, v.yys) 579 } 580 __yyfmt__.Printf("state stack %%v\n", a) 581 } 582 row := %[1]sParseTab[yystate] 583 yyn = 0 584 if yyxchar < len(row) { 585 if yyn = int(row[yyxchar]); yyn != 0 { 586 yyn += %[1]sTabOfs 587 } 588 } 589 switch { 590 case yyn > 0: // shift 591 yychar = -1 592 yyVAL = yylval 593 yystate = yyn 594 yyshift = yyn 595 if %[1]sDebug >= 2 { 596 __yyfmt__.Printf("shift, and goto state %%d\n", yystate) 597 } 598 if Errflag > 0 { 599 Errflag-- 600 } 601 goto yystack 602 case yyn < 0: // reduce 603 case yystate == 1: // accept 604 if %[1]sDebug >= 2 { 605 __yyfmt__.Println("accept") 606 } 607 goto ret0 608 } 609 610 if yyn == 0 { 611 /* error ... attempt to resume parsing */ 612 switch Errflag { 613 case 0: /* brand new error */ 614 if %[1]sDebug >= 1 { 615 __yyfmt__.Printf("no action for %%s in state %%d\n", %[1]sSymName(yychar), yystate) 616 } 617 msg, ok := %[1]sXErrors[%[1]sXError{yystate, yyxchar}] 618 if !ok { 619 msg, ok = %[1]sXErrors[%[1]sXError{yystate, -1}] 620 } 621 if !ok && yyshift != 0 { 622 msg, ok = %[1]sXErrors[%[1]sXError{yyshift, yyxchar}] 623 } 624 if !ok { 625 msg, ok = %[1]sXErrors[%[1]sXError{yyshift, -1}] 626 } 627 if !ok || msg == "" { 628 msg = "syntax error" 629 } 630 yylex.Error(msg) 631 Nerrs++ 632 fallthrough 633 634 case 1, 2: /* incompletely recovered error ... try again */ 635 Errflag = 3 636 637 /* find a state where "error" is a legal shift action */ 638 for yyp >= 0 { 639 row := %[1]sParseTab[yyS[yyp].yys] 640 if yyError < len(row) { 641 yyn = int(row[yyError])+%[1]sTabOfs 642 if yyn > 0 { // hit 643 if %[1]sDebug >= 2 { 644 __yyfmt__.Printf("error recovery found error shift in state %%d\n", yyS[yyp].yys) 645 } 646 yystate = yyn /* simulate a shift of "error" */ 647 goto yystack 648 } 649 } 650 651 /* the current p has no shift on "error", pop stack */ 652 if %[1]sDebug >= 2 { 653 __yyfmt__.Printf("error recovery pops state %%d\n", yyS[yyp].yys) 654 } 655 yyp-- 656 } 657 /* there is no state on the stack with an error shift ... abort */ 658 if %[1]sDebug >= 2 { 659 __yyfmt__.Printf("error recovery failed\n") 660 } 661 goto ret1 662 663 case 3: /* no shift yet; clobber input char */ 664 if %[1]sDebug >= 2 { 665 __yyfmt__.Printf("error recovery discards %%s\n", %[1]sSymName(yychar)) 666 } 667 if yychar == %[1]sEofCode { 668 goto ret1 669 } 670 671 yychar = -1 672 goto yynewstate /* try again in the same state */ 673 } 674 } 675 676 r := -yyn 677 x0 := %[1]sReductions[r] 678 x, n := x0.xsym, x0.components 679 yypt := yyp 680 _ = yypt // guard against "declared and not used" 681 682 yyp -= n 683 if yyp+1 >= len(yyS) { 684 nyys := make([]%[1]sSymType, len(yyS)*2) 685 copy(nyys, yyS) 686 yyS = nyys 687 } 688 yyVAL = yyS[yyp+1] 689 690 /* consult goto table to find next state */ 691 exState := yystate 692 yystate = int(%[1]sParseTab[yyS[yyp].yys][x])+%[1]sTabOfs 693 /* reduction by production r */ 694 if %[1]sDebug >= 2 { 695 __yyfmt__.Printf("reduce using rule %%v (%%s), and goto state %%d\n", r, %[1]sSymNames[x], yystate) 696 } 697 698 switch r {%i 699 `, 700 *oPref, errSym, *oDlvalf, *oDlval) 701 for r, rule := range p.Rules { 702 if rule.Action == nil { 703 continue 704 } 705 706 action := rule.Action.Values 707 if len(action) == 0 { 708 continue 709 } 710 711 if len(action) == 1 { 712 part := action[0] 713 if part.Type == parser.ActionValueGo { 714 src := part.Src 715 src = src[1 : len(src)-1] // Remove lead '{' and trail '}' 716 if strings.TrimSpace(src) == "" { 717 continue 718 } 719 } 720 } 721 722 components := rule.Components 723 typ := rule.Sym.Type 724 max := len(components) 725 if p := rule.Parent; p != nil { 726 max = rule.MaxParentDlr 727 components = p.Components 728 } 729 f.Format("case %d: ", r) 730 for _, part := range action { 731 num := part.Num 732 switch part.Type { 733 case parser.ActionValueGo: 734 f.Format("%s", part.Src) 735 case parser.ActionValueDlrDlr: 736 f.Format("yyVAL.%s", typ) 737 if typ == "" { 738 panic("internal error 002") 739 } 740 case parser.ActionValueDlrNum: 741 typ := p.Syms[components[num-1]].Type 742 if typ == "" { 743 panic("internal error 003") 744 } 745 f.Format("yyS[yypt-%d].%s", max-num, typ) 746 case parser.ActionValueDlrTagDlr: 747 f.Format("yyVAL.%s", part.Tag) 748 case parser.ActionValueDlrTagNum: 749 f.Format("yyS[yypt-%d].%s", max-num, part.Tag) 750 } 751 } 752 f.Format("\n") 753 } 754 f.Format(`%u 755 } 756 757 if yyEx != nil && yyEx.Reduced(r, exState, &yyVAL) { 758 return -1 759 } 760 goto yystack /* stack new state and value */ 761 } 762 763 %[2]s 764 `, *oPref, p.Tail) 765 _ = oNoLines //TODO Ignored for now 766 return nil 767 } 768 769 func injectImport(src string) string { 770 const inj = ` 771 772 import __yyfmt__ "fmt" 773 ` 774 fset := token.NewFileSet() 775 file := fset.AddFile("", -1, len(src)) 776 var s scanner.Scanner 777 s.Init( 778 file, 779 []byte(src), 780 nil, 781 scanner.ScanComments, 782 ) 783 for { 784 switch _, tok, _ := s.Scan(); tok { 785 case token.EOF: 786 return inj + src 787 case token.PACKAGE: 788 s.Scan() // ident 789 pos, _, _ := s.Scan() 790 ofs := file.Offset(pos) 791 return src[:ofs] + inj + src[ofs:] 792 } 793 } 794 }