109 lines
2.1 KiB
Nim
109 lines
2.1 KiB
Nim
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
|
|
# # )
|