From 88dad17ee3c80dded864ddf4692e5fd327bf3bc7 Mon Sep 17 00:00:00 2001 From: Brandon Dyck Date: Wed, 11 Sep 2024 14:23:08 -0600 Subject: [PATCH] Handle reader errors in Regexp --- bytes/regexp.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/bytes/regexp.go b/bytes/regexp.go index c7c3272..7b0b7c1 100644 --- a/bytes/regexp.go +++ b/bytes/regexp.go @@ -16,6 +16,7 @@ import ( // with the regexp package. type RuneReader struct { cursor cursor.Cursor[byte] + err error } 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) { + defer func() { + rr.err = err + }() var b [4]byte s := b[:] n, next, err := rr.cursor.Read(s) @@ -40,6 +44,10 @@ func (rr *RuneReader) Cursor() cursor.Cursor[byte] { return rr.cursor } +func (rr *RuneReader) Error() error { + return rr.err +} + func Regexp(str string) gigaparsec.Parser[byte, []byte] { if !strings.HasPrefix(str, "^") && !strings.HasPrefix(str, `\A`) { 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) { r := NewRuneReader(input.Cursor()) 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 { return gigaparsec.Fail[byte, []byte](false, gigaparsec.Message{ Pos: input.Pos(), @@ -65,7 +76,7 @@ func Regexp(str string) gigaparsec.Parser[byte, []byte] { n, _, err := input.Cursor().Read(dst) if err != nil { // 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) return gigaparsec.Succeed(true, dst, next, gigaparsec.MessageOK(input.Pos())), nil