From de0382e812e054b861a81fea53632d1dbd190d32 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Fri, 17 Jun 2022 18:44:42 +0200 Subject: [PATCH] WIP Working seq parsing --- src/org/org_block_heading.nim | 57 ++++++++++++++++++++--------- src/parser/parser_types.nim | 67 +++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 17 deletions(-) diff --git a/src/org/org_block_heading.nim b/src/org/org_block_heading.nim index 1cf77a5..cc29dea 100644 --- a/src/org/org_block_heading.nim +++ b/src/org/org_block_heading.nim @@ -49,6 +49,7 @@ let parseHeadingText = @[ # # builder.level = token.tokenStringValue().len # token + let buildStars = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.}= org.level = tokens.len org @@ -101,31 +102,53 @@ let headingParser = choice(@[ endOfStream, ]) +let newlineParser: seq[Parser -> ParserResult] = @[newline + newline] + +let buildNewline = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.} = + OrgBlock( + kind: orgNewline + ) + +proc concatOrgBlock(xs: seq[OrgBlock], ys: seq[OrgBlock]): seq[OrgBlock] = xs & ys + +let contentParsersSeq: seq[tuple[ + parsers: seq[Parser -> ParserResult], + tokenFoldFn: (seq[ParserToken], OrgBlock) -> OrgBlock, + ignoreEmpty: bool, + # concatFn: (seq[OrgBlock], seq[OrgBlock]) -> seq[OrgBlock], +]] = @[ + (newlineParser, buildNewline, false), + # (newlineParser, buildNewline, false), +] + proc parseHeadlineChildren(builder: OrgBuilder): OrgBuilderResult = var headingBlock = builder.tree[0] - var parserAcc: ParserResult = ParserResult.ok(builder.parser) + var builderAcc: OrgBuilderResult = OrgBuilderResult.ok(builder) - # echo parserAcc + while builderAcc.isOk() and builderAcc.tryParser(headingParser).isErr(): + builderAcc = builderAcc + .applyParsersSeqToSeq( + contentParsersSeq + ) - while parserAcc.isOk() and parserAcc.flatMap(headingParser).isErr(): - parserAcc = parserAcc.flatMap(anyCh) + builderAcc - let content = parserAcc.foldTokens( - (err) => "", - (xs: seq[ParserToken]) => xs.tokensToString(), - ) - headingBlock.content = content + # let content = builderAcc.fold( + # (_err) => "", + # (builder: OrgBuilder) => builder.tree, + # ) + # headingBlock.content = content - let res = parserAcc.fold( - (err) => OrgBuilderResult.err((builder, "Could not parse content")), - (parser: Parser) => OrgBuilderResult.ok(( - parser: parser.emptyTokens(), - tree: @[headingBlock], - )) - ) + # let res = builderAcc.fold( + # (_err) => OrgBuilderResult.err((builder, "Could not parse content")), + # (builder: OrgBuilder) => OrgBuilderResult.ok(( + # parser: builder.parser.emptyTokens(), + # tree: @[headingBlock], + # )) + # ) - res + # res proc makeOrg*(x: string): OrgBuilderResult = var acc = initOrgBuilder(x) diff --git a/src/parser/parser_types.nim b/src/parser/parser_types.nim index 1f37d04..df02c9a 100644 --- a/src/parser/parser_types.nim +++ b/src/parser/parser_types.nim @@ -199,6 +199,38 @@ proc applyParsersToSingle*[T]( ) ) +## TODO Implement applyParsersSeqToSingle with this function by forming the concatFn +proc applyParsersToSeq*[T]( + builder: Builder[T], + parsers: seq[Parser -> ParserResult], + tokenFoldFn: (seq[ParserToken], T) -> T, + # concatFn = `&`, + optional = false, + isFirst: bool, +): BuilderResult[T] = + # Apply the current parsing functions and convert to text tokens wrapped in ParserResult + let newParser = ParserResult.ok(Parser( + state: builder[0].state, + tokens: @[] + )) + .parseSeq(parsers) + + newParser + .foldTokens( + (err: ParserError) => BuilderResult[T].err((builder, "foo")), + (newTokens: seq[ParserToken]) => ( + if optional and newTokens.len == 0: + BuilderResult[T].ok(builder) + else: + BuilderResult[T].ok( + builder.initBuilder( + newParser.unsafeGet(), + builder.tree & builder.tree + ) + ) + ) + ) + proc applyParsersSeqToSingle*[T]( builderResult: BuilderResult[T], initT: T, @@ -220,6 +252,27 @@ proc applyParsersSeqToSingle*[T]( builderResult ) +proc applyParsersSeqToSeq*[T]( + builderResult: BuilderResult[T], + xs: seq[tuple[ + parsers: seq[Parser -> ParserResult], + tokenFoldFn: (seq[ParserToken], T) -> T, + ignoreEmpty: bool, + # concatFn: (seq[T], seq[T]) -> seq[T], + ]], +): BuilderResult[T] = + xs.foldl( + a.flatMap((builder: Builder[T]) => applyParsersToSeq( + builder = builder, + parsers = b.parsers, + tokenFoldFn = b.tokenFoldFn, + optional = b.ignoreEmpty, + isFirst = a == builderResult, + # concatFn = concatFn + )), + builderResult + ) + proc applyParsers*[T]( builder: Builder[T], parsers: seq[Parser -> ParserResult], @@ -260,6 +313,20 @@ proc foldBuilder*[T, T2]( let err = builderResult.error() onError(err[1]) +# proc parseBuildOr*[T]( +# ## Checks +# builderResult: BuilderResult[T], +# builders: seq[tuple[ +# parsers: seq[Parser -> ParserResult], +# tokenFoldFn: (seq[ParserToken], T) -> T, +# ]], +# defaultBuilder: tuple[ +# defaultParser: Parser -> ParserResult, +# defaultFoldFn: (seq[ParserToken], T) -> T, +# ], +# until: +# ): BuilderResult[T] = + # -- Stringifiers