Documentation
This commit is contained in:
@@ -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 => "",
|
||||||
|
|||||||
Reference in New Issue
Block a user