From 79b7cc082cac1904b87bbe7996df5a8824f7c2d8 Mon Sep 17 00:00:00 2001 From: Adam Scarr Date: Sun, 13 Aug 2017 15:28:43 +1000 Subject: Add one byte prediction to Any() --- combinator.go | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'combinator.go') diff --git a/combinator.go b/combinator.go index 1572e6c..01386e6 100644 --- a/combinator.go +++ b/combinator.go @@ -38,14 +38,40 @@ func NoAutoWS(parser Parserish) Parser { // Any matches the first successful parser and returns its result func Any(parsers ...Parserish) Parser { parserfied := ParsifyAll(parsers...) + // For + predictor := [255]int{} return NewParser("Any()", func(ps *State) Result { + if ps.Pos >= len(ps.Input) { + ps.ErrorHere("!EOF") + return Result{} + } longestError := Error{} startpos := ps.Pos - for _, parser := range parserfied { + predictorChar := ps.Input[startpos] + predicted := predictor[predictorChar] + + node := parserfied[predicted](ps) + if !ps.Errored() { + return node + } + + if ps.Error.pos >= longestError.pos { + longestError = ps.Error + } + if ps.Cut <= startpos { + ps.Recover() + } else { + return node + } + + for i, parser := range parserfied { + if i == predicted { + continue + } node := parser(ps) if ps.Errored() { - if ps.Error.pos > longestError.pos { + if ps.Error.pos >= longestError.pos { longestError = ps.Error } if ps.Cut > startpos { @@ -54,6 +80,7 @@ func Any(parsers ...Parserish) Parser { ps.Recover() continue } + predictor[predictorChar] = i return node } -- cgit v1.2.3