import std/options import std/strutils import std/strformat import std/collections/sequtils import std/sugar import results import fusion/matching import fp/maybe import print {.experimental: "caseStmtMacros".} type ParsePosition = tuple column, line, currentLine: int atNewLine: bool ParseError = tuple unexpected: string expected: seq[string] state: ParserState message: string ParserState* = ref object stream: string position, lastPosition: int Token* = ref object value: char Parser* = ref object state: ParserState tokens: seq[Token] ParserResult* = Result[Parser, (Parser, string)] proc indentKey(x: string, count: int): string = var y = x.indent(count) y.delete(0..count - 1) y proc `$`*(x: Token): string = &"""Token( value: {x.value}, )""" proc `$`*(x: ParserState): string = &"""ParserState( stream: "{x.stream}", position: {x.position}, lastPosition: {x.lastPosition}, )""" proc `$`*(x: Parser): string = &"""Parser( state: {indentKey($x.state, 2)}, tokens: {indentKey($x.tokens, 2)}, )""" proc initParser(str: string): ParserResult = Parser( state: ParserState( stream: str, position: 0, lastPosition: 0, ), tokens: newSeq[Token](), ).ok() proc ch(parser: Parser, c: char): ParserResult = let state = parser.state if state.stream[0] == c: Parser( state: ParserState( stream: state.stream[1 .. ^1], position: parser.state.position + 1, lastPosition: parser.state.position, ), tokens: parser.tokens & Token(value: c) ).ok() else: err((parser, &"Expected {c}")) # type R = Result[int, string] # echo R.ok 4 echo initParser("Foo") .flatMap((x: Parser) => ch(x, c = 'F')) .flatMap((x: Parser) => ch(x, c = 'o')) .flatMap((x: Parser) => ch(x, c = 'o')) # proc parseStars # proc parseHeadline(parser: ParserResult[OrgElement]): ParserResult[OrgElement] = # parser # .flatMap(parseA) # # flatMapOptionalToken( # # content = # # ) # # flatMapToken( # # content = # # ) # # flatMapToken( # # tags # # )