diff options
author | Adam Scarr <adam@vektah.net> | 2017-08-13 15:28:43 +1000 |
---|---|---|
committer | Adam Scarr <adam@vektah.net> | 2017-08-13 15:28:43 +1000 |
commit | 79b7cc082cac1904b87bbe7996df5a8824f7c2d8 (patch) | |
tree | 6f97bfaf20629a77fc2a847fa82b0bcb5a5cc2af /combinator.go | |
parent | e30b92276464f1a7cbd9e3772f315c990fac2073 (diff) |
Add one byte prediction to Any()
Diffstat (limited to 'combinator.go')
-rw-r--r-- | combinator.go | 31 |
1 files changed, 29 insertions, 2 deletions
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 } |