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] ParserResult* = Result[Parser, ParserError]
Builder*[T] = tuple[ Builder*[T] = tuple[
parser: ParserResult, parser: Parser,
tree: seq[T] tree: seq[T]
] ]
BuilderResult*[T] = Result[Builder[T], (Builder[T], string)] BuilderResult*[T] = Result[Builder[T], (Builder[T], string)]
@@ -109,7 +109,7 @@ proc `$`*(x: ParserError): string =
{errSpace}^ Expected '{expected}' but got '{unexpected}'""" {errSpace}^ Expected '{expected}' but got '{unexpected}'"""
else: "ParseError" else: "ParseError"
proc initParser(str: string): ParserResult = proc initParser(str: string): Parser =
Parser( Parser(
state: ParserState( state: ParserState(
stream: str, stream: str,
@@ -117,7 +117,7 @@ proc initParser(str: string): ParserResult =
lastPosition: 0, lastPosition: 0,
), ),
tokens: newSeq[Token](), tokens: newSeq[Token](),
).ok() )
func ch(expectedChars: set[char]): (Parser -> ParserResult) {.inline.} = func ch(expectedChars: set[char]): (Parser -> ParserResult) {.inline.} =
return func(parser: Parser): ParserResult = return func(parser: Parser): ParserResult =
@@ -262,67 +262,71 @@ proc foldTokens[T](
let err = parserResult.error() let err = parserResult.error()
onError(err) 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]) = proc applyParsers[T](
# builder.map(proc(b: Builder) = builder: Builder[T],
# (@parser, @builder) := builder parsers: seq[Parser -> ParserResult],
# b 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 = newParser
# (@parser, @builder) := builder .foldTokens(
# parser.foldTokens( (err: ParserError) => BuilderResult[T].err((builder, "foo")),
# proc(x: ParserError): BuilderResult = err(x), (newTokens: seq[Token]) => BuilderResult[T].ok(
# proc(xs: seq[Token]): BuilderResult = ok(parser, builder.map()), 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: 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 = @[ let parseHeadingStars = @[
manyUntil(ch('*'), ch(' ')), manyUntil(ch('*'), ch(' ')),
ignore(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 = # let buildHeadingStars =
type StringBuilder = BuilderResult[string] type StringBuilderT = string
type StringBuilder = Builder[StringBuilderT]
type StringBuilderResult = BuilderResult[StringBuilderT]
let sampleBuilder: StringBuilder = StringBuilder.ok(Builder(( proc stringConcat(typeInfo: StringBuilderT):
parser: initParser(""), (seq[Token], seq[StringBuilderT]) -> seq[StringBuilderT] =
tree: newSeq[string](), 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 echo sampleBuilder
# .mapTree((x: string) => x)
# @[ # @[