Handle reader errors in Regexp

This commit is contained in:
Brandon Dyck 2024-09-11 14:23:08 -06:00
parent 065bb70138
commit 88dad17ee3

View File

@ -16,6 +16,7 @@ import (
// with the regexp package. // with the regexp package.
type RuneReader struct { type RuneReader struct {
cursor cursor.Cursor[byte] cursor cursor.Cursor[byte]
err error
} }
func NewRuneReader(c cursor.Cursor[byte]) *RuneReader { func NewRuneReader(c cursor.Cursor[byte]) *RuneReader {
@ -23,6 +24,9 @@ func NewRuneReader(c cursor.Cursor[byte]) *RuneReader {
} }
func (rr *RuneReader) ReadRune() (r rune, size int, err error) { func (rr *RuneReader) ReadRune() (r rune, size int, err error) {
defer func() {
rr.err = err
}()
var b [4]byte var b [4]byte
s := b[:] s := b[:]
n, next, err := rr.cursor.Read(s) n, next, err := rr.cursor.Read(s)
@ -40,6 +44,10 @@ func (rr *RuneReader) Cursor() cursor.Cursor[byte] {
return rr.cursor return rr.cursor
} }
func (rr *RuneReader) Error() error {
return rr.err
}
func Regexp(str string) gigaparsec.Parser[byte, []byte] { func Regexp(str string) gigaparsec.Parser[byte, []byte] {
if !strings.HasPrefix(str, "^") && !strings.HasPrefix(str, `\A`) { if !strings.HasPrefix(str, "^") && !strings.HasPrefix(str, `\A`) {
str = "^" + str str = "^" + str
@ -49,7 +57,10 @@ func Regexp(str string) gigaparsec.Parser[byte, []byte] {
return func(input gigaparsec.State[byte]) (gigaparsec.Result[byte, []byte], error) { return func(input gigaparsec.State[byte]) (gigaparsec.Result[byte, []byte], error) {
r := NewRuneReader(input.Cursor()) r := NewRuneReader(input.Cursor())
idx := re.FindReaderIndex(r) idx := re.FindReaderIndex(r)
// TODO Check error from r; this requires an Error() method on cursor.RuneReader. err := r.Error()
if err != nil && !errors.Is(err, io.EOF) {
return gigaparsec.Result[byte, []byte]{}, fmt.Errorf("Regexp: reader error: %w", err)
}
if idx == nil { if idx == nil {
return gigaparsec.Fail[byte, []byte](false, gigaparsec.Message{ return gigaparsec.Fail[byte, []byte](false, gigaparsec.Message{
Pos: input.Pos(), Pos: input.Pos(),
@ -65,7 +76,7 @@ func Regexp(str string) gigaparsec.Parser[byte, []byte] {
n, _, err := input.Cursor().Read(dst) n, _, err := input.Cursor().Read(dst)
if err != nil { if err != nil {
// If we can't access those same bytes again, something is wrong. // If we can't access those same bytes again, something is wrong.
return gigaparsec.Result[byte, []byte]{}, fmt.Errorf("Regex: unexpected error: %w", err) return gigaparsec.Result[byte, []byte]{}, fmt.Errorf("Regexp: unexpected error: %w", err)
} }
next := input.At(input.Pos() + n) next := input.At(input.Pos() + n)
return gigaparsec.Succeed(true, dst, next, gigaparsec.MessageOK(input.Pos())), nil return gigaparsec.Succeed(true, dst, next, gigaparsec.MessageOK(input.Pos())), nil