1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
package main
import (
"flag"
"fmt"
"go/ast"
"go/printer"
"go/token"
"os"
"regexp"
"strings"
"github.com/itchyny/astgen-go"
"github.com/wader/gojq"
)
const fileFormat = `// Code generated by _tools/gen_builtin.go; DO NOT EDIT.
package gojq
func init() {%s}
`
func main() {
var input, output string
flag.StringVar(&input, "i", "", "input file")
flag.StringVar(&output, "o", "", "output file")
flag.Parse()
if err := run(input, output); err != nil {
fmt.Fprint(os.Stderr, err)
os.Exit(1)
}
}
func run(input, output string) error {
cnt, err := os.ReadFile(input)
if err != nil {
return err
}
q, err := gojq.Parse(string(cnt))
if err != nil {
return err
}
fds := make(map[string][]*gojq.FuncDef)
for _, fd := range q.FuncDefs {
fd.Minify()
fds[fd.Name] = append(fds[fd.Name], fd)
}
fds["_assign"] = nil
fds["_modify"] = nil
t, err := astgen.Build(fds)
if err != nil {
return err
}
var sb strings.Builder
sb.WriteString("\n\tbuiltinFuncDefs = ")
if err := printCompositeLit(&sb, t.(*ast.CompositeLit)); err != nil {
return err
}
out := os.Stdout
if output != "" {
f, err := os.Create(output)
if err != nil {
return err
}
defer f.Close()
out = f
}
_, err = fmt.Fprintf(out, fileFormat, sb.String())
return err
}
func printCompositeLit(out *strings.Builder, t *ast.CompositeLit) error {
err := printer.Fprint(out, token.NewFileSet(), t.Type)
if err != nil {
return err
}
out.WriteString("{")
for _, kv := range t.Elts {
out.WriteString("\n\t\t")
var sb strings.Builder
err = printer.Fprint(&sb, token.NewFileSet(), kv)
if err != nil {
return err
}
str := sb.String()
for op := gojq.OpPipe; op <= gojq.OpUpdateAlt; op++ {
r := regexp.MustCompile(fmt.Sprintf(`\b((?:Update)?Op): %d\b`, op))
str = r.ReplaceAllString(str, fmt.Sprintf("$1: %#v", op))
}
for termType := gojq.TermTypeIdentity; termType <= gojq.TermTypeQuery; termType++ {
r := regexp.MustCompile(fmt.Sprintf(`(Term{Type): %d\b`, termType))
str = r.ReplaceAllString(str, fmt.Sprintf("$1: %#v", termType))
}
out.WriteString(strings.ReplaceAll(str, "gojq.", ""))
out.WriteString(",")
}
out.WriteString("\n\t}\n")
return nil
}
|