From ce07cbc8dad85886d6f331610fb01010f5c6e34f Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 20 Jan 2022 17:00:00 +0100 Subject: [PATCH] Parser transformation --- src/test.nim | 102 ++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/src/test.nim b/src/test.nim index 95191fd..5857f8c 100644 --- a/src/test.nim +++ b/src/test.nim @@ -37,7 +37,7 @@ type ParserResult* = Result[Parser, ParserError] Builder*[T] = tuple[ - parser: ParserResult, + parser: Parser, tree: seq[T] ] BuilderResult*[T] = Result[Builder[T], (Builder[T], string)] @@ -109,7 +109,7 @@ proc `$`*(x: ParserError): string = {errSpace}^ Expected '{expected}' but got '{unexpected}'""" else: "ParseError" -proc initParser(str: string): ParserResult = +proc initParser(str: string): Parser = Parser( state: ParserState( stream: str, @@ -117,7 +117,7 @@ proc initParser(str: string): ParserResult = lastPosition: 0, ), tokens: newSeq[Token](), - ).ok() + ) func ch(expectedChars: set[char]): (Parser -> ParserResult) {.inline.} = return func(parser: Parser): ParserResult = @@ -262,67 +262,71 @@ proc foldTokens[T]( let err = parserResult.error() onError(err) +proc merge[T](t: Builder[T], parser: Parser, tree: seq[T]): Builder[T] = + Builder[T](( + parser, + tree + )) -# proc mapTree[T](builder: BuilderResult[T], fn: Builder[T] -> Builder[T]) = -# builder.map(proc(b: Builder) = -# (@parser, @builder) := builder -# b -# ) +proc applyParsers[T]( + builder: Builder[T], + parsers: seq[Parser -> ParserResult], + tokenFoldFn: (seq[Token], seq[T]) -> seq[T], +): BuilderResult[T] = + # proc nested(b: Builder[T]): BuilderResult[T] = + let newParser = ParserResult.ok(Parser( + state: builder[0].state, + tokens: @[] + )) + .parseSeq(parsers) -# proc applyParserTokens[T](builder: BuilderResult, fn: seq[Token] -> T): BuilderResult = -# (@parser, @builder) := builder -# parser.foldTokens( -# proc(x: ParserError): BuilderResult = err(x), -# proc(xs: seq[Token]): BuilderResult = ok(parser, builder.map()), -# ) + newParser + .foldTokens( + (err: ParserError) => BuilderResult[T].err((builder, "foo")), + (newTokens: seq[Token]) => BuilderResult[T].ok( + builder.merge(newParser.unsafeGet(), tokenFoldFn(newTokens, builder[1])) + ), + ) + +proc mapTree[T](builder: BuilderResult[T], fn: seq[T] -> seq[T]): BuilderResult[T] = + builder.map(proc(b: Builder[T]): Builder[T] = Builder(( + parser: b[0], + tree: fn(b[1]), + ))) 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 initParser("BB").parseSeq(@[ - # choice(@[ch(Digits), ch('B')]), - # ]) - let parseHeadingStars = @[ manyUntil(ch('*'), ch(' ')), ignore(ch(' ')) ] - # proc buildHeadingStars(stars: ParserResult, builder: OrgElement): OrgElement = - # builder.level = stars.get().len - - # let todoKeywords = @[ - # "TODO", - # ] - # let todoDoneKeywords = @[ - # "DONE", - # ] - # let parseHeadingTodo = @[ - - # ] # let buildHeadingStars = - type StringBuilder = BuilderResult[string] + type StringBuilderT = string + type StringBuilder = Builder[StringBuilderT] + type StringBuilderResult = BuilderResult[StringBuilderT] - let sampleBuilder: StringBuilder = StringBuilder.ok(Builder(( - parser: initParser(""), - tree: newSeq[string](), + 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 = StringBuilderResult + .ok(StringBuilder(( + parser: initParser("**** Some stars"), + tree: newSeq[StringBuilderT](), ))) + .flatMap((x: StringBuilder) => x.applyParsers( + parsers = parseHeadingStars, + tokenFoldFn = stringConcat("Stars: ") + )) + .flatMap((x: StringBuilder) => x.applyParsers( + parsers = parseHeadingStars, + tokenFoldFn = stringConcat("Stars: ") + )) + echo sampleBuilder - # .mapTree((x: string) => x) # @[