Extract properties block parser to file

This commit is contained in:
Florian Schroedl
2022-01-20 17:00:00 +01:00
parent cad191a976
commit 21a6234149
5 changed files with 131 additions and 88 deletions

View File

@@ -0,0 +1,59 @@
import std/sugar
import std/strformat
import std/collections/sequtils
import std/strutils
import results
import fusion/matching
import ../utils/fp
import ../parser/parser
import ../parser/utils
{.experimental: "caseStmtMacros".}
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),
]
when isMainModule:
let example = initParserResult(""":PROPERTIES:
:PROP_NAME: Value
:PROP_NAME: Value
:PROP_NAME: Value
:PROP_NAME: Value
:PROPERTIES_END:""").parseSeq(parseProperties)
echo example

View File

@@ -3,30 +3,13 @@ import std/strformat
import std/collections/sequtils import std/collections/sequtils
import std/strutils import std/strutils
import parser/parser import parser/parser
import parser/utils
import results import results
import utils/fp import utils/fp
import fusion/matching import fusion/matching
{.experimental: "caseStmtMacros".} {.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 = @[ let parseHeadingStars = @[
manyUntil(ch('*'), ch(' ')), manyUntil(ch('*'), ch(' ')),
ignore(ch(' ')) ignore(ch(' '))
@@ -41,56 +24,12 @@ when isMainModule:
let parseTodoKeyword = todoKeywords.createTodoKeywordParser() let parseTodoKeyword = todoKeywords.createTodoKeywordParser()
let parseDoneKeyword = doneKeywords.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 = @[ let parseHeadingText = @[
anyUntil(newline), anyUntil(newline),
ignore(newline), ignore(newline),
] ]
when isMainModule:
let sampleBuilder = StringBuilderResult let sampleBuilder = StringBuilderResult
.ok(StringBuilder(( .ok(StringBuilder((
parser: initParser("""**** TODO Some stars parser: initParser("""**** TODO Some stars
@@ -118,4 +57,4 @@ when isMainModule:
xs => "Parser Succesfull:\n" & xs.join("\n"), xs => "Parser Succesfull:\n" & xs.join("\n"),
) )
# echo sampleBuilder echo sampleBuilder

View File

@@ -33,8 +33,8 @@ type
# keyValuePairValue*: parserTokenKeyValuePairValueT # keyValuePairValue*: parserTokenKeyValuePairValueT
Parser* = ref object Parser* = ref object
state: ParserState state*: ParserState
tokens: seq[ParserToken] tokens*: seq[ParserToken]
ParseErrorKind = enum ParseErrorKind = enum
choiceMismatchErr choiceMismatchErr
@@ -238,6 +238,26 @@ func ignore*(parserFn: Parser -> ParserResult): (Parser -> ParserResult) {.inlin
tokens: parser.tokens, tokens: parser.tokens,
)) ))
func flattenParserTokens*(parser: Parser): ParserResult =
return ParserResult.ok(
Parser(
state: parser.state,
tokens: @[
ParserToken(
kind: parserTokenString,
stringValue: parser.tokens.foldl(a & b.tokenStringValue(), "")
)
]
)
)
func emptyTokens*(parser: Parser): Parser =
Parser(
state: parser.state,
tokens: newSeq[ParserToken](),
)
func optional*(parserFn: Parser -> ParserResult): (Parser -> ParserResult) {.inline.} = func optional*(parserFn: Parser -> ParserResult): (Parser -> ParserResult) {.inline.} =
## Parse characters and ignore failure ## Parse characters and ignore failure
return proc(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
@@ -293,8 +313,8 @@ proc `+`*(parserFnA: Parser -> ParserResult, parserFnB: Parser -> ParserResult):
let newlineParser = choice(@[ let newlineParser = choice(@[
ch(NewLines),
endOfStream, endOfStream,
ch(NewLines)
]) ])
proc newline*(parser: Parser): ParserResult = newlineParser(parser) proc newline*(parser: Parser): ParserResult = newlineParser(parser)

21
src/parser/utils.nim Normal file
View File

@@ -0,0 +1,21 @@
import std/sugar
import std/collections/sequtils
import ./parser
import results
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](),
)))

View File

@@ -1,5 +1,9 @@
import std/sugar import std/sugar
import fp/maybe import fp/maybe
import results
template isSome*(self: Result): bool = self.isOk()
template isNone*(self: Result): bool = self.isErr()
proc findMaybe*[T](xs: seq[T], fn: T -> bool): Maybe[T] = proc findMaybe*[T](xs: seq[T], fn: T -> bool): Maybe[T] =
for x in xs: for x in xs: