Build text parser
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
import std/sugar
|
||||
import std/collections/sequtils
|
||||
import results
|
||||
import fusion/matching
|
||||
import ./org_types
|
||||
import ../utils/fp
|
||||
import ../parser/parser_internals
|
||||
import ../parser/parser_types
|
||||
|
||||
let parseBetweenDelimiter* = proc(delimiterParser: (Parser -> ParserResult)): (Parser -> ParserResult) {.closure.} =
|
||||
ignore(delimiterParser) + anyUntil(delimiterParser + whitespace) + ignore(delimiterParser)
|
||||
ignore(delimiterParser) +
|
||||
anyUntil(delimiterParser + whitespace) +
|
||||
ignore(delimiterParser)
|
||||
|
||||
let boldParser* = parseBetweenDelimiter(ch('*'))
|
||||
let italicParser* = parseBetweenDelimiter(ch('/'))
|
||||
@@ -15,5 +19,71 @@ let verbatimParser* = parseBetweenDelimiter(ch('='))
|
||||
let codeParser* = parseBetweenDelimiter(ch('~'))
|
||||
let strikeThroughParser* = parseBetweenDelimiter(ch('+'))
|
||||
|
||||
echo initParser("""_foo bar *_
|
||||
""").underlinedParser()
|
||||
|
||||
# until parser != delimiterparser
|
||||
# takeChar and save to current parser
|
||||
# else:
|
||||
# saveTokens to new text block
|
||||
# saveBlock delimiterparser
|
||||
|
||||
# let delimiterParser* = anyUntil(choice(@[
|
||||
# boldParser,
|
||||
# italicParser,
|
||||
# underlinedParser,
|
||||
# verbatimParser,
|
||||
# codeParser,
|
||||
# strikeThroughParser,
|
||||
# ]), newline)
|
||||
|
||||
|
||||
type OrgBuilderT* = OrgElement
|
||||
type OrgBuilder* = Builder[OrgBuilderT]
|
||||
type OrgBuilderResult* = BuilderResult[OrgBuilderT]
|
||||
|
||||
proc makeBoldTokens*(content: string): OrgBuilderT =
|
||||
OrgBuilderT(
|
||||
kind: orgBoldText,
|
||||
content: content,
|
||||
)
|
||||
|
||||
proc makeOrgToken*(orgTokenFn: string -> OrgBuilderT): (seq[ParserToken], seq[OrgBuilderT]) -> seq[OrgBuilderT] =
|
||||
return proc(parserTokens: seq[ParserToken], builderTokens: seq[OrgBuilderT]): seq[OrgBuilderT] =
|
||||
return builderTokens & parserTokens.foldl(a & b.tokenStringValue(), "").orgTokenFn()
|
||||
|
||||
proc textParser[T](
|
||||
builder: Builder[T],
|
||||
builderFns: seq[tuple[
|
||||
parserFn: Parser -> ParserResult,
|
||||
tokenFoldFn: (seq[ParserToken], seq[T]) -> seq[T],
|
||||
]],
|
||||
stopFn = newline,
|
||||
): BuilderResult[T] =
|
||||
let (parser, tree) = builder
|
||||
|
||||
var parserAcc: ParserResult = parser.ok()
|
||||
var builderAcc: Builder = builder
|
||||
|
||||
while parser.isOk() and parserAcc.flatMap(stopFn).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 it's tokens
|
||||
# Otherwise leave the raw tokens
|
||||
var found = false
|
||||
for builderFn in builderFns:
|
||||
let (parserFn, tokenFoldFn) = builderFn
|
||||
let parseResult = emptyParser.flatMap(parserFn)
|
||||
|
||||
if parseResult.isOk():
|
||||
let okParser = parseResult.unsafeGet()
|
||||
|
||||
found = true
|
||||
parserAcc = parseResult
|
||||
builderAcc = builder.initBuilder(
|
||||
okParser,
|
||||
tokenFoldFn(okParser.tokens, builderAcc[1]),
|
||||
)
|
||||
break
|
||||
|
||||
if not found:
|
||||
parserAcc = parserAcc.flatMap(anyCh)
|
||||
|
||||
Reference in New Issue
Block a user