Add peek functions

This commit is contained in:
Florian Schroedl
2022-08-28 18:19:53 +02:00
parent bc7525e353
commit 0ba76a1203

View File

@@ -185,6 +185,27 @@ proc ignore*(parserFn: parserFnT): parserFnT {.inline.} =
tokens: parser.tokens,
))
proc peek*(amount: int, parserFn: parserFnT): parserFnT {.inline.} =
## Creates parser function with a nested `parserFn`:
## Parses using the `parserFn` but dont capture the resulting tokens and keep the current position.
return proc(parser: Parser): ParserResult =
let state = parser.state
let newIndex = state.position + amount
let newParser = initParser(
stream = state.stream,
tokens = parser.tokens,
position = newIndex,
lastPosition = state.position,
)
parserFn(newParser)
.map(p => parser)
proc peek1*(parserFn: parserFnT): parserFnT = peek(1, parserFn)
proc peekCurrent*(parserFn: parserFnT): parserFnT = peek(0, parserFn)
proc peekBack1*(parserFn: parserFnT): parserFnT = peek(-1, parserFn)
proc manyUntil*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.inline.} =
## Creates parser function with a nested `acceptFn` parser function until the `stopFn` parserFunction is met:
## Parses until the `stopFn` is reached or on an errror.
@@ -330,6 +351,12 @@ when isMainModule:
# ignore
assert testParser123.flatMap(ignore(ch('1'))).tokensToString() == ""
# peek
assert testParser123.flatMap(ch('1') + peekCurrent(ch('2')) + ch('2')).tokensToString() == "12"
assert testParser123.flatMap(ch('1') + peekCurrent(ch('1'))).isErr() == true
assert testParser123.flatMap(peekCurrent(startOfStream)).isOk() == true
assert testParser123.flatMap(ch('1') + peekBack1(startOfStream)).isOk() == true
# manyUntil
assert testAbc1Parser.flatMap(manyUntil(anyCh, digit)).tokensToString() == "abc"