diff options
author | Adam Scarr <adam@vektah.net> | 2017-08-13 22:11:27 +1000 |
---|---|---|
committer | Adam Scarr <adam@vektah.net> | 2017-08-13 22:11:27 +1000 |
commit | ddb61bdfc034a683f755dec6ddc80627d2d43522 (patch) | |
tree | 5d3192d70c5d2a4c62a2be8b8d11de2b0455546b /combinator.go | |
parent | 139e7606f4ab68b469438956c378745f51f7b65b (diff) |
Add an Until function
Diffstat (limited to 'combinator.go')
-rw-r--r-- | combinator.go | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/combinator.go b/combinator.go index d7be3f9..4e7e4a5 100644 --- a/combinator.go +++ b/combinator.go @@ -26,7 +26,7 @@ func NoAutoWS(parser Parserish) Parser { parserfied := Parsify(parser) return func(ps *State, node *Result) { oldWS := ps.WS - ps.WS = func(ps *State) {} + ps.WS = NoWhitespace parserfied(ps, node) ps.WS = oldWS } @@ -145,6 +145,36 @@ func Maybe(parser Parserish) Parser { }) } +// Until will consume all input until one of the given parsers match. This is running every parser over every byte, +// so its probably going to be slow. +func Until(parsers ...Parserish) Parser { + parserfied := ParsifyAll(parsers...) + return NewParser("Until()", func(ps *State, node *Result) { + ws := ps.WS + ps.WS = NoWhitespace + defer func() { + ps.WS = ws + }() + startPos := ps.Pos + for ps.Pos < len(ps.Input) { + endPos := ps.Pos + for _, p := range parserfied { + ps.Pos = endPos + + p(ps, node) + + if !ps.Errored() { + node.Token = ps.Input[startPos:endPos] + return + } + ps.Recover() + } + ps.Pos++ + } + node.Token = ps.Input[startPos:ps.Pos] + }) +} + // Bind will set the node .Result when the given parser matches // This is useful for giving a value to keywords and constant literals // like true and false. See the json parser for an example. |