diff --git a/combinator.go b/combinator.go index 5b0d584..ae4d31c 100644 --- a/combinator.go +++ b/combinator.go @@ -35,7 +35,6 @@ func NoAutoWS(parser Parserish) Parser { // Any matches the first successful parser and returns its result func Any(parsers ...Parserish) Parser { parserfied := ParsifyAll(parsers...) - // Records which parser was successful for each byte, and will use it first next time. return NewParser("Any()", func(ps *State, node *Result) { ps.WS(ps) @@ -45,13 +44,7 @@ func Any(parsers ...Parserish) Parser { } startpos := ps.Pos - longestError := ps.Error - if ps.Cut <= startpos { - ps.Recover() - } else { - return - } - + var longestError Error for _, parser := range parserfied { parser(ps, node) if ps.Errored() { @@ -72,14 +65,14 @@ func Any(parsers ...Parserish) Parser { }) } -// Some matches one or more parsers and returns the value as .Child[n] +// Some matches zero or more parsers and returns the value as .Child[n] // an optional separator can be provided and that value will be consumed // but not returned. Only one separator can be provided. func Some(parser Parserish, separator ...Parserish) Parser { return NewParser("Some()", manyImpl(0, parser, separator...)) } -// Many matches zero or more parsers and returns the value as .Child[n] +// Many matches one or more parsers and returns the value as .Child[n] // an optional separator can be provided and that value will be consumed // but not returned. Only one separator can be provided. func Many(parser Parserish, separator ...Parserish) Parser { diff --git a/combinator_test.go b/combinator_test.go index b315b37..17a0c11 100644 --- a/combinator_test.go +++ b/combinator_test.go @@ -88,6 +88,17 @@ func TestAny(t *testing.T) { }) }) + + // see https://github.com/vektah/goparsify/issues/3 + t.Run("doesn't succeed early after caller error", func(t *testing.T) { + str := "str" + str1 := Seq("str", "1") + str2 := Any("str2") + p := Any(str1, str2, str) + _, ps := runParser("str", p) + require.False(t, ps.Errored()) + require.Equal(t, "", ps.Get()) + }) } func TestSome(t *testing.T) { diff --git a/errors.go b/errors.go index 3f8787c..e684e14 100644 --- a/errors.go +++ b/errors.go @@ -17,10 +17,10 @@ func (e *Error) Error() string { return fmt.Sprintf("offset %d: expected %s", e. // UnparsedInputError is returned by Run when not all of the input was consumed. There may still be a valid result type UnparsedInputError struct { - remaining string + Remaining string } // Error satisfies the golang error interface func (e UnparsedInputError) Error() string { - return "left unparsed: " + e.remaining + return "left unparsed: " + e.Remaining }