Add optional parser method

This commit is contained in:
Florian Schroedl
2022-01-20 17:00:00 +01:00
parent 905fd06348
commit 811bf23fe7

View File

@@ -203,6 +203,16 @@ func ignore*(parserFn: Parser -> ParserResult): (Parser -> ParserResult) {.inlin
tokens: parser.tokens,
))
func optional*(parserFn: Parser -> ParserResult): (Parser -> ParserResult) {.inline.} =
## Parse characters and ignore failure
return proc(parser: Parser): ParserResult =
let newParser = parserFn(parser)
if newParser.isOk():
newParser
else:
parser.ok()
func manyUntil*(acceptFn: Parser -> ParserResult, stopFn: Parser -> ParserResult): (Parser -> ParserResult) {.inline.} =
## Parse characters but throw success tokens away
return proc(parser: Parser): ParserResult =
@@ -241,6 +251,7 @@ func choice*(parsers: seq[Parser -> ParserResult]): (Parser -> ParserResult) {.i
proc(x: ParserResult): ParserResult = x,
)
proc parseSeq*(parser: ParserResult, xs: seq[Parser -> ParserResult]): ParserResult =
xs.foldl(a.flatMap(b), parser)
@@ -307,35 +318,10 @@ proc foldBuilder*[T, T2](
onError(err[1])
when isMainModule:
let parseHeadingStars = @[
manyUntil(ch('*'), ch(' ')),
ignore(ch(' '))
let optionalPrefixParser = @[
optional(ch('_')),
str("ABC")
]
let parseHeadingText = @[
anyUntil(endOfStream),
]
type StringBuilderT = string
type StringBuilder = Builder[StringBuilderT]
type StringBuilderResult = BuilderResult[StringBuilderT]
proc stringConcat(typeInfo: StringBuilderT):
(seq[Token], seq[StringBuilderT]) -> seq[StringBuilderT] =
return proc(xs: seq[Token], ys: seq[StringBuilderT]): seq[StringBuilderT] =
return ys & xs.foldl(a & b.value, typeInfo)
let sampleBuilder = StringBuilderResult
.ok(StringBuilder((
parser: initParser("**** Some stars"),
tree: newSeq[StringBuilderT](),
)))
.applyParsersSeq(@[
(parseHeadingStars, stringConcat("Stars: ")),
(parseHeadingText, stringConcat("Text: "))
])
.foldBuilder(
err => &"Error Parsing: {err}",
xs => "Parser Succesfull:\n" & xs.join("\n"),
)
echo sampleBuilder
echo initParserResult("_ABC").parseSeq(optionalPrefixParser)
echo initParserResult("ABC").parseSeq(optionalPrefixParser)