Implemented csexp.Parse
This commit is contained in:
parent
8261a876d1
commit
2d3c8748be
@ -2,10 +2,15 @@ package csexp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.codemonkeysoftware.net/b/gigaparsec"
|
||||||
|
pbytes "git.codemonkeysoftware.net/b/gigaparsec/bytes"
|
||||||
|
"git.codemonkeysoftware.net/b/gigaparsec/cursor"
|
||||||
"git.codemonkeysoftware.net/b/peachy-go/shortcircuit"
|
"git.codemonkeysoftware.net/b/peachy-go/shortcircuit"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -82,6 +87,73 @@ func (l List) Clone() Sexp {
|
|||||||
return l2
|
return l2
|
||||||
}
|
}
|
||||||
|
|
||||||
func Parse(data []byte) (Sexp, error) {
|
var parseLength = gigaparsec.Map(pbytes.Regexp(`0|[1-9]\d*`), func(s string) uint64 {
|
||||||
return nil, nil
|
n, err := strconv.ParseUint(s, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
})
|
||||||
|
|
||||||
|
func acceptN(n uint64) gigaparsec.Parser[byte, []byte] {
|
||||||
|
expected := fmt.Sprintf("%d bytes", n)
|
||||||
|
return func(s gigaparsec.State[byte]) (gigaparsec.Result[byte, []byte], error) {
|
||||||
|
if n == 0 {
|
||||||
|
return gigaparsec.Succeed[byte, []byte](true, nil, s, gigaparsec.MessageOK(s.Pos())), nil
|
||||||
|
}
|
||||||
|
dst := make([]byte, n)
|
||||||
|
_, next, err := s.Read(dst)
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
return gigaparsec.Fail[byte, []byte](false, gigaparsec.MessageEnd(s.Pos(), expected)), nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return gigaparsec.Result[byte, []byte]{}, err
|
||||||
|
}
|
||||||
|
return gigaparsec.Succeed(true, dst, next, gigaparsec.MessageOK(s.Pos())), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var parseAtom = gigaparsec.Map(gigaparsec.Bind2(
|
||||||
|
parseLength,
|
||||||
|
gigaparsec.Pipe[byte, byte, uint64](gigaparsec.Match[byte](':')),
|
||||||
|
acceptN,
|
||||||
|
), func(s []byte) Sexp { return Atom(s) })
|
||||||
|
|
||||||
|
func parseSexp(input gigaparsec.State[byte]) (gigaparsec.Result[byte, Sexp], error) {
|
||||||
|
return gigaparsec.Choose(parseAtom, parseList)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRestOfList(input gigaparsec.State[byte]) (gigaparsec.Result[byte, []Sexp], error) {
|
||||||
|
return gigaparsec.Choose(
|
||||||
|
gigaparsec.Map(gigaparsec.Match[byte](')'), func(byte) []Sexp { return nil }),
|
||||||
|
gigaparsec.Bind(
|
||||||
|
parseSexp,
|
||||||
|
func(s Sexp) gigaparsec.Parser[byte, []Sexp] {
|
||||||
|
return gigaparsec.Map(
|
||||||
|
parseRestOfList,
|
||||||
|
func(rest []Sexp) []Sexp { return append([]Sexp{s}, rest...) },
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseList(input gigaparsec.State[byte]) (gigaparsec.Result[byte, Sexp], error) {
|
||||||
|
return gigaparsec.Map(gigaparsec.Seq2(
|
||||||
|
gigaparsec.Match[byte]('('),
|
||||||
|
parseRestOfList,
|
||||||
|
func(_ byte, rest []Sexp) []Sexp { return rest },
|
||||||
|
), func(sexps []Sexp) Sexp { return List(sexps) })(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(data []byte) (Sexp, error) {
|
||||||
|
result, err := parseSexp(gigaparsec.MakeState(cursor.NewSlice(data)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("csexp.Parse: %w", err)
|
||||||
|
}
|
||||||
|
if failed, _, msg := result.Failed(); failed {
|
||||||
|
return nil, fmt.Errorf("csexp.Parse: %v", msg)
|
||||||
|
}
|
||||||
|
_, _, sexp, _, _ := result.Succeeded()
|
||||||
|
return sexp, nil
|
||||||
}
|
}
|
||||||
|
9
go.mod
9
go.mod
@ -1,10 +1,13 @@
|
|||||||
module git.codemonkeysoftware.net/b/peachy-go
|
module git.codemonkeysoftware.net/b/peachy-go
|
||||||
|
|
||||||
go 1.22.1
|
go 1.23
|
||||||
|
|
||||||
|
toolchain go1.23.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.codemonkeysoftware.net/b/gigaparsec v0.0.0-20240917174243-4fa3c2a46611
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
||||||
github.com/shoenig/test v1.9.0
|
github.com/shoenig/test v1.11.0
|
||||||
pgregory.net/rapid v1.1.0
|
pgregory.net/rapid v1.1.0
|
||||||
zombiezen.com/go/sqlite v1.3.0
|
zombiezen.com/go/sqlite v1.3.0
|
||||||
)
|
)
|
||||||
@ -22,3 +25,5 @@ require (
|
|||||||
modernc.org/memory v1.7.2 // indirect
|
modernc.org/memory v1.7.2 // indirect
|
||||||
modernc.org/sqlite v1.29.1 // indirect
|
modernc.org/sqlite v1.29.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace git.codemonkeysoftware.net/b/gigaparsec v0.0.0-20240917174243-4fa3c2a46611 => ../gigaparsec
|
||||||
|
4
go.sum
4
go.sum
@ -12,8 +12,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd
|
|||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/shoenig/test v1.9.0 h1:PWtSP8Ty2N0F+Ndh4p0a8SOofFmTEIX/nYh/c3vRCbo=
|
github.com/shoenig/test v1.11.0 h1:NoPa5GIoBwuqzIviCrnUJa+t5Xb4xi5Z+zODJnIDsEQ=
|
||||||
github.com/shoenig/test v1.9.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI=
|
github.com/shoenig/test v1.11.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
|
Loading…
Reference in New Issue
Block a user