Parser transformation

This commit is contained in:
Florian Schroedl
2022-01-20 17:00:00 +01:00
parent b6fd4faad1
commit ce07cbc8da

View File

@@ -37,7 +37,7 @@ type
ParserResult* = Result[Parser, ParserError]
Builder*[T] = tuple[
parser: ParserResult,
parser: Parser,
tree: seq[T]
]
BuilderResult*[T] = Result[Builder[T], (Builder[T], string)]
@@ -109,7 +109,7 @@ proc `$`*(x: ParserError): string =
{errSpace}^ Expected '{expected}' but got '{unexpected}'"""
else: "ParseError"
proc initParser(str: string): ParserResult =
proc initParser(str: string): Parser =
Parser(
state: ParserState(
stream: str,
@@ -117,7 +117,7 @@ proc initParser(str: string): ParserResult =
lastPosition: 0,
),
tokens: newSeq[Token](),
).ok()
)
func ch(expectedChars: set[char]): (Parser -> ParserResult) {.inline.} =
return func(parser: Parser): ParserResult =
@@ -262,67 +262,71 @@ proc foldTokens[T](
let err = parserResult.error()
onError(err)
proc merge[T](t: Builder[T], parser: Parser, tree: seq[T]): Builder[T] =
Builder[T]((
parser,
tree
))
# proc mapTree[T](builder: BuilderResult[T], fn: Builder[T] -> Builder[T]) =
# builder.map(proc(b: Builder) =
# (@parser, @builder) := builder
# b
# )
proc applyParsers[T](
builder: Builder[T],
parsers: seq[Parser -> ParserResult],
tokenFoldFn: (seq[Token], seq[T]) -> seq[T],
): BuilderResult[T] =
# proc nested(b: Builder[T]): BuilderResult[T] =
let newParser = ParserResult.ok(Parser(
state: builder[0].state,
tokens: @[]
))
.parseSeq(parsers)
# proc applyParserTokens[T](builder: BuilderResult, fn: seq[Token] -> T): BuilderResult =
# (@parser, @builder) := builder
# parser.foldTokens(
# proc(x: ParserError): BuilderResult = err(x),
# proc(xs: seq[Token]): BuilderResult = ok(parser, builder.map()),
# )
newParser
.foldTokens(
(err: ParserError) => BuilderResult[T].err((builder, "foo")),
(newTokens: seq[Token]) => BuilderResult[T].ok(
builder.merge(newParser.unsafeGet(), tokenFoldFn(newTokens, builder[1]))
),
)
proc mapTree[T](builder: BuilderResult[T], fn: seq[T] -> seq[T]): BuilderResult[T] =
builder.map(proc(b: Builder[T]): Builder[T] = Builder((
parser: b[0],
tree: fn(b[1]),
)))
when isMainModule:
# let fooParser = initParser("FOO___BAR")
# .parseSeq(@[
# str("FOO"),
# ignore(str("___")),
# ch('B'),
# ch('B'),
# ch('A'),
# ch('R'),
# ])
# .foldTokens(
# err => $err,
# xs => xs.foldl(a & b.value, "")
# )
# echo initParser("BB").parseSeq(@[
# choice(@[ch(Digits), ch('B')]),
# ])
let parseHeadingStars = @[
manyUntil(ch('*'), ch(' ')),
ignore(ch(' '))
]
# proc buildHeadingStars(stars: ParserResult, builder: OrgElement): OrgElement =
# builder.level = stars.get().len
# let todoKeywords = @[
# "TODO",
# ]
# let todoDoneKeywords = @[
# "DONE",
# ]
# let parseHeadingTodo = @[
# ]
# let buildHeadingStars =
type StringBuilder = BuilderResult[string]
type StringBuilderT = string
type StringBuilder = Builder[StringBuilderT]
type StringBuilderResult = BuilderResult[StringBuilderT]
let sampleBuilder: StringBuilder = StringBuilder.ok(Builder((
parser: initParser(""),
tree: newSeq[string](),
proc stringConcat(typeInfo: StringBuilderT):
(seq[Token], seq[StringBuilderT]) -> seq[StringBuilderT] =
return proc(xs: seq[Token], ys: seq[StringBuilderT]): seq[StringBuilderT] =
return ys & xs.foldl(a & b.value, typeInfo)
let sampleBuilder: StringBuilderResult = StringBuilderResult
.ok(StringBuilder((
parser: initParser("**** Some stars"),
tree: newSeq[StringBuilderT](),
)))
.flatMap((x: StringBuilder) => x.applyParsers(
parsers = parseHeadingStars,
tokenFoldFn = stringConcat("Stars: ")
))
.flatMap((x: StringBuilder) => x.applyParsers(
parsers = parseHeadingStars,
tokenFoldFn = stringConcat("Stars: ")
))
echo sampleBuilder
# .mapTree((x: string) => x)
# @[