122 lines
3.2 KiB
Nim
122 lines
3.2 KiB
Nim
import std/sugar
|
|
import std/strformat
|
|
import std/collections/sequtils
|
|
import std/strutils
|
|
import parser/parser
|
|
import results
|
|
import utils/fp
|
|
import fusion/matching
|
|
|
|
{.experimental: "caseStmtMacros".}
|
|
|
|
type StringBuilderT = string
|
|
type StringBuilder = Builder[StringBuilderT]
|
|
type StringBuilderResult = BuilderResult[StringBuilderT]
|
|
proc stringConcat(typeInfo: StringBuilderT):
|
|
(seq[ParserToken], seq[StringBuilderT]) -> seq[StringBuilderT] =
|
|
|
|
return proc(xs: seq[ParserToken], ys: seq[StringBuilderT]): seq[StringBuilderT] =
|
|
return ys & xs.foldl(a & b.tokenStringValue(), typeInfo)
|
|
|
|
|
|
proc initStringBuilder(str: string): StringBuilderResult =
|
|
StringBuilderResult
|
|
.ok(StringBuilder((
|
|
parser: initParser(str),
|
|
tree: newSeq[StringBuilderT](),
|
|
)))
|
|
|
|
when isMainModule:
|
|
let parseHeadingStars = @[
|
|
manyUntil(ch('*'), ch(' ')),
|
|
ignore(ch(' '))
|
|
]
|
|
|
|
proc createTodoKeywordParser(xs: seq[string]): (Parser -> ParserResult) =
|
|
choice(xs.map((x: string) => str(x) + ignore(ch(' '))))
|
|
|
|
let todoKeywords = @["TODO"]
|
|
let doneKeywords = @["DONE"]
|
|
|
|
let parseTodoKeyword = todoKeywords.createTodoKeywordParser()
|
|
let parseDoneKeyword = doneKeywords.createTodoKeywordParser()
|
|
|
|
let propertiesKeyParser = ignore(ch(':')) + anyUntil(choice(@[str(": "), newline]))
|
|
let propertiesValueParser = ignore(str(": ")) + anyUntil(newline) + ignore(newline)
|
|
let propertiesParser = proc(parser: Parser): ParserResult {.closure.} =
|
|
let keyTokenParser = parser
|
|
.propertiesKeyParser()
|
|
.flatMap(flattenParserTokens)
|
|
|
|
|
|
let valueTokenParser = keyTokenParser
|
|
.map(emptyTokens)
|
|
.flatMap(propertiesValueParser)
|
|
.flatMap(flattenParserTokens)
|
|
|
|
case (keyTokenParser, valueTokenParser):
|
|
of (Some(@key), Some(@value)):
|
|
ok(Parser(
|
|
state: value.state,
|
|
tokens: @[
|
|
key.tokens[0],
|
|
value.tokens[0],
|
|
]
|
|
))
|
|
else: valueTokenParser
|
|
|
|
let propertiesStartParser = str(":PROPERTIES_START:") + newline
|
|
let propertiesEndParser = str(":PROPERTIES_END:") + newline
|
|
|
|
let parseProperties = @[
|
|
ignore(propertiesStartParser),
|
|
manyUntil(
|
|
propertiesParser,
|
|
propertiesEndParser,
|
|
),
|
|
ignore(propertiesEndParser),
|
|
]
|
|
|
|
|
|
echo initParserResult(""":PROPERTIES:
|
|
:PROP_NAME: Value
|
|
:PROP_NAME: Value
|
|
:PROP_NAME: Value
|
|
:PROP_NAME: Value
|
|
:PROPERTIES_END:
|
|
""").parseSeq(parseProperties)
|
|
|
|
let parseHeadingText = @[
|
|
anyUntil(newline),
|
|
ignore(newline),
|
|
]
|
|
|
|
let sampleBuilder = StringBuilderResult
|
|
.ok(StringBuilder((
|
|
parser: initParser("""**** TODO Some stars
|
|
:PROPERTIES:
|
|
:PROP_NAME: Value
|
|
:PROP_NAME: Value
|
|
:PROP_NAME: Value
|
|
:PROP_NAME: Value
|
|
:PROPERTIES_END:
|
|
"""),
|
|
tree: newSeq[StringBuilderT](),
|
|
)))
|
|
.applyParsersSeq(@[
|
|
(parseHeadingStars, stringConcat("Stars: ")),
|
|
|
|
(@[optional(parseTodoKeyword)], stringConcat("TODO: ")),
|
|
(@[optional(parseDoneKeyword)], stringConcat("DONE: ")),
|
|
|
|
(parseHeadingText, stringConcat("Text: ")),
|
|
# (parseProperties, stringConcat("Properties: ")),
|
|
# (@[optional(choice(parseProperties))], stringConcat("Properties: ")),
|
|
])
|
|
.foldBuilder(
|
|
err => &"Error Parsing: {err}",
|
|
xs => "Parser Succesfull:\n" & xs.join("\n"),
|
|
)
|
|
|
|
# echo sampleBuilder
|