Return error messages from Return and Satisfy
This commit is contained in:
parent
0a1fe0821a
commit
b3b90b7e6b
@ -18,16 +18,18 @@ type Result[In, Out any] struct {
|
|||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
Pos uint64
|
Pos uint64
|
||||||
Msg string
|
Got string
|
||||||
Expected []string
|
Expected []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ParseError struct {
|
func MessageOK(pos uint64) Message { return Message{Pos: pos} }
|
||||||
Message
|
|
||||||
}
|
func MessageEnd(pos uint64) Message { return Message{Pos: pos, Got: "end of input"} }
|
||||||
|
|
||||||
|
type ParseError Message
|
||||||
|
|
||||||
func (pe ParseError) Error() string {
|
func (pe ParseError) Error() string {
|
||||||
return fmt.Sprintf("parse error: %d: %s", pe.Message.Pos, pe.Message.Msg)
|
return fmt.Sprintf("parse error: %d: %s", pe.Pos, pe.Got)
|
||||||
}
|
}
|
||||||
|
|
||||||
type State[T any] cursor.Cursor[T]
|
type State[T any] cursor.Cursor[T]
|
||||||
@ -36,24 +38,35 @@ type Parser[In, Out any] func(State[In]) (consumed bool, reply Result[In, Out],
|
|||||||
|
|
||||||
func Return[In, Out any](value Out) Parser[In, Out] {
|
func Return[In, Out any](value Out) Parser[In, Out] {
|
||||||
return func(state State[In]) (bool, Result[In, Out], error) {
|
return func(state State[In]) (bool, Result[In, Out], error) {
|
||||||
return false, Result[In, Out]{Value: value, State: state}, nil
|
return false, Result[In, Out]{
|
||||||
|
Value: value,
|
||||||
|
State: state,
|
||||||
|
Message: MessageOK(state.Pos()),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Satisfy[T any](pred func(T) bool) Parser[T, T] {
|
func Satisfy[T any](pred func(T) bool) Parser[T, T] {
|
||||||
return func(state State[T]) (bool, Result[T, T], error) {
|
return func(state State[T]) (bool, Result[T, T], error) {
|
||||||
b := make([]T, 1)
|
token := make([]T, 1)
|
||||||
n, next, err := state.Read(b)
|
n, next, err := state.Read(token)
|
||||||
if errors.Is(err, io.EOF) {
|
if errors.Is(err, io.EOF) {
|
||||||
return false, Result[T, T]{}, ErrNoParse
|
return false, Result[T, T]{}, ParseError(MessageEnd(state.Pos()))
|
||||||
}
|
}
|
||||||
if n != 1 {
|
if n != 1 {
|
||||||
panic(fmt.Sprintf("expected 1 element from Read, but got %d", n))
|
panic(fmt.Sprintf("expected 1 element from Read, but got %d", n))
|
||||||
}
|
}
|
||||||
if pred(b[0]) {
|
if pred(token[0]) {
|
||||||
return true, Result[T, T]{Value: b[0], State: next}, nil
|
return true, Result[T, T]{
|
||||||
|
Value: token[0],
|
||||||
|
State: next,
|
||||||
|
Message: MessageOK(state.Pos()),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return false, Result[T, T]{}, ParseError{
|
||||||
|
Pos: state.Pos(),
|
||||||
|
Got: fmt.Sprint(token),
|
||||||
}
|
}
|
||||||
return false, Result[T, T]{}, ErrNoParse
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +81,7 @@ func Bind[In, A, B any](p Parser[In, A], f func(A) Parser[In, B]) Parser[In, B]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Add error propagation
|
||||||
func Choose[In, Out any](p, q Parser[In, Out]) Parser[In, Out] {
|
func Choose[In, Out any](p, q Parser[In, Out]) Parser[In, Out] {
|
||||||
return func(input State[In]) (bool, Result[In, Out], error) {
|
return func(input State[In]) (bool, Result[In, Out], error) {
|
||||||
consumedP, replyP, errP := p(input)
|
consumedP, replyP, errP := p(input)
|
||||||
|
Loading…
Reference in New Issue
Block a user