func dumpDB(db *DB, tag string) (string, error) { var buf bytes.Buffer f := strutil.IndentFormatter(&buf, "\t") f.Format("---- %s%i\n", tag) for nm, tab := range db.root.tables { h := tab.head f.Format("%u%q: head %d, scols0 %q, scols %q%i\n", nm, h, cols2meta(tab.cols0), cols2meta(tab.cols)) for h != 0 { rec, err := db.store.Read(nil, h, tab.cols...) if err != nil { return "", err } f.Format("record @%d: %v\n", h, rec) h = rec[0].(int64) } f.Format("%u") for i, v := range tab.indices { if v == nil { continue } xname := v.name cname := "id()" if i != 0 { cname = tab.cols0[i-1].name } f.Format("index %s on %s%i\n", xname, cname) it, _, err := v.x.Seek(nil) if err != nil { return "", err } for { k, v, err := it.Next() if err != nil { if err == io.EOF { break } return "", err } f.Format("%v: %v\n", k, v) } f.Format("%u") } } return buf.String(), nil }
// String implements fmt.Stringer func (l List) String() string { var b bytes.Buffer f := strutil.IndentFormatter(&b, "\t") for _, s := range l.l { switch s.(type) { case beginTransactionStmt: f.Format("%s\n%i", s) case commitStmt, rollbackStmt: f.Format("%u%s\n", s) default: f.Format("%s\n", s) } } return b.String() }
func prettyPrint(w io.Writer, v interface{}) { if v == nil { return } f := strutil.IndentFormatter(w, "· ") defer func() { if e := recover(); e != nil { f.Format("\npanic: %v", e) } }() prettyPrint0(nil, f, "", "", v) }
func _dump() { s := fmt.Sprintf("%#v", _parserResult) s = strings.Replace(s, "%", "%%", -1) s = strings.Replace(s, "{", "{%i\n", -1) s = strings.Replace(s, "}", "%u\n}", -1) s = strings.Replace(s, ", ", ",\n", -1) var buf bytes.Buffer strutil.IndentFormatter(&buf, ". ").Format(s) buf.WriteString("\n") a := strings.Split(buf.String(), "\n") for _, v := range a { if strings.HasSuffix(v, "(nil)") || strings.HasSuffix(v, "(nil),") { continue } fmt.Println(v) } }
func main1(in string) (err error) { var out io.Writer if nm := *oOut; nm != "" { var f *os.File var e error if f, err = os.Create(nm); err != nil { return err } defer func() { if e1 := f.Close(); e1 != nil && err == nil { err = e1 } }() w := bufio.NewWriter(f) defer func() { if e1 := w.Flush(); e1 != nil && err == nil { err = e1 } }() buf := bytes.NewBuffer(nil) out = buf defer func() { var dest []byte if dest, e = format.Source(buf.Bytes()); e != nil { dest = buf.Bytes() } if _, e = w.Write(dest); e != nil && err == nil { err = e } }() } var rep io.Writer if nm := *oReport; nm != "" { f, err1 := os.Create(nm) if err1 != nil { return err1 } defer func() { if e := f.Close(); e != nil && err == nil { err = e } }() w := bufio.NewWriter(f) defer func() { if e := w.Flush(); e != nil && err == nil { err = e } }() rep = w } var xerrors []byte if nm := *oXErrors; nm != "" { b, err1 := ioutil.ReadFile(nm) if err1 != nil { return err1 } xerrors = b } p, err := y.ProcessFile(token.NewFileSet(), in, &y.Options{ //NoDefault: *oNoDefault, AllowConflicts: true, Closures: *oClosures, LA: *oLA, Reducible: *oReducible, Report: rep, Resolved: *oResolved, XErrorsName: *oXErrors, XErrorsSrc: xerrors, }) if err != nil { return err } if fn := *oXErrorsGen; fn != "" { f, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0666) if err != nil { return err } b := bufio.NewWriter(f) if err := p.SkeletonXErrors(b); err != nil { return err } if err := b.Flush(); err != nil { return err } if err := f.Close(); err != nil { return err } } msu := make(map[*y.Symbol]int, len(p.Syms)) // sym -> usage for nm, sym := range p.Syms { if nm == "" || nm == "ε" || nm == "$accept" || nm == "#" { continue } msu[sym] = 0 } var minArg, maxArg int for _, state := range p.Table { for _, act := range state { msu[act.Sym]++ k, arg := act.Kind() if k == 'a' { continue } if k == 'r' { arg = -arg } minArg, maxArg = mathutil.Min(minArg, arg), mathutil.Max(maxArg, arg) } } su := make(symsUsed, 0, len(msu)) for sym, used := range msu { su = append(su, symUsed{sym, used}) } sort.Sort(su) // ----------------------------------------------------------- Prologue f := strutil.IndentFormatter(out, "\t") f.Format("// CAUTION: Generated file - DO NOT EDIT.\n\n") f.Format("%s", injectImport(p.Prologue)) f.Format(` type %[1]sSymType %i%s%u type %[1]sXError struct { state, xsym int } `, *oPref, p.UnionSrc) // ---------------------------------------------------------- Constants nsyms := map[string]*y.Symbol{} a := make([]string, 0, len(msu)) maxTokName := 0 for sym := range msu { nm := sym.Name if nm == "$default" || nm == "$end" || sym.IsTerminal && nm[0] != '\'' && sym.Value > 0 { maxTokName = mathutil.Max(maxTokName, len(nm)) a = append(a, nm) } nsyms[nm] = sym } sort.Strings(a) f.Format("\nconst (%i\n") for _, v := range a { nm := v switch nm { case "error": nm = *oPref + "ErrCode" case "$default": nm = *oPref + "Default" case "$end": nm = *oPref + "EofCode" } f.Format("%s%s = %d\n", nm, strings.Repeat(" ", maxTokName-len(nm)+1), nsyms[v].Value) } minArg-- // eg: [-13, 42], minArg -14 maps -13 to 1 so zero cell values -> empty. f.Format("\n%sMaxDepth = 200\n", *oPref) f.Format("%sTabOfs = %d\n", *oPref, minArg) f.Format("%u)") // ---------------------------------------------------------- Variables f.Format("\n\nvar (%i\n") // Lex translation table f.Format("%sXLAT = map[int]int{%i\n", *oPref) xlat := make(map[int]int, len(su)) var errSym int for i, v := range su { if v.sym.Name == "error" { errSym = i } xlat[v.sym.Value] = i f.Format("%6d: %3d, // %s (%dx)\n", v.sym.Value, i, v.sym.Name, msu[v.sym]) } f.Format("%u}\n") // Symbol names f.Format("\n%sSymNames = []string{%i\n", *oPref) for _, v := range su { f.Format("%q,\n", v.sym.Name) } f.Format("%u}\n") // Reduction table f.Format("\n%sReductions = []struct{xsym, components int}{%i\n", *oPref) for _, rule := range p.Rules { f.Format("{%d, %d},\n", xlat[rule.Sym.Value], len(rule.Components)) } f.Format("%u}\n") // XError table f.Format("\n%[1]sXErrors = map[%[1]sXError]string{%i\n", *oPref) for _, xerr := range p.XErrors { state := xerr.Stack[len(xerr.Stack)-1] xsym := -1 if xerr.Lookahead != nil { xsym = xlat[xerr.Lookahead.Value] } f.Format("%[1]sXError{%d, %d}: \"%s\",\n", *oPref, state, xsym, xerr.Msg) } f.Format("%u}\n\n") // Parse table tbits := 32 switch n := mathutil.BitLen(maxArg - minArg + 1); { case n < 8: tbits = 8 case n < 16: tbits = 16 } f.Format("%sParseTab = [%d][]uint%d{%i\n", *oPref, len(p.Table), tbits) nCells := 0 var tabRow sortutil.Uint64Slice for si, state := range p.Table { tabRow = tabRow[:0] max := 0 for _, act := range state { sym := act.Sym xsym, ok := xlat[sym.Value] if !ok { panic("internal error 001") } max = mathutil.Max(max, xsym) kind, arg := act.Kind() switch kind { case 'a': arg = 0 case 'r': arg *= -1 } tabRow = append(tabRow, uint64(xsym)<<32|uint64(arg-minArg)) } nCells += max tabRow.Sort() col := -1 if si%5 == 0 { f.Format("// %d\n", si) } f.Format("{") for i, v := range tabRow { xsym := int(uint32(v >> 32)) arg := int(uint32(v)) if col+1 != xsym { f.Format("%d: ", xsym) } switch { case i == len(tabRow)-1: f.Format("%d", arg) default: f.Format("%d, ", arg) } col = xsym } f.Format("},\n") } f.Format("%u}\n") 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) if n := p.ConflictsSR; n != 0 { fmt.Fprintf(os.Stderr, "conflicts: %d shift/reduce\n", n) } if n := p.ConflictsRR; n != 0 { fmt.Fprintf(os.Stderr, "conflicts: %d reduce/reduce\n", n) } f.Format(`%u) var %[1]sDebug = 0 type %[1]sLexer interface { Lex(lval *%[1]sSymType) int Errorf(format string, a ...interface{}) Errors() []error } type %[1]sLexerEx interface { %[1]sLexer Reduced(rule, state int, lval *%[1]sSymType) bool } func %[1]sSymName(c int) (s string) { x, ok := %[1]sXLAT[c] if ok { return %[1]sSymNames[x] } return __yyfmt__.Sprintf("%%d", c) } func %[1]slex1(yylex %[1]sLexer, lval *%[1]sSymType) (n int) { n = yylex.Lex(lval) if n <= 0 { n = %[1]sEofCode } if %[1]sDebug >= 3 { __yyfmt__.Printf("\nlex %%s(%%#x %%d), %[4]s: %[3]s\n", %[1]sSymName(n), n, n, %[4]s) } return n } func %[1]sParse(yylex %[1]sLexer, parser *Parser) int { const yyError = %[2]d yyEx, _ := yylex.(%[1]sLexerEx) var yyn int parser.yylval = %[1]sSymType{} parser.yyVAL = %[1]sSymType{} yyS := parser.cache Nerrs := 0 /* number of errors */ Errflag := 0 /* error recovery flag */ yyerrok := func() { if %[1]sDebug >= 2 { __yyfmt__.Printf("yyerrok()\n") } Errflag = 0 } _ = yyerrok yystate := 0 yychar := -1 var yyxchar int var yyshift int yyp := -1 goto yystack ret0: return 0 ret1: return 1 yystack: /* put a state and value onto the stack */ yyp++ if yyp >= len(yyS) { nyys := make([]%[1]sSymType, len(yyS)*2) copy(nyys, yyS) yyS = nyys parser.cache = yyS } yyS[yyp] = parser.yyVAL yyS[yyp].yys = yystate yynewstate: if yychar < 0 { yychar = %[1]slex1(yylex, &parser.yylval) var ok bool if yyxchar, ok = %[1]sXLAT[yychar]; !ok { yyxchar = len(%[1]sSymNames) // > tab width } } if %[1]sDebug >= 4 { var a []int for _, v := range yyS[:yyp+1] { a = append(a, v.yys) } __yyfmt__.Printf("state stack %%v\n", a) } row := %[1]sParseTab[yystate] yyn = 0 if yyxchar < len(row) { if yyn = int(row[yyxchar]); yyn != 0 { yyn += %[1]sTabOfs } } switch { case yyn > 0: // shift yychar = -1 parser.yyVAL = parser.yylval yystate = yyn yyshift = yyn if %[1]sDebug >= 2 { __yyfmt__.Printf("shift, and goto state %%d\n", yystate) } if Errflag > 0 { Errflag-- } goto yystack case yyn < 0: // reduce case yystate == 1: // accept if %[1]sDebug >= 2 { __yyfmt__.Println("accept") } goto ret0 } if yyn == 0 { /* error ... attempt to resume parsing */ switch Errflag { case 0: /* brand new error */ if %[1]sDebug >= 1 { __yyfmt__.Printf("no action for %%s in state %%d\n", %[1]sSymName(yychar), yystate) } msg, ok := %[1]sXErrors[%[1]sXError{yystate, yyxchar}] if !ok { msg, ok = %[1]sXErrors[%[1]sXError{yystate, -1}] } if !ok && yyshift != 0 { msg, ok = %[1]sXErrors[%[1]sXError{yyshift, yyxchar}] } if !ok { msg, ok = %[1]sXErrors[%[1]sXError{yyshift, -1}] } if !ok || msg == "" { msg = "syntax error" } // ignore goyacc error message yylex.Errorf("") Nerrs++ fallthrough case 1, 2: /* incompletely recovered error ... try again */ Errflag = 3 /* find a state where "error" is a legal shift action */ for yyp >= 0 { row := %[1]sParseTab[yyS[yyp].yys] if yyError < len(row) { yyn = int(row[yyError])+%[1]sTabOfs if yyn > 0 { // hit if %[1]sDebug >= 2 { __yyfmt__.Printf("error recovery found error shift in state %%d\n", yyS[yyp].yys) } yystate = yyn /* simulate a shift of "error" */ goto yystack } } /* the current p has no shift on "error", pop stack */ if %[1]sDebug >= 2 { __yyfmt__.Printf("error recovery pops state %%d\n", yyS[yyp].yys) } yyp-- } /* there is no state on the stack with an error shift ... abort */ if %[1]sDebug >= 2 { __yyfmt__.Printf("error recovery failed\n") } goto ret1 case 3: /* no shift yet; clobber input char */ if %[1]sDebug >= 2 { __yyfmt__.Printf("error recovery discards %%s\n", %[1]sSymName(yychar)) } if yychar == %[1]sEofCode { goto ret1 } yychar = -1 goto yynewstate /* try again in the same state */ } } r := -yyn x0 := %[1]sReductions[r] x, n := x0.xsym, x0.components yypt := yyp _ = yypt // guard against "declared and not used" yyp -= n if yyp+1 >= len(yyS) { nyys := make([]%[1]sSymType, len(yyS)*2) copy(nyys, yyS) yyS = nyys parser.cache = yyS } parser.yyVAL = yyS[yyp+1] /* consult goto table to find next state */ exState := yystate yystate = int(%[1]sParseTab[yyS[yyp].yys][x])+%[1]sTabOfs /* reduction by production r */ if %[1]sDebug >= 2 { __yyfmt__.Printf("reduce using rule %%v (%%s), and goto state %%d\n", r, %[1]sSymNames[x], yystate) } switch r {%i `, *oPref, errSym, *oDlvalf, *oDlval) for r, rule := range p.Rules { if rule.Action == nil { continue } action := rule.Action.Values if len(action) == 0 { continue } if len(action) == 1 { part := action[0] if part.Type == parser.ActionValueGo { src := part.Src src = src[1 : len(src)-1] // Remove lead '{' and trail '}' if strings.TrimSpace(src) == "" { continue } } } components := rule.Components typ := rule.Sym.Type max := len(components) if p1 := rule.Parent; p1 != nil { max = rule.MaxParentDlr components = p1.Components } f.Format("case %d: ", r) for _, part := range action { num := part.Num switch part.Type { case parser.ActionValueGo: f.Format("%s", part.Src) case parser.ActionValueDlrDlr: f.Format("parser.yyVAL.%s", typ) if typ == "" { panic("internal error 002") } case parser.ActionValueDlrNum: typ := p.Syms[components[num-1]].Type if typ == "" { panic("internal error 003") } f.Format("yyS[yypt-%d].%s", max-num, typ) case parser.ActionValueDlrTagDlr: f.Format("parser.yyVAL.%s", part.Tag) case parser.ActionValueDlrTagNum: f.Format("yyS[yypt-%d].%s", max-num, part.Tag) } } f.Format("\n") } f.Format(`%u } if yyEx != nil && yyEx.Reduced(r, exState, &parser.yyVAL) { return -1 } goto yystack /* stack new state and value */ } %[2]s `, *oPref, p.Tail) _ = oNoLines //TODO Ignored for now return nil }
func (t *Tree) dump() string { var buf bytes.Buffer f := strutil.IndentFormatter(&buf, "\t") num := map[interface{}]int{} visited := map[interface{}]bool{} handle := func(p interface{}) int { if isNil(p) { return 0 } if n, ok := num[p]; ok { return n } n := len(num) + 1 num[p] = n return n } var pagedump func(interface{}, string) pagedump = func(p interface{}, pref string) { if isNil(p) || visited[p] { return } visited[p] = true switch x := p.(type) { case *x: h := handle(p) n := 0 for i, v := range x.x { if v.ch != nil || v.k != nil { n = i + 1 } } f.Format("%sX#%d(%p) n %d:%d {", pref, h, x, x.c, n) a := []interface{}{} for i, v := range x.x[:n] { a = append(a, v.ch) if i != 0 { f.Format(" ") } f.Format("(C#%d K %v)", handle(v.ch), v.k) } f.Format("}\n") for _, p := range a { pagedump(p, pref+". ") } case *d: h := handle(p) n := 0 for i, v := range x.d { if v.k != nil || v.v != nil { n = i + 1 } } f.Format("%sD#%d(%p) P#%d N#%d n %d:%d {", pref, h, x, handle(x.p), handle(x.n), x.c, n) for i, v := range x.d[:n] { if i != 0 { f.Format(" ") } f.Format("%v:%v", v.k, v.v) } f.Format("}\n") } } pagedump(t.r, "") s := buf.String() if s != "" { s = s[:len(s)-1] } return s }
func prettyPrint0(protect map[interface{}]struct{}, sf strutil.Formatter, prefix, suffix string, v interface{}) { if v == nil { return } switch x := v.(type) { case *Token: if x == nil { return } sf.Format("%s%v"+suffix, prefix, x.String()) return } rt := reflect.TypeOf(v) rv := reflect.ValueOf(v) switch rt.Kind() { case reflect.Slice: if rv.Len() == 0 { return } sf.Format("%s[]%T{ // len %d%i\n", prefix, rv.Index(0).Interface(), rv.Len()) for i := 0; i < rv.Len(); i++ { prettyPrint0(protect, sf, fmt.Sprintf("%d: ", i), ",\n", rv.Index(i).Interface()) } sf.Format("%u}" + suffix) case reflect.Struct: sf.Format("%s%T{%i\n", prefix, v) for i := 0; i < rt.NumField(); i++ { f := rv.Field(i) if !f.CanInterface() { continue } prettyPrint0(protect, sf, fmt.Sprintf("%s: ", rt.Field(i).Name), ",\n", f.Interface()) } sf.Format("%u}" + suffix) case reflect.Ptr: if rv.IsNil() { return } rvi := rv.Interface() if _, ok := protect[rvi]; ok { sf.Format("%s&%T{ /* recursive/repetitive pointee not shown */ }"+suffix, prefix, rv.Elem().Interface()) return } if protect == nil { protect = map[interface{}]struct{}{} } protect[rvi] = struct{}{} prettyPrint0(protect, sf, prefix+"&", suffix, rv.Elem().Interface()) case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int8: if v := rv.Int(); v != 0 { sf.Format("%s%v"+suffix, prefix, v) } case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint8: if v := rv.Uint(); v != 0 { sf.Format("%s%v"+suffix, prefix, rv.Uint()) } case reflect.Bool: if v := rv.Bool(); v { sf.Format("%s%v"+suffix, prefix, rv.Bool()) } case reflect.String: s := rv.Interface().(string) if s == "" { return } sf.Format("%s%q"+suffix, prefix, s) case reflect.Map: keys := rv.MapKeys() if len(keys) == 0 { return } var buf bytes.Buffer nf := strutil.IndentFormatter(&buf, "· ") var skeys []string for i, k := range keys { prettyPrint0(protect, nf, "", "", k.Interface()) skeys = append(skeys, fmt.Sprintf("%s%10d", buf.Bytes(), i)) } sort.Strings(skeys) sf.Format("%s%T{%i\n", prefix, v) for _, k := range skeys { si := strings.TrimSpace(k[len(k)-10:]) k = k[:len(k)-10] n, _ := strconv.ParseUint(si, 10, 64) mv := rv.MapIndex(keys[n]) prettyPrint0(protect, sf, fmt.Sprintf("%s: ", k), ",\n", mv.Interface()) } sf.Format("%u}" + suffix) default: panic(fmt.Sprintf("prettyPrint: missing support for reflect.Kind == %v", rt.Kind())) } }
func str(v interface{}) string { var buf bytes.Buffer f := strutil.IndentFormatter(&buf, ". ") g := func(interface{}) {} g = func(v interface{}) { switch x := v.(type) { case nil: f.Format("<nil>") case int: f.Format("'%c'\n", x) case string: f.Format("%q\n", x) case []*Act: f.Format("%T{%i\n", x) for _, v := range x { g(v) } f.Format("%u}\n") case *Act: f.Format("%T{%i\n", x) f.Format("Src: %q\n", x.Src) if x.Tok != 0 { f.Format("Tok: %s, Tag: %q, Num: %d\n", x.Tok, x.Tag, x.Num) } f.Format("%u}\n") case *Def: f.Format("%T{%i\n", x) f.Format("Rword: %s, ", x.Rword) f.Format("Tag: %q, ", x.Tag) f.Format("Nlist: %T{%i\n", x.Nlist) for _, v := range x.Nlist { g(v) } f.Format("%u}\n") f.Format("%u}\n") case *Nmno: var s string switch v := x.Identifier.(type) { case string: s = fmt.Sprintf("%q", v) case int: s = fmt.Sprintf("'%c'", v) } f.Format("%T{Identifier: %s, Number: %d}\n", x, s, x.Number) case *Prec: var s string switch v := x.Identifier.(type) { case string: s = fmt.Sprintf("%q", v) case int: s = fmt.Sprintf("'%c'", v) } f.Format("%T{%i\n", x) f.Format("Identifier: %s\n", s) g(x.Act) f.Format("%u}\n") case *Rule: f.Format("%T{%i\n", x) f.Format("Name: %q, ", x.Name) f.Format("Body: %T{%i\n", x.Body) for _, v := range x.Body { g(v) } f.Format("%u}\n") if x.Prec != nil { f.Format("Prec: ") g(x.Prec) } f.Format("%u}\n") case *Spec: f.Format("%T{%i\n", x) f.Format("Defs: %T{%i\n", x.Defs) for _, v := range x.Defs { g(v) } f.Format("%u}\n") f.Format("Rules: %T{%i\n", x.Rules) for _, v := range x.Rules { g(v) } f.Format("%u}\n") f.Format("Tail: %q\n", x.Tail) f.Format("%u}\n") default: f.Format("%s(str): %T(%#v)\n", todo, x, x) } } g(v) return buf.String() }
func (y *y) report(w io.Writer) { f := strutil.IndentFormatter(w, " ") if y.opts.debugSyms { var a []string max := 0 for _, v := range y.syms { max = mathutil.Max(max, len(v.Name)) } for _, v := range y.syms { a = append(a, fmt.Sprintf("%[2]*[1]s val %6[3]d, id %3[5]d, type %[4]q", v.Name, -max-1, v.Value, v.Type, v.id), ) } sort.Strings(a) for _, v := range a { f.Format("%s\n", v) } } for si, state := range y.States { f.Format("state %d //", si) syms, la := state.Syms0() for _, s := range syms { switch { case s == nil: f.Format(" <?>") case !s.IsTerminal: f.Format(" <%s>", s) default: f.Format(" %s", s) } } if la != nil { f.Format(" [%s]", la) } f.Format("%i\n\n") switch { case y.opts.Closures: for _, item := range state.kernel.closure(y) { rule := y.Rules[item.rule()] f.Format("%v", item.dump(y)) if y.opts.LA || item.next(y) == nil { switch i, ok := state.kernel.find(item); { case ok: f.Format(" [%s]", state.lookahead[i].dump(y)) default: if i, ok := state.xitems.find(item); ok { f.Format(" [%s]", state.xla[i].dump(y)) } } } if as := assocStr[rule.Associativity]; as != "" || rule.Precedence >= 0 { f.Format(" // assoc %s, prec %d", as, rule.Precedence) } f.Format("\n") } default: for i, item := range state.kernel { rule := y.Rules[item.rule()] f.Format("%v", item.dump(y)) if y.opts.LA || item.dot() == len(rule.Components) { f.Format(" [%s]", state.lookahead[i].dump(y)) } if as := assocStr[rule.Associativity]; as != "" || rule.Precedence >= 0 { f.Format(" // assoc %s, prec %d", as, rule.Precedence) } f.Format("\n") } for i, item := range state.xitems { rule := y.Rules[item.rule()] f.Format("%v [%s]", item.dump(y), state.xla[i].dump(y)) if as := assocStr[rule.Associativity]; as != "" || rule.Precedence >= 0 { f.Format(" // assoc %s, prec %d", as, rule.Precedence) } f.Format("\n") } } f.Format("%i\n") a := []string{} var w int for sym := range state.actions { w = mathutil.Max(w, len(sym.Name)) a = append(a, sym.Name) } sort.Strings(a) type conflict struct { sym *Symbol acts []action } var conflicts []conflict for _, nm := range a { sym := y.Syms[nm] acts := state.actions[sym] act := acts[0] f.Format("%-*s %v", w, nm, act) if act.kind == 'r' { f.Format(" (%s)", y.Rules[act.arg].Sym.Name) } if len(acts) > 1 { conflicts = append(conflicts, conflict{sym, acts}) } f.Format("\n") } a = a[:0] w = 0 for sym := range state.gotos { w = mathutil.Max(w, len(sym.Name)) a = append(a, sym.Name) } sort.Strings(a) for i, nm := range a { if i == 0 { f.Format("\n") } f.Format("%-*s %v\n", w, nm, state.gotos[y.Syms[nm]]) } for i, conflict := range conflicts { if i == 0 { if len(state.gotos) != 0 { f.Format("\n") } } sym := conflict.sym nm := sym.Name f.Format("conflict on %v", nm) for _, act := range conflict.acts { f.Format(", %s", act.String()) } if as := assocStr[sym.Associativity]; as != "" || sym.Precedence >= 0 { f.Format(" // %v: assoc %s, prec %d", nm, assocStr[sym.Associativity], sym.Precedence) } f.Format("\n") } if len(state.resolved) != 0 { f.Format("\n") } for _, v := range state.resolved { f.Format("%s\n", v) } f.Format("%u%u\n") } }
func genASTExamples(spec *y.Parser) { f0 := bytes.NewBuffer(nil) f := strutil.IndentFormatter(f0, "\t") defer func() { file, err := os.Create(*oASTExamples) if err != nil { log.Fatal(err) } b, err := format.Source(f0.Bytes()) if err != nil { b = f0.Bytes() } if _, err := file.Write(b); err != nil { log.Fatal(err) } if err := file.Close(); err != nil { log.Fatal(err) } }() fmt.Fprintf(f, caution) if copyright != "" { fmt.Fprintf(f, "%s\n", copyright) } fmt.Fprintf(f, `package %s import ( "fmt" ) `, *oPkg) states := spec.Reductions() for _, sym := range nonTerminals { nm := sym.Name rules := sym.Rules w := len(strconv.Itoa(len(rules))) nextExample: for icase, rule := range rules { if isIgnored(rule.Sym) { continue } for _, c := range rule.Components { if c == "error" { continue nextExample } } src := "" for _, d := range ruleDirectives[rule] { if d.cmd != "example" { continue } src = unquote(d.arg) break } ruleNum := rule.RuleNum if src == "" { ilit = 0 var r []string state, ok := states[ruleNum] if !ok { // State not reachable? continue nextExample //TODO- panic("internal error") } syms := spec.States[state[0]].Reduce0(rule) if len(syms) == 0 { log.Fatalf("rule %d not reduced in state %d", ruleNum, state[0]) } for _, v := range syms { nm := v.Name if nm == "$end" { continue } if nm == "error" { continue nextExample } ls := v.LiteralString tokDirective := false for _, d := range tokenDirectives[nm] { if d.cmd != "token" { continue } ls = unquote(d.arg) tokDirective = true break } if ls == "" { if nm[0] == '\'' { ls = unquote(nm) } else { log.Fatalf("%v: no literal string for %s", fset.Position(v.Pos), nm) } } if tokDirective { s := strings.Replace(ls, "%%", "", -1) if strings.Contains(s, "%") { ls = fmt.Sprintf(ls, lits[ilit]) ilit = (ilit + 1) % len(lits) } } else { ls = unquote(ls) } r = append(r, strings.Trim(ls, " \t\v\f")) } src = strings.Join(r, *oTokenSep) } switch { case icase == 0: f.Format("\nfunc Example%s() {%i\n", nm) default: f.Format("\nfunc Example%s_case%0*d() {%i\n", nm, w, icase) } switch len(normalizedBody(rule.Body)) { case 1: f.Format("fmt.Println(%s(%d, %q) == (%s)(nil))\n", *oExAST, ruleNum, src, nodes[nm].typ) default: f.Format("fmt.Println(%s(%d, %q))\n", *oExAST, ruleNum, src) } f.Format("// Output:\n%u}\n") } } }
func (j *job) render(w io.Writer, start string) (err error) { f := strutil.IndentFormatter(w, "\t") f.Format(`%%{ //%s Put your favorite license here // yacc source generated by ebnf2y[1] // at %s // // $ %s // // CAUTION: If this file is a Go source file (*.go), it was generated // automatically by '$ go tool yacc' from a *.y file - DO NOT EDIT in that case! // // [1]: http://github.com/cznic/ebnf2y package %s //%s real package name //%s required only be the demo _dump function import ( "bytes" "fmt" "strings" "github.com/cznic/strutil" ) %%} %%union { item interface{} //%s insert real field(s) } `, todo, time.Now(), strings.Join(os.Args, " "), j.pkg, todo, todo, todo) j.term2name = map[string]string{} a := []string{} for name := range j.rep.Tokens { token := j.inventName(j.tPrefix+strings.ToUpper(name), "") j.term2name[name] = token a = append(a, token) } if len(a) != 0 { sort.Strings(a) for _, name := range a { f.Format("%%token\t%s\n", name) } f.Format("\n%%type\t<item> \t/*%s real type(s), if/where applicable */\n", todo) for _, name := range a { f.Format("\t%s\n", name) } f.Format("\n") } j.inventName(j.tPrefix+"TOK", "") a = a[:0] for lit := range j.rep.Literals { if len(lit) == 1 || toAscii(lit) != "" { continue } j.term2name[lit] = j.inventName(j.tPrefix+"TOK", "") a = append(a, lit) } if len(a) != 0 { for _, lit := range a { f.Format("%%token\t%s\t/*%s Name for %q */\n", j.term2name[lit], todo, lit) } f.Format("\n") f.Format("%%type\t<item> \t/*%s real type(s), if/where applicable */\n", todo) for _, lit := range a { f.Format("\t%s\n", j.term2name[lit]) } f.Format("\n") } a = a[:0] for lit := range j.rep.Literals { nm := toAscii(lit) if len(lit) == 1 || nm == "" { continue } name := j.inventName(j.tPrefix+strings.ToUpper(nm), "") j.term2name[lit] = name a = append(a, name) } if len(a) != 0 { sort.Strings(a) for _, name := range a { f.Format("%%token %s\n", name) } f.Format("\n") } a = a[:0] for name := range j.rep.NonTerminals { a = append(a, name) } sort.Strings(a) f.Format("%%type\t<item> \t/*%s real type(s), if/where applicable */\n", todo) for _, name := range a { f.Format("\t%s\n", name) } f.Format("\n") f.Format("/*%s %%left, %%right, ... declarations */\n\n%%start %s\n\n%%%%\n\n", todo, start) rule := 0 for _, name := range a { f.Format("%s:\n\t", name) expr := j.grm[name].Expr switch x := expr.(type) { case ebnf.Alternative: for i, v := range x { if i != 0 { f.Format("|\t") } rule++ f.Format("%s\n\t{\n\t\t%s //%s %d\n\t}\n", j.str(v), j.ystr(v, name, start, i), todo, rule) } default: rule++ f.Format("%s\n\t{\n\t\t%s //%s %d\n\t}\n", j.str(x), j.ystr(x, name, start, -1), todo, rule) } f.Format("\n") } f.Format(`%%%% //%s remove demo stuff below var _parserResult interface{} type (%i `, todo) for _, name := range a { f.Format("%s interface{}\n", name) } f.Format(`%u) func _dump() { s := fmt.Sprintf("%%#v", _parserResult) s = strings.Replace(s, "%%", "%%%%", -1) s = strings.Replace(s, "{", "{%%i\n", -1) s = strings.Replace(s, "}", "%%u\n}", -1) s = strings.Replace(s, ", ", ",\n", -1) var buf bytes.Buffer strutil.IndentFormatter(&buf, ". ").Format(s) buf.WriteString("\n") a := strings.Split(buf.String(), "\n") for _, v := range a { if strings.HasSuffix(v, "(nil)") || strings.HasSuffix(v, "(nil),") { continue } fmt.Println(v) } } // End of demo stuff `) return }