Create an org heading builder

This commit is contained in:
Florian Schroedl
2022-05-04 17:00:00 +02:00
parent bec4953a97
commit 722e66cf85
10 changed files with 342 additions and 0 deletions

View File

@@ -7,6 +7,21 @@ 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[

View File

@@ -3,8 +3,10 @@ import std/strformat
import std/collections/sequtils
import std/sugar
import results
import fp/maybe
import fusion/matching
import ../utils/str
import ../utils/fp
{.experimental: "caseStmtMacros".}
@@ -46,6 +48,12 @@ type
]
BuilderResult*[T] = Result[Builder[T], (Builder[T], string)]
# SingleBuilder*[T] = tuple[
# parser: Parser,
# tree: T
# ]
# SingleBuilderResult*[T] = Result[SingleBuilder[T], (SingleBuilder[T], string)]
# -- Initalizers
func initParserToken*(x: char): ParserToken = ParserToken(kind: parserTokenChar, charValue: x)
@@ -130,6 +138,71 @@ proc mapTree*[T](builder: BuilderResult[T], fn: seq[T] -> seq[T]): BuilderResult
tree: fn(b[1]),
)))
proc tryParser*[T](
builder: Builder[T],
parser: Parser -> ParserResult,
): BuilderResult[T] =
## Try out a `parser` on a `builder`
## When succesful return the original builder, otherwise return an error
ParserResult.ok(Parser(
state: builder[0].state,
tokens: @[]
))
.flatMap(parser)
.foldTokens(
(err: ParserError) => BuilderResult[T].err((builder, "Error")),
(newTokens: seq[ParserToken]) => BuilderResult[T].ok(builder),
)
proc tryParser*[T](
builder: BuilderResult[T],
parser: Parser -> ParserResult,
): BuilderResult[T] =
## Try out a `parser` on a `builder` result
## When succesful return the ok builder, otherwise return an error
builder.flatMap((x: Builder[T]) => tryParser(x, parser))
proc applyParsersToSingle*[T](
builder: Builder[T],
parsers: seq[Parser -> ParserResult],
tokenFoldFn: (seq[ParserToken], T) -> T,
initT: T,
): 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]) => BuilderResult[T].ok(
builder.initBuilder(
newParser.unsafeGet(),
builder.tree
.last()
.orElse(just(initT))
.map((x: T) => @[tokenFoldFn(newTokens, x)])
.getOrElse(newSeq[T]())
)
)
)
proc applyParsersSeqToSingle*[T](
builderResult: BuilderResult[T],
initT: T,
xs: seq[tuple[
parsers: seq[Parser -> ParserResult],
tokenFoldFn: (seq[ParserToken], T) -> T,
]],
): BuilderResult[T] =
xs.foldl(
a.flatMap((builder: Builder[T]) => applyParsersToSingle(builder, b[0], b[1], initT)),
builderResult
)
proc applyParsers*[T](
builder: Builder[T],
parsers: seq[Parser -> ParserResult],