Documentation

This commit is contained in:
Florian Schroedl
2022-01-20 17:00:00 +01:00
parent 51f4f3d35f
commit b1e4a36e36

View File

@@ -14,15 +14,15 @@ let parseBetweenDelimiter* = proc(start: (Parser -> ParserResult), stop: (Parser
anyUntil(stop + whitespace) + anyUntil(stop + whitespace) +
ignore(start) ignore(start)
let parseBetweenIdenticalDelimiter* = proc(delimiterParser: (Parser -> ParserResult)): (Parser -> ParserResult) {.closure.} = let parseBetweenPair* = proc(delimiterParser: (Parser -> ParserResult)): (Parser -> ParserResult) {.closure.} =
parseBetweenDelimiter(delimiterParser, delimiterParser) parseBetweenDelimiter(delimiterParser, delimiterParser)
let boldParser* = parseBetweenIdenticalDelimiter(ch('*')) let boldParser* = parseBetweenPair(ch('*'))
let italicParser* = parseBetweenIdenticalDelimiter(ch('/')) let italicParser* = parseBetweenPair(ch('/'))
let underlineParser* = parseBetweenIdenticalDelimiter(ch('_')) let underlineParser* = parseBetweenPair(ch('_'))
let verbatimParser* = parseBetweenIdenticalDelimiter(ch('=')) let verbatimParser* = parseBetweenPair(ch('='))
let codeParser* = parseBetweenIdenticalDelimiter(ch('~')) let codeParser* = parseBetweenPair(ch('~'))
let strikeThroughParser* = parseBetweenIdenticalDelimiter(ch('+')) let strikeThroughParser* = parseBetweenPair(ch('+'))
type OrgBuilderT* = OrgElement type OrgBuilderT* = OrgElement
type OrgBuilder* = Builder[OrgBuilderT] type OrgBuilder* = Builder[OrgBuilderT]
@@ -78,43 +78,48 @@ proc parseText[T](
builder: Builder[T], builder: Builder[T],
builderFns: seq[tuple[ builderFns: seq[tuple[
parserFn: Parser -> ParserResult, parserFn: Parser -> ParserResult,
tokenFoldFn: (seq[ParserToken], seq[T]) -> seq[T], concatFn: (seq[ParserToken], seq[T]) -> seq[T],
]], ]],
otherWiseFn: (seq[ParserToken]) -> seq[T], defaultBuilderFn: (seq[ParserToken]) -> seq[T],
stopFn = newline, stopAtParserFn = newline,
): BuilderResult[T] = ): BuilderResult[T] =
## Parse remaining text in `builder` by going checking in 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 let (parser, tree) = builder
# Mutating accumulators
var parserAcc: ParserResult = ParserResult.ok(parser) var parserAcc: ParserResult = ParserResult.ok(parser)
var builderAcc: Builder[T] = builder var builderAcc: Builder[T] = builder
while parserAcc.isOk() and parserAcc.flatMap(stopFn).isErr(): 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 # Empty the parser tokens as we want to seperate them for the next parser in the sequence
let emptyParser = parserAcc.map(emptyTokens) let emptyParser = parserAcc.map(emptyTokens)
# Find the first matching parser and convert it's tokens # Find the first matching parser and convert its tokens
# Otherwise leave the raw tokens
var found = false var found = false
for builderFn in builderFns: for builderFn in builderFns:
let (parserFn, tokenFoldFn) = builderFn let (parserFn, concatFn) = builderFn
let parseResult = emptyParser.flatMap(parserFn)
let parseResult = emptyParser.flatMap(parserFn)
if parseResult.isOk(): if parseResult.isOk():
let okParser = parseResult.unsafeGet() let okParser = parseResult.unsafeGet()
let textTokens = parserAcc # Convert all previous unmatched tokens via the `defaultBuilderTokens`
let defaultBuilderTokens = parserAcc
.foldTokens( .foldTokens(
onError = _ => newSeq[T](), onError = _ => newSeq[T](),
onSuccess = otherWiseFn, onSuccess = defaultBuilderFn,
) )
found = true found = true
parserAcc = parseResult.map(emptyTokens) parserAcc = parseResult.map(emptyTokens)
builderAcc = builder.initBuilder( builderAcc = builder.initBuilder(
okParser, okParser,
tokenFoldFn( concatFn(
okParser.tokens, okParser.tokens,
builderAcc[1] & textTokens, builderAcc[1] & defaultBuilderTokens,
), ),
) )
break break
@@ -122,15 +127,15 @@ proc parseText[T](
if not found: if not found:
parserAcc = parserAcc.flatMap(anyCh) parserAcc = parserAcc.flatMap(anyCh)
let textTokens = parserAcc let defaultBuilderTokens = parserAcc
.foldTokens( .foldTokens(
onError = _ => newSeq[T](), onError = _ => newSeq[T](),
onSuccess = otherWiseFn, onSuccess = defaultBuilderFn,
) )
BuilderResult[T].ok(builder.initBuilder( BuilderResult[T].ok(builder.initBuilder(
builderAcc[0], builderAcc[0],
builderAcc[1] & textTokens, builderAcc[1] & defaultBuilderTokens,
)) ))
proc makeRawTokenOrEmpty(xs: seq[ParserToken]): seq[OrgBuilderT] = proc makeRawTokenOrEmpty(xs: seq[ParserToken]): seq[OrgBuilderT] =
@@ -154,7 +159,7 @@ when isMainModule:
(codeParser, makeOrgToken(makeCodeToken)), (codeParser, makeOrgToken(makeCodeToken)),
(strikeThroughParser, makeOrgToken(makeStrikeThroughToken)), (strikeThroughParser, makeOrgToken(makeStrikeThroughToken)),
], ],
otherWiseFn = makeRawTokenOrEmpty, defaultBuilderFn = makeRawTokenOrEmpty,
)) ))
# .foldBuilder( # .foldBuilder(
# err => "", # err => "",