From b8ab82f95ccfbfe5e12a5fa8c31e2e9b3c44c3b2 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Fri, 19 Aug 2022 16:10:42 +0200 Subject: [PATCH] Use proc, fn and const dont work --- TODO.org | 2 +- src_v2/parser/builder_api.nim | 92 ------------------------------ src_v2/parser/parser_internals.nim | 83 +++++++++++++++------------ src_v2/parser/parser_types.nim | 38 ++++++------ src_v2/parser/test.nim | 11 ++++ src_v2/parser/utils.nim | 31 ---------- 6 files changed, 79 insertions(+), 178 deletions(-) delete mode 100644 src_v2/parser/builder_api.nim create mode 100644 src_v2/parser/test.nim delete mode 100644 src_v2/parser/utils.nim diff --git a/TODO.org b/TODO.org index f9045ad..6e3a992 100644 --- a/TODO.org +++ b/TODO.org @@ -28,7 +28,7 @@ ** TODO Headline content parser :LOGBOOK: -CLOCK: [2022-08-09 Tue 17:51] +CLOCK: [2022-08-09 Tue 17:51]--[2022-08-09 Tue 19:51] => 2:00 :END: So I've had some heavy misconceptions while working on the content, diff --git a/src_v2/parser/builder_api.nim b/src_v2/parser/builder_api.nim deleted file mode 100644 index d6ad42e..0000000 --- a/src_v2/parser/builder_api.nim +++ /dev/null @@ -1,92 +0,0 @@ -import std/sugar -import std/collections/sequtils -import std/strformat -import std/strutils -import results -import fusion/matching -import ./parser_internals -import ./parser_types - -# proc tryParseBuildOrg*[T]( -# builder: Builder[T], -# builderFns: seq[ -# Builder[T] -> BuilderResult[T] -# ], -# stopAtParserFn = endOfStream -# ): BuilderResult[T] = - -# # Mutating accumulators -# var builderAcc: BuilderResult[T] = BuilderResult.ok(builder) - -# while builderAcc.isOk() and builderAcc.tryParser(stopAtParserFn).isErr() -# for fn in builderFns: -# fn - -proc tryParseBuild*[T]( - builder: Builder[T], - builderFns: seq[tuple[ - parserFn: Parser -> ParserResult, - builderFn: seq[ParserToken] -> seq[T], - ]], - defaultBuilderFn: seq[ParserToken] -> seq[T], - stopAtParserFn = newline, - concatFn = concat[T], -): BuilderResult[T] = - ## Parse text in `builder` by checking the `builderFns` list for a sucessful `parserFn`. - ## The `ok` `parserFn` result will be merged into the `Builder[T].tree` by using the `concatFn`. - ## Otherwise continue taking any character until the `stopAtParserFn` condition is found. - ## Any non-matching tokens will be converted using the `defaultBuilderFn`. - let (parser, tree) = builder - - # Mutating accumulators - var parserAcc: ParserResult = ParserResult.ok(parser) - var builderAcc: Builder[T] = builder - - while parserAcc.isOk() and parserAcc.flatMap(stopAtParserFn).isErr(): - # Empty the parser tokens as we want to seperate them for the next parser in the sequence - let emptyParser = parserAcc.map(emptyTokens) - - # Find the first matching parser and convert its tokens - var found = false - for fn in builderFns: - let (parserFn, builderFn) = fn - - let parseResult = emptyParser.flatMap(parserFn) - if parseResult.isOk(): - let okParser = parseResult.unsafeGet() - - # Convert all previous unmatched tokens via the `defaultBuilderTokens` - let defaultBuilderTokens = parserAcc - .foldTokens( - onError = _ => newSeq[T](), - onSuccess = defaultBuilderFn, - ) - - found = true - parserAcc = parseResult.map(emptyTokens) - builderAcc = builder.initBuilder( - okParser, - concatFn( - builderAcc.tree, - defaultBuilderTokens, - builderFn(okParser.tokens), - ) - ) - break - - if not found: - parserAcc = parserAcc.flatMap(anyCh) - - let defaultBuilderTokens = parserAcc - .foldTokens( - onError = _ => newSeq[T](), - onSuccess = defaultBuilderFn, - ) - - BuilderResult[T].ok(builder.initBuilder( - builderAcc.parser, - concatFn( - builderAcc.tree, - defaultBuilderTokens, - ), - )) diff --git a/src_v2/parser/parser_internals.nim b/src_v2/parser/parser_internals.nim index 739889d..173263f 100644 --- a/src_v2/parser/parser_internals.nim +++ b/src_v2/parser/parser_internals.nim @@ -14,12 +14,12 @@ import ./parser_types # -- Types -type parserFnT = proc(t0: Parser): ParserResult {.nosideeffect.} +type parserFnT = proc(t0: Parser): ParserResult # -- Utilities -func lookBack*(count: int): (parserFnT) = - return func(parser: Parser): ParserResult = +proc lookBack*(count: int): (parserFnT) = + return proc(parser: Parser): ParserResult = let state = parser.state let newIndex = state.position - 1 @@ -32,10 +32,10 @@ func lookBack*(count: int): (parserFnT) = tokens: parser.tokens, ).ok() -# -- Parsing Functions +# -- Parsing Proctions -func ch*(expectedChars: set[char]): parserFnT {.inline.} = - return func(parser: Parser): ParserResult = +proc ch*(expectedChars: set[char]): parserFnT {.inline.} = + return proc(parser: Parser): ParserResult = let state = parser.state let newIndex = state.position + 1 @@ -66,8 +66,8 @@ func ch*(expectedChars: set[char]): parserFnT {.inline.} = parser: parser, )) -func ch*(expectedChar: char): parserFnT {.inline.} = - return func(parser: Parser): ParserResult = +proc ch*(expectedChar: char): parserFnT {.inline.} = + return proc(parser: Parser): ParserResult = let state = parser.state let newIndex = state.position + 1 @@ -98,10 +98,10 @@ func ch*(expectedChar: char): parserFnT {.inline.} = parser: parser, )) -const anyCh* = ch(AllChars) +let anyCh* = ch(AllChars) -func str*(s: string): parserFnT {.inline.} = - return func(parser: Parser): ParserResult = +proc str*(s: string): parserFnT {.inline.} = + return proc(parser: Parser): ParserResult = var p = parser.ok() for c in s.items: p = p.flatMap(ch(c)) @@ -109,9 +109,9 @@ func str*(s: string): parserFnT {.inline.} = # -- Parsing API -func optional*(parserFn: parserFnT): parserFnT {.inline.} = +proc optional*(parserFn: parserFnT): parserFnT {.inline.} = ## Parse characters and ignore failure - return func(parser: Parser): ParserResult = + return proc(parser: Parser): ParserResult = let newParser = parserFn(parser) if newParser.isOk(): @@ -119,18 +119,18 @@ func optional*(parserFn: parserFnT): parserFnT {.inline.} = else: parser.ok() -func ignore*(parserFn: parserFnT): parserFnT {.inline.} = +proc ignore*(parserFn: parserFnT): parserFnT {.inline.} = ## Parse characters but throw success tokens away - return func(parser: Parser): ParserResult = + return proc(parser: Parser): ParserResult = return parserFn(parser) .map((x: Parser) => Parser( state: x.state, tokens: parser.tokens, )) -func manyUntilPerformant*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.inline.} = +proc manyUntilPerformant*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.inline.} = ## Parse characters but throw success tokens away - return func(parser: Parser): ParserResult = + return proc(parser: Parser): ParserResult = let startPosition = parser.state.position var res: ParserResult = parser.ok() @@ -151,22 +151,22 @@ func manyUntilPerformant*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.i ] )) -func anyUntilPerformant*(stopFn: parserFnT): parserFnT {.inline.} = +proc anyUntilPerformant*(stopFn: parserFnT): parserFnT {.inline.} = manyUntilPerformant(ch(AllChars), stopFn) -func manyUntil*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.inline.} = +proc manyUntil*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.inline.} = ## Parse characters but throw success tokens away - return func(parser: Parser): ParserResult = + return proc(parser: Parser): ParserResult = var res: ParserResult = parser.ok() while res.isOk() and res.flatMap(stopFn).isErr(): res = res.flatMap(acceptFn) return res -func anyUntil*(stopFn: parserFnT): parserFnT {.inline.} = +proc anyUntil*(stopFn: parserFnT): parserFnT {.inline.} = manyUntil(anyCh, stopFn) -func choice*(parsers: seq[parserFnT]): parserFnT {.inline} = - return func(parser: Parser): ParserResult {.closure, nosideeffect.} = +proc choice*(parsers: seq[parserFnT]): parserFnT {.inline} = + return proc(parser: Parser): ParserResult {.closure.} = var errors: seq[ParserResult] = newSeq[ParserResult]() var found = Nothing[ParserResult]() @@ -181,7 +181,7 @@ func choice*(parsers: seq[parserFnT]): parserFnT {.inline} = return found .fold( - func(): ParserResult = + proc(): ParserResult = let prettyErrors = errors.map((x: ParserResult) => x.error().expected) err(ParserError( kind: choiceMismatchErr, @@ -190,21 +190,21 @@ func choice*(parsers: seq[parserFnT]): parserFnT {.inline} = unexpected: errors[0].error().unexpected, parser: parser, )), - func(x: ParserResult): ParserResult = x, + proc(x: ParserResult): ParserResult = x, ) -func `+`*(parserFnA: parserFnT, parserFnB: parserFnT): parserFnT {.inline.} = +proc `+`*(parserFnA: parserFnT, parserFnB: parserFnT): parserFnT {.inline.} = ## Parse characters and ignore failure - return func(parser: Parser): ParserResult = + return proc(parser: Parser): ParserResult = parserFnA(parser).flatMap(parserFnB) -func parseSeq*(parser: ParserResult, xs: seq[parserFnT]): ParserResult = +proc parseSeq*(parser: ParserResult, xs: seq[parserFnT]): ParserResult {.inline.} = xs.foldl(a.flatMap(b), parser) # -- Parsing Aliases -func endOfStream*(parser: Parser): ParserResult = +proc endOfStream*(parser: Parser): ParserResult = let index = parser.state.position + 1 if index == parser.state.stream.len: ok(parser) @@ -216,27 +216,40 @@ func endOfStream*(parser: Parser): ParserResult = parser: parser, )) -const newlineParser = choice(@[ +let newlineParser = choice(@[ ch(NewLines), endOfStream, ]) -func newline*(parser: Parser): ParserResult = +proc newline*(parser: Parser): ParserResult = newlineParser(parser) .mapErr((x: ParserError) => x.setErrorExpectedField("Newline")) -const whitespaceParser = choice(@[ +let whitespaceParser = choice(@[ ch(Whitespace), newlineParser, ]) -func whitespace*(parser: Parser): ParserResult = +proc whitespace*(parser: Parser): ParserResult = whitespaceParser(parser) .mapErr((x: ParserError) => x.setErrorExpectedField("Whitespace")) # -- Parsing Helpers -const parseBetweenDelimiter* = func(start: parserFnT, stop: parserFnT): parserFnT {.closure.} = +let parseBetweenDelimiter* = proc(start: parserFnT, stop: parserFnT): parserFnT {.closure.} = ignore(start) + anyUntil(stop + whitespace) + ignore(start) -const parseBetweenPair* = func(delimiterParser: parserFnT): parserFnT {.closure.} = +let parseBetweenPair* = proc(delimiterParser: parserFnT): parserFnT {.closure.} = parseBetweenDelimiter(delimiterParser, delimiterParser) + +# -- Tests + +when isMainModule: + let test1 = initParserResult("123") + + let ch1 = ch('1') + let chDigits = @[ch(Digits)] + + # echo type ch1 + # echo test1.flatMap((x: Parser) => ParserResult.ok(x)) + echo test1.flatMap(newlineParser) + # .flatMap(ch1) diff --git a/src_v2/parser/parser_types.nim b/src_v2/parser/parser_types.nim index 4ea88c2..82b519b 100644 --- a/src_v2/parser/parser_types.nim +++ b/src_v2/parser/parser_types.nim @@ -70,10 +70,10 @@ func initParser*(str: string): Parser = tokens: newSeq[ParserToken](), ) -proc initParserResult*(str: string): ParserResult = +func initParserResult*(str: string): ParserResult = ParserResult.ok(initParser(str)) -proc initBuilder*[T](t: Builder[T], parser: Parser, tree: seq[T]): Builder[T] = +func initBuilder*[T](t: Builder[T], parser: Parser, tree: seq[T]): Builder[T] = Builder[T](( parser, tree @@ -113,7 +113,7 @@ func emptyTokens*(parser: Parser): Parser = tokens: newSeq[ParserToken](), ) -proc foldTokens*[T]( +func foldTokens*[T]( parserResult: ParserResult, onError: ParserError -> T, onSuccess: seq[ParserToken] -> T, @@ -133,13 +133,13 @@ func setErrorExpectedField*(err: ParserError, expected: string): ParserError = parser: err.parser, ) -proc mapTree*[T](builder: BuilderResult[T], fn: seq[T] -> seq[T]): BuilderResult[T] = - builder.map(proc(b: Builder[T]): Builder[T] = Builder(( +func mapTree*[T](builder: BuilderResult[T], fn: seq[T] -> seq[T]): BuilderResult[T] = + builder.map(func(b: Builder[T]): Builder[T] = Builder(( parser: b[0], tree: fn(b[1]), ))) -proc tryParser*[T]( +func tryParser*[T]( builder: Builder[T], parser: Parser -> ParserResult, ): BuilderResult[T] = @@ -155,7 +155,7 @@ proc tryParser*[T]( (newTokens: seq[ParserToken]) => BuilderResult[T].ok(builder), ) -proc tryParser*[T]( +func tryParser*[T]( builder: BuilderResult[T], parser: Parser -> ParserResult, ): BuilderResult[T] = @@ -163,7 +163,7 @@ proc tryParser*[T]( ## When succesful return the ok builder, otherwise return an error builder.flatMap((x: Builder[T]) => tryParser(x, parser)) -proc applyParsersToSingle*[T]( +func applyParsersToSingle*[T]( builder: Builder[T], parsers: seq[Parser -> ParserResult], tokenFoldFn: (seq[ParserToken], T) -> T, @@ -200,7 +200,7 @@ proc applyParsersToSingle*[T]( ) ## TODO Implement applyParsersSeqToSingle with this function by forming the concatFn -proc applyParsersToSeq*[T]( +func applyParsersToSeq*[T]( builder: Builder[T], parsers: seq[Parser -> ParserResult], tokenFoldFn: (seq[ParserToken], T) -> T, @@ -231,7 +231,7 @@ proc applyParsersToSeq*[T]( ) ) -proc applyParsersSeqToSingle*[T]( +func applyParsersSeqToSingle*[T]( builderResult: BuilderResult[T], initT: T, xs: seq[tuple[ @@ -252,7 +252,7 @@ proc applyParsersSeqToSingle*[T]( builderResult ) -proc applyParsersSeqToSeq*[T]( +func applyParsersSeqToSeq*[T]( builderResult: BuilderResult[T], xs: seq[tuple[ parsers: seq[Parser -> ParserResult], @@ -273,12 +273,12 @@ proc applyParsersSeqToSeq*[T]( builderResult ) -proc applyParsers*[T]( +func applyParsers*[T]( builder: Builder[T], parsers: seq[Parser -> ParserResult], tokenFoldFn: (seq[ParserToken], seq[T]) -> seq[T], ): BuilderResult[T] = - # proc nested(b: Builder[T]): BuilderResult[T] = + # func nested(b: Builder[T]): BuilderResult[T] = let newParser = ParserResult.ok(Parser( state: builder[0].state, tokens: @[] @@ -293,7 +293,7 @@ proc applyParsers*[T]( ), ) -proc applyParsersSeq*[T]( +func applyParsersSeq*[T]( builder: BuilderResult[T], xs: seq[tuple[ parsers: seq[Parser -> ParserResult], @@ -302,7 +302,7 @@ proc applyParsersSeq*[T]( xs.foldl(a.flatMap((x: Builder[T]) => x.applyParsers(b[0], b[1])), builder) -proc foldBuilder*[T, T2]( +func foldBuilder*[T, T2]( builderResult: BuilderResult[T], onError: string -> T2, onSuccess: seq[T] -> T2, @@ -313,7 +313,7 @@ proc foldBuilder*[T, T2]( let err = builderResult.error() onError(err[1]) -# proc parseBuildOr*[T]( +# func parseBuildOr*[T]( # ## Checks # builderResult: BuilderResult[T], # builders: seq[tuple[ @@ -415,20 +415,20 @@ func highlightStreamPosition2(stream: string, position: int): string = stream.dup(insert(&"{beforeNewline}{spaceChars}^{lineChars} Char at \"{escapedChar}\"\n", insertMessageAtIndex)) -proc `$`*(x: ParserState): string = +func `$`*(x: ParserState): string = &"""ParserState( stream: "{x.stream.highlightStreamPosition(x.position)}", position: {x.position}, lastPosition: {x.lastPosition}, )""" -proc `$`*(x: Parser): string = +func `$`*(x: Parser): string = &"""Parser( state: {indentAfterNewline($x.state, 2)}, tokens: {indentAfterNewline($x.tokens, 2)}, )""" -proc `$`*(x: ParserError): string = +func `$`*(x: ParserError): string = case x: of charMismatchErr(expected: @expected, parser: @parser, index: @index, unexpected: @unexpected): # TODO: Only works for single line right now diff --git a/src_v2/parser/test.nim b/src_v2/parser/test.nim new file mode 100644 index 0000000..19e70b9 --- /dev/null +++ b/src_v2/parser/test.nim @@ -0,0 +1,11 @@ +import sugar +import results + +func adder_generator(a: int): (int -> int) = + return func(b: int): int = + a + b + + +const add_1 = adder_generator(1) + +echo add_1(1) diff --git a/src_v2/parser/utils.nim b/src_v2/parser/utils.nim deleted file mode 100644 index 405d0ce..0000000 --- a/src_v2/parser/utils.nim +++ /dev/null @@ -1,31 +0,0 @@ -import std/sugar -import std/collections/sequtils -import results -import ./parser_types - -type StringBuilderT* = string -type StringBuilder* = Builder[StringBuilderT] -type StringBuilderResult* = BuilderResult[StringBuilderT] - -proc stringConcat*(typeInfo: StringBuilderT, seperator = ""): - (seq[ParserToken], seq[StringBuilderT]) -> seq[StringBuilderT] = - - return proc(xs: seq[ParserToken], ys: seq[StringBuilderT]): seq[StringBuilderT] = - return ys & xs.foldl(a & b.tokenStringValue() & seperator, typeInfo) - -proc initStringBuilder*(str: string): StringBuilderResult = - StringBuilderResult - .ok(StringBuilder(( - parser: initParser(str), - tree: newSeq[StringBuilderT](), - ))) - -proc fold*[T, E, T2]( - self: Result[T, E], - onError: E -> T2, - onSuccess: T -> T2, -): T2 = - if self.isOk(): - onSuccess(self.unsafeGet()) - else: - onError(self.error())