Implement anyUntil using endOfStream

This commit is contained in:
Florian Schroedl
2022-01-20 17:00:00 +01:00
parent 1d7d669146
commit dfb4baa8c8

View File

@@ -173,6 +173,17 @@ func ch(expectedChar: char): (Parser -> ParserResult) {.inline.} =
parser: parser,
))
proc endOfStream(parser: Parser): ParserResult =
if parser.state.position == parser.state.stream.len - 1:
ok(parser)
else:
err(ParserError(
kind: endOfStringErr,
expected: &"EndOfString",
index: parser.state.position,
parser: parser,
))
func ignore(parserFn: Parser -> ParserResult): (Parser -> ParserResult) {.inline.} =
## Parse characters but throw success tokens away
return proc(parser: Parser): ParserResult =
@@ -190,6 +201,9 @@ func manyUntil(acceptFn: Parser -> ParserResult, stopFn: Parser -> ParserResult)
res = res.flatMap(acceptFn)
return res
func anyUntil(stopFn: Parser -> ParserResult): (Parser -> ParserResult) {.inline.} =
manyUntil(ch(AllChars), stopFn)
proc parseSeq(parser: ParserResult, xs: seq[Parser -> ParserResult]): ParserResult =
xs.foldl(a.flatMap(b), parser)
@@ -212,31 +226,33 @@ proc foldTokens[T](
onError(err)
when isMainModule:
let fooParser = initParser("FOO___BAR")
.parseSeq(@[
str("FOO"),
ignore(str("___")),
ch('B'),
ch('B'),
ch('A'),
ch('R'),
])
.foldTokens(
err => $err,
xs => xs.foldl(a & b.value, "")
)
# echo fooParser
# let fooParser = initParser("FOO___BAR")
# .parseSeq(@[
# str("FOO"),
# ignore(str("___")),
# ch('B'),
# ch('B'),
# ch('A'),
# ch('R'),
# ])
# .foldTokens(
# err => $err,
# xs => xs.foldl(a & b.value, "")
# )
let manUntilTest = initParser("AAAB")
.flatMap(manyUntil(ch('B'), ch('B')))
echo initParser("**** Foo")
.parseSeq(@[
manyUntil(ch('*'), ch(' ')),
ignore(ch ' '),
str("Foo")
echo initParser("_FOO___BAR").parseSeq(@[
anyUntil(endOfStream),
])
# .parseSeq(@[
# manyUntil(ch('*'), ch(' ')),
# ignore(ch ' '),
# str("Foo")
# ])
# echo initParser("AAAB").flatMap(ch 'b')
# # .flatMap(ch('A'))
# # .flatMap(ch('B'))