Add an Until function
This commit is contained in:
parent
139e7606f4
commit
ddb61bdfc0
@ -26,7 +26,7 @@ func NoAutoWS(parser Parserish) Parser {
|
|||||||
parserfied := Parsify(parser)
|
parserfied := Parsify(parser)
|
||||||
return func(ps *State, node *Result) {
|
return func(ps *State, node *Result) {
|
||||||
oldWS := ps.WS
|
oldWS := ps.WS
|
||||||
ps.WS = func(ps *State) {}
|
ps.WS = NoWhitespace
|
||||||
parserfied(ps, node)
|
parserfied(ps, node)
|
||||||
ps.WS = oldWS
|
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
|
// Bind will set the node .Result when the given parser matches
|
||||||
// This is useful for giving a value to keywords and constant literals
|
// This is useful for giving a value to keywords and constant literals
|
||||||
// like true and false. See the json parser for an example.
|
// like true and false. See the json parser for an example.
|
||||||
|
@ -181,6 +181,20 @@ func TestMap(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUntil(t *testing.T) {
|
||||||
|
parser := Until("world", ".")
|
||||||
|
|
||||||
|
t.Run("success", func(t *testing.T) {
|
||||||
|
result, _ := runParser("this is the end of the world", parser)
|
||||||
|
require.Equal(t, "this is the end of the ", result.Token)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("eof", func(t *testing.T) {
|
||||||
|
result, _ := runParser("this is the end of it all", parser)
|
||||||
|
require.Equal(t, "this is the end of it all", result.Token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestBind(t *testing.T) {
|
func TestBind(t *testing.T) {
|
||||||
parser := Bind("true", true)
|
parser := Bind("true", true)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user