From f0c10152d05002db1fd29acb78fe1cc128b8f000 Mon Sep 17 00:00:00 2001 From: Brandon Dyck Date: Fri, 13 Sep 2024 20:48:33 -0600 Subject: [PATCH] Generate Seq --- gigaparsec.go | 2 +- internal/bindgen/bindgen.go | 39 ++++-- internal/bindgen/seq.go.tmpl | 34 ++++++ seq.go | 225 +++++++++++++++++++++++++++++++++++ 4 files changed, 287 insertions(+), 13 deletions(-) create mode 100644 internal/bindgen/seq.go.tmpl create mode 100644 seq.go diff --git a/gigaparsec.go b/gigaparsec.go index f77e0df..bdbe313 100644 --- a/gigaparsec.go +++ b/gigaparsec.go @@ -1,6 +1,6 @@ package gigaparsec -//go:generate go run ./internal/bindgen -output bind.go -max 5 -pkg gigaparsec +//go:generate go run ./internal/bindgen -bindpath bind.go -seqpath seq.go -max 5 -pkg gigaparsec import ( "errors" "fmt" diff --git a/internal/bindgen/bindgen.go b/internal/bindgen/bindgen.go index 239f99b..1d5c6fd 100644 --- a/internal/bindgen/bindgen.go +++ b/internal/bindgen/bindgen.go @@ -13,7 +13,10 @@ import ( //go:embed bind.go.tmpl var bind string -var tmpl *template.Template +//go:embed seq.go.tmpl +var seq string + +var bindTmpl, seqTmpl *template.Template func main() { err := run() @@ -24,13 +27,17 @@ func main() { } func run() error { - outputPath := flag.String("output", "", "output file path") + bindPath := flag.String("bindpath", "", "bind file path") + seqPath := flag.String("seqpath", "", "seq file path") maxBindLen := flag.Int("max", 0, "max bind length") pkg := flag.String("pkg", "", "output package") flag.Parse() - if *outputPath == "" { - return errors.New("output required") + if *bindPath == "" { + return errors.New("bindpath required") + } + if *seqPath == "" { + return errors.New("seqpath required") } if *maxBindLen == 0 { return errors.New("maxbind required") @@ -39,23 +46,31 @@ func run() error { return errors.New("pkg required") } - tmpl = template.New("") - _, err := tmpl.New("bind").Parse(bind) - if err != nil { - return fmt.Errorf("failed to parse bind: %w", err) - } + bindTmpl = template.Must(template.New("bind").Parse(bind)) + seqTmpl = template.Must(template.New("seq").Parse(seq)) - f, err := os.OpenFile(*outputPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777) + fbind, err := os.OpenFile(*bindPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777) if err != nil { return err } - defer f.Close() + defer fbind.Close() data := File{ Package: *pkg, Counter: Counter(*maxBindLen), } - return tmpl.ExecuteTemplate(f, "bind", data) + err = bindTmpl.Execute(fbind, data) + if err != nil { + return err + } + + fseq, err := os.OpenFile(*seqPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777) + if err != nil { + return err + } + defer fseq.Close() + + return seqTmpl.Execute(fseq, data) } type File struct { diff --git a/internal/bindgen/seq.go.tmpl b/internal/bindgen/seq.go.tmpl new file mode 100644 index 0000000..a8b1fa6 --- /dev/null +++ b/internal/bindgen/seq.go.tmpl @@ -0,0 +1,34 @@ +{{define "func"}}{{if gt . 1 -}} +func Seq{{.}}[In, Out{{range .Count}}, T{{.}}{{end}} any]( + {{- range .Count}} + p{{.}} Parser[In, T{{.}}],{{end}} + f func({{range .Count}}{{if ne . 1}}, {{end}}T{{.}}{{end}}) Out, +) Parser[In, Out] { + return func(s State[In]) (Result[In, Out], error) { + var anyConsumed bool + var failed bool + var msg Message + var next = s +{{range .Count}} + r{{.}}, err := p{{.}}(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r{{.}}.Consumed() + failed, _, msg = r{{.}}.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val{{.}}, next, _ := r{{.}}.Succeeded() +{{end}} + final := f({{range .Count}}{{if ne . 1}}, {{end}}val{{.}}{{end}}) + return Succeed(anyConsumed, final, next, MessageOK(s.Pos())), nil + } +}{{end}}{{end -}} + +// GENERATED FILE. DO NOT EDIT. + +package {{.Package}} +{{range .Count}}{{template "func" .}} + +{{end}} diff --git a/seq.go b/seq.go new file mode 100644 index 0000000..ee5da2b --- /dev/null +++ b/seq.go @@ -0,0 +1,225 @@ +// GENERATED FILE. DO NOT EDIT. + +package gigaparsec + +func Seq2[In, Out, T, T2 any]( + p Parser[In, T], + p2 Parser[In, T2], + f func(T, T2) Out, +) Parser[In, Out] { + return func(s State[In]) (Result[In, Out], error) { + var anyConsumed bool + var failed bool + var msg Message + var next = s + + r, err := p(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r.Consumed() + failed, _, msg = r.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val, next, _ := r.Succeeded() + + r2, err := p2(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r2.Consumed() + failed, _, msg = r2.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val2, next, _ := r2.Succeeded() + + final := f(val, val2) + return Succeed(anyConsumed, final, next, MessageOK(s.Pos())), nil + } +} +func Seq3[In, Out, T, T2, T3 any]( + p Parser[In, T], + p2 Parser[In, T2], + p3 Parser[In, T3], + f func(T, T2, T3) Out, +) Parser[In, Out] { + return func(s State[In]) (Result[In, Out], error) { + var anyConsumed bool + var failed bool + var msg Message + var next = s + + r, err := p(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r.Consumed() + failed, _, msg = r.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val, next, _ := r.Succeeded() + + r2, err := p2(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r2.Consumed() + failed, _, msg = r2.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val2, next, _ := r2.Succeeded() + + r3, err := p3(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r3.Consumed() + failed, _, msg = r3.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val3, next, _ := r3.Succeeded() + + final := f(val, val2, val3) + return Succeed(anyConsumed, final, next, MessageOK(s.Pos())), nil + } +} +func Seq4[In, Out, T, T2, T3, T4 any]( + p Parser[In, T], + p2 Parser[In, T2], + p3 Parser[In, T3], + p4 Parser[In, T4], + f func(T, T2, T3, T4) Out, +) Parser[In, Out] { + return func(s State[In]) (Result[In, Out], error) { + var anyConsumed bool + var failed bool + var msg Message + var next = s + + r, err := p(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r.Consumed() + failed, _, msg = r.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val, next, _ := r.Succeeded() + + r2, err := p2(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r2.Consumed() + failed, _, msg = r2.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val2, next, _ := r2.Succeeded() + + r3, err := p3(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r3.Consumed() + failed, _, msg = r3.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val3, next, _ := r3.Succeeded() + + r4, err := p4(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r4.Consumed() + failed, _, msg = r4.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val4, next, _ := r4.Succeeded() + + final := f(val, val2, val3, val4) + return Succeed(anyConsumed, final, next, MessageOK(s.Pos())), nil + } +} +func Seq5[In, Out, T, T2, T3, T4, T5 any]( + p Parser[In, T], + p2 Parser[In, T2], + p3 Parser[In, T3], + p4 Parser[In, T4], + p5 Parser[In, T5], + f func(T, T2, T3, T4, T5) Out, +) Parser[In, Out] { + return func(s State[In]) (Result[In, Out], error) { + var anyConsumed bool + var failed bool + var msg Message + var next = s + + r, err := p(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r.Consumed() + failed, _, msg = r.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val, next, _ := r.Succeeded() + + r2, err := p2(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r2.Consumed() + failed, _, msg = r2.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val2, next, _ := r2.Succeeded() + + r3, err := p3(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r3.Consumed() + failed, _, msg = r3.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val3, next, _ := r3.Succeeded() + + r4, err := p4(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r4.Consumed() + failed, _, msg = r4.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val4, next, _ := r4.Succeeded() + + r5, err := p5(next) + if err != nil { + return Result[In, Out]{}, err + } + anyConsumed = anyConsumed || r5.Consumed() + failed, _, msg = r5.Failed() + if failed { + return Fail[In, Out](anyConsumed, msg), nil + } + _, _, val5, next, _ := r5.Succeeded() + + final := f(val, val2, val3, val4, val5) + return Succeed(anyConsumed, final, next, MessageOK(s.Pos())), nil + } +} +