Use proc, fn and const dont work
This commit is contained in:
2
TODO.org
2
TODO.org
@@ -28,7 +28,7 @@
|
||||
|
||||
** TODO Headline content parser
|
||||
:LOGBOOK:
|
||||
CLOCK: [2022-08-09 Tue 17:51]
|
||||
CLOCK: [2022-08-09 Tue 17:51]--[2022-08-09 Tue 19:51] => 2:00
|
||||
:END:
|
||||
|
||||
So I've had some heavy misconceptions while working on the content,
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
import std/sugar
|
||||
import std/collections/sequtils
|
||||
import std/strformat
|
||||
import std/strutils
|
||||
import results
|
||||
import fusion/matching
|
||||
import ./parser_internals
|
||||
import ./parser_types
|
||||
|
||||
# proc tryParseBuildOrg*[T](
|
||||
# builder: Builder[T],
|
||||
# builderFns: seq[
|
||||
# Builder[T] -> BuilderResult[T]
|
||||
# ],
|
||||
# stopAtParserFn = endOfStream
|
||||
# ): BuilderResult[T] =
|
||||
|
||||
# # Mutating accumulators
|
||||
# var builderAcc: BuilderResult[T] = BuilderResult.ok(builder)
|
||||
|
||||
# while builderAcc.isOk() and builderAcc.tryParser(stopAtParserFn).isErr()
|
||||
# for fn in builderFns:
|
||||
# fn
|
||||
|
||||
proc tryParseBuild*[T](
|
||||
builder: Builder[T],
|
||||
builderFns: seq[tuple[
|
||||
parserFn: Parser -> ParserResult,
|
||||
builderFn: seq[ParserToken] -> seq[T],
|
||||
]],
|
||||
defaultBuilderFn: seq[ParserToken] -> seq[T],
|
||||
stopAtParserFn = newline,
|
||||
concatFn = concat[T],
|
||||
): BuilderResult[T] =
|
||||
## Parse text in `builder` by checking the `builderFns` list for a sucessful `parserFn`.
|
||||
## The `ok` `parserFn` result will be merged into the `Builder[T].tree` by using the `concatFn`.
|
||||
## Otherwise continue taking any character until the `stopAtParserFn` condition is found.
|
||||
## Any non-matching tokens will be converted using the `defaultBuilderFn`.
|
||||
let (parser, tree) = builder
|
||||
|
||||
# Mutating accumulators
|
||||
var parserAcc: ParserResult = ParserResult.ok(parser)
|
||||
var builderAcc: Builder[T] = builder
|
||||
|
||||
while parserAcc.isOk() and parserAcc.flatMap(stopAtParserFn).isErr():
|
||||
# Empty the parser tokens as we want to seperate them for the next parser in the sequence
|
||||
let emptyParser = parserAcc.map(emptyTokens)
|
||||
|
||||
# Find the first matching parser and convert its tokens
|
||||
var found = false
|
||||
for fn in builderFns:
|
||||
let (parserFn, builderFn) = fn
|
||||
|
||||
let parseResult = emptyParser.flatMap(parserFn)
|
||||
if parseResult.isOk():
|
||||
let okParser = parseResult.unsafeGet()
|
||||
|
||||
# Convert all previous unmatched tokens via the `defaultBuilderTokens`
|
||||
let defaultBuilderTokens = parserAcc
|
||||
.foldTokens(
|
||||
onError = _ => newSeq[T](),
|
||||
onSuccess = defaultBuilderFn,
|
||||
)
|
||||
|
||||
found = true
|
||||
parserAcc = parseResult.map(emptyTokens)
|
||||
builderAcc = builder.initBuilder(
|
||||
okParser,
|
||||
concatFn(
|
||||
builderAcc.tree,
|
||||
defaultBuilderTokens,
|
||||
builderFn(okParser.tokens),
|
||||
)
|
||||
)
|
||||
break
|
||||
|
||||
if not found:
|
||||
parserAcc = parserAcc.flatMap(anyCh)
|
||||
|
||||
let defaultBuilderTokens = parserAcc
|
||||
.foldTokens(
|
||||
onError = _ => newSeq[T](),
|
||||
onSuccess = defaultBuilderFn,
|
||||
)
|
||||
|
||||
BuilderResult[T].ok(builder.initBuilder(
|
||||
builderAcc.parser,
|
||||
concatFn(
|
||||
builderAcc.tree,
|
||||
defaultBuilderTokens,
|
||||
),
|
||||
))
|
||||
@@ -14,12 +14,12 @@ import ./parser_types
|
||||
|
||||
# -- Types
|
||||
|
||||
type parserFnT = proc(t0: Parser): ParserResult {.nosideeffect.}
|
||||
type parserFnT = proc(t0: Parser): ParserResult
|
||||
|
||||
# -- Utilities
|
||||
|
||||
func lookBack*(count: int): (parserFnT) =
|
||||
return func(parser: Parser): ParserResult =
|
||||
proc lookBack*(count: int): (parserFnT) =
|
||||
return proc(parser: Parser): ParserResult =
|
||||
let state = parser.state
|
||||
let newIndex = state.position - 1
|
||||
|
||||
@@ -32,10 +32,10 @@ func lookBack*(count: int): (parserFnT) =
|
||||
tokens: parser.tokens,
|
||||
).ok()
|
||||
|
||||
# -- Parsing Functions
|
||||
# -- Parsing Proctions
|
||||
|
||||
func ch*(expectedChars: set[char]): parserFnT {.inline.} =
|
||||
return func(parser: Parser): ParserResult =
|
||||
proc ch*(expectedChars: set[char]): parserFnT {.inline.} =
|
||||
return proc(parser: Parser): ParserResult =
|
||||
let state = parser.state
|
||||
let newIndex = state.position + 1
|
||||
|
||||
@@ -66,8 +66,8 @@ func ch*(expectedChars: set[char]): parserFnT {.inline.} =
|
||||
parser: parser,
|
||||
))
|
||||
|
||||
func ch*(expectedChar: char): parserFnT {.inline.} =
|
||||
return func(parser: Parser): ParserResult =
|
||||
proc ch*(expectedChar: char): parserFnT {.inline.} =
|
||||
return proc(parser: Parser): ParserResult =
|
||||
let state = parser.state
|
||||
let newIndex = state.position + 1
|
||||
|
||||
@@ -98,10 +98,10 @@ func ch*(expectedChar: char): parserFnT {.inline.} =
|
||||
parser: parser,
|
||||
))
|
||||
|
||||
const anyCh* = ch(AllChars)
|
||||
let anyCh* = ch(AllChars)
|
||||
|
||||
func str*(s: string): parserFnT {.inline.} =
|
||||
return func(parser: Parser): ParserResult =
|
||||
proc str*(s: string): parserFnT {.inline.} =
|
||||
return proc(parser: Parser): ParserResult =
|
||||
var p = parser.ok()
|
||||
for c in s.items:
|
||||
p = p.flatMap(ch(c))
|
||||
@@ -109,9 +109,9 @@ func str*(s: string): parserFnT {.inline.} =
|
||||
|
||||
# -- Parsing API
|
||||
|
||||
func optional*(parserFn: parserFnT): parserFnT {.inline.} =
|
||||
proc optional*(parserFn: parserFnT): parserFnT {.inline.} =
|
||||
## Parse characters and ignore failure
|
||||
return func(parser: Parser): ParserResult =
|
||||
return proc(parser: Parser): ParserResult =
|
||||
let newParser = parserFn(parser)
|
||||
|
||||
if newParser.isOk():
|
||||
@@ -119,18 +119,18 @@ func optional*(parserFn: parserFnT): parserFnT {.inline.} =
|
||||
else:
|
||||
parser.ok()
|
||||
|
||||
func ignore*(parserFn: parserFnT): parserFnT {.inline.} =
|
||||
proc ignore*(parserFn: parserFnT): parserFnT {.inline.} =
|
||||
## Parse characters but throw success tokens away
|
||||
return func(parser: Parser): ParserResult =
|
||||
return proc(parser: Parser): ParserResult =
|
||||
return parserFn(parser)
|
||||
.map((x: Parser) => Parser(
|
||||
state: x.state,
|
||||
tokens: parser.tokens,
|
||||
))
|
||||
|
||||
func manyUntilPerformant*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.inline.} =
|
||||
proc manyUntilPerformant*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.inline.} =
|
||||
## Parse characters but throw success tokens away
|
||||
return func(parser: Parser): ParserResult =
|
||||
return proc(parser: Parser): ParserResult =
|
||||
let startPosition = parser.state.position
|
||||
var res: ParserResult = parser.ok()
|
||||
|
||||
@@ -151,22 +151,22 @@ func manyUntilPerformant*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.i
|
||||
]
|
||||
))
|
||||
|
||||
func anyUntilPerformant*(stopFn: parserFnT): parserFnT {.inline.} =
|
||||
proc anyUntilPerformant*(stopFn: parserFnT): parserFnT {.inline.} =
|
||||
manyUntilPerformant(ch(AllChars), stopFn)
|
||||
|
||||
func manyUntil*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.inline.} =
|
||||
proc manyUntil*(acceptFn: parserFnT, stopFn: parserFnT): parserFnT {.inline.} =
|
||||
## Parse characters but throw success tokens away
|
||||
return func(parser: Parser): ParserResult =
|
||||
return proc(parser: Parser): ParserResult =
|
||||
var res: ParserResult = parser.ok()
|
||||
while res.isOk() and res.flatMap(stopFn).isErr():
|
||||
res = res.flatMap(acceptFn)
|
||||
return res
|
||||
|
||||
func anyUntil*(stopFn: parserFnT): parserFnT {.inline.} =
|
||||
proc anyUntil*(stopFn: parserFnT): parserFnT {.inline.} =
|
||||
manyUntil(anyCh, stopFn)
|
||||
|
||||
func choice*(parsers: seq[parserFnT]): parserFnT {.inline} =
|
||||
return func(parser: Parser): ParserResult {.closure, nosideeffect.} =
|
||||
proc choice*(parsers: seq[parserFnT]): parserFnT {.inline} =
|
||||
return proc(parser: Parser): ParserResult {.closure.} =
|
||||
var errors: seq[ParserResult] = newSeq[ParserResult]()
|
||||
var found = Nothing[ParserResult]()
|
||||
|
||||
@@ -181,7 +181,7 @@ func choice*(parsers: seq[parserFnT]): parserFnT {.inline} =
|
||||
|
||||
return found
|
||||
.fold(
|
||||
func(): ParserResult =
|
||||
proc(): ParserResult =
|
||||
let prettyErrors = errors.map((x: ParserResult) => x.error().expected)
|
||||
err(ParserError(
|
||||
kind: choiceMismatchErr,
|
||||
@@ -190,21 +190,21 @@ func choice*(parsers: seq[parserFnT]): parserFnT {.inline} =
|
||||
unexpected: errors[0].error().unexpected,
|
||||
parser: parser,
|
||||
)),
|
||||
func(x: ParserResult): ParserResult = x,
|
||||
proc(x: ParserResult): ParserResult = x,
|
||||
)
|
||||
|
||||
|
||||
func `+`*(parserFnA: parserFnT, parserFnB: parserFnT): parserFnT {.inline.} =
|
||||
proc `+`*(parserFnA: parserFnT, parserFnB: parserFnT): parserFnT {.inline.} =
|
||||
## Parse characters and ignore failure
|
||||
return func(parser: Parser): ParserResult =
|
||||
return proc(parser: Parser): ParserResult =
|
||||
parserFnA(parser).flatMap(parserFnB)
|
||||
|
||||
func parseSeq*(parser: ParserResult, xs: seq[parserFnT]): ParserResult =
|
||||
proc parseSeq*(parser: ParserResult, xs: seq[parserFnT]): ParserResult {.inline.} =
|
||||
xs.foldl(a.flatMap(b), parser)
|
||||
|
||||
# -- Parsing Aliases
|
||||
|
||||
func endOfStream*(parser: Parser): ParserResult =
|
||||
proc endOfStream*(parser: Parser): ParserResult =
|
||||
let index = parser.state.position + 1
|
||||
if index == parser.state.stream.len:
|
||||
ok(parser)
|
||||
@@ -216,27 +216,40 @@ func endOfStream*(parser: Parser): ParserResult =
|
||||
parser: parser,
|
||||
))
|
||||
|
||||
const newlineParser = choice(@[
|
||||
let newlineParser = choice(@[
|
||||
ch(NewLines),
|
||||
endOfStream,
|
||||
])
|
||||
|
||||
func newline*(parser: Parser): ParserResult =
|
||||
proc newline*(parser: Parser): ParserResult =
|
||||
newlineParser(parser)
|
||||
.mapErr((x: ParserError) => x.setErrorExpectedField("Newline"))
|
||||
|
||||
const whitespaceParser = choice(@[
|
||||
let whitespaceParser = choice(@[
|
||||
ch(Whitespace),
|
||||
newlineParser,
|
||||
])
|
||||
func whitespace*(parser: Parser): ParserResult =
|
||||
proc whitespace*(parser: Parser): ParserResult =
|
||||
whitespaceParser(parser)
|
||||
.mapErr((x: ParserError) => x.setErrorExpectedField("Whitespace"))
|
||||
|
||||
# -- Parsing Helpers
|
||||
|
||||
const parseBetweenDelimiter* = func(start: parserFnT, stop: parserFnT): parserFnT {.closure.} =
|
||||
let parseBetweenDelimiter* = proc(start: parserFnT, stop: parserFnT): parserFnT {.closure.} =
|
||||
ignore(start) + anyUntil(stop + whitespace) + ignore(start)
|
||||
|
||||
const parseBetweenPair* = func(delimiterParser: parserFnT): parserFnT {.closure.} =
|
||||
let parseBetweenPair* = proc(delimiterParser: parserFnT): parserFnT {.closure.} =
|
||||
parseBetweenDelimiter(delimiterParser, delimiterParser)
|
||||
|
||||
# -- Tests
|
||||
|
||||
when isMainModule:
|
||||
let test1 = initParserResult("123")
|
||||
|
||||
let ch1 = ch('1')
|
||||
let chDigits = @[ch(Digits)]
|
||||
|
||||
# echo type ch1
|
||||
# echo test1.flatMap((x: Parser) => ParserResult.ok(x))
|
||||
echo test1.flatMap(newlineParser)
|
||||
# .flatMap(ch1)
|
||||
|
||||
@@ -70,10 +70,10 @@ func initParser*(str: string): Parser =
|
||||
tokens: newSeq[ParserToken](),
|
||||
)
|
||||
|
||||
proc initParserResult*(str: string): ParserResult =
|
||||
func initParserResult*(str: string): ParserResult =
|
||||
ParserResult.ok(initParser(str))
|
||||
|
||||
proc initBuilder*[T](t: Builder[T], parser: Parser, tree: seq[T]): Builder[T] =
|
||||
func initBuilder*[T](t: Builder[T], parser: Parser, tree: seq[T]): Builder[T] =
|
||||
Builder[T]((
|
||||
parser,
|
||||
tree
|
||||
@@ -113,7 +113,7 @@ func emptyTokens*(parser: Parser): Parser =
|
||||
tokens: newSeq[ParserToken](),
|
||||
)
|
||||
|
||||
proc foldTokens*[T](
|
||||
func foldTokens*[T](
|
||||
parserResult: ParserResult,
|
||||
onError: ParserError -> T,
|
||||
onSuccess: seq[ParserToken] -> T,
|
||||
@@ -133,13 +133,13 @@ func setErrorExpectedField*(err: ParserError, expected: string): ParserError =
|
||||
parser: err.parser,
|
||||
)
|
||||
|
||||
proc mapTree*[T](builder: BuilderResult[T], fn: seq[T] -> seq[T]): BuilderResult[T] =
|
||||
builder.map(proc(b: Builder[T]): Builder[T] = Builder((
|
||||
func mapTree*[T](builder: BuilderResult[T], fn: seq[T] -> seq[T]): BuilderResult[T] =
|
||||
builder.map(func(b: Builder[T]): Builder[T] = Builder((
|
||||
parser: b[0],
|
||||
tree: fn(b[1]),
|
||||
)))
|
||||
|
||||
proc tryParser*[T](
|
||||
func tryParser*[T](
|
||||
builder: Builder[T],
|
||||
parser: Parser -> ParserResult,
|
||||
): BuilderResult[T] =
|
||||
@@ -155,7 +155,7 @@ proc tryParser*[T](
|
||||
(newTokens: seq[ParserToken]) => BuilderResult[T].ok(builder),
|
||||
)
|
||||
|
||||
proc tryParser*[T](
|
||||
func tryParser*[T](
|
||||
builder: BuilderResult[T],
|
||||
parser: Parser -> ParserResult,
|
||||
): BuilderResult[T] =
|
||||
@@ -163,7 +163,7 @@ proc tryParser*[T](
|
||||
## When succesful return the ok builder, otherwise return an error
|
||||
builder.flatMap((x: Builder[T]) => tryParser(x, parser))
|
||||
|
||||
proc applyParsersToSingle*[T](
|
||||
func applyParsersToSingle*[T](
|
||||
builder: Builder[T],
|
||||
parsers: seq[Parser -> ParserResult],
|
||||
tokenFoldFn: (seq[ParserToken], T) -> T,
|
||||
@@ -200,7 +200,7 @@ proc applyParsersToSingle*[T](
|
||||
)
|
||||
|
||||
## TODO Implement applyParsersSeqToSingle with this function by forming the concatFn
|
||||
proc applyParsersToSeq*[T](
|
||||
func applyParsersToSeq*[T](
|
||||
builder: Builder[T],
|
||||
parsers: seq[Parser -> ParserResult],
|
||||
tokenFoldFn: (seq[ParserToken], T) -> T,
|
||||
@@ -231,7 +231,7 @@ proc applyParsersToSeq*[T](
|
||||
)
|
||||
)
|
||||
|
||||
proc applyParsersSeqToSingle*[T](
|
||||
func applyParsersSeqToSingle*[T](
|
||||
builderResult: BuilderResult[T],
|
||||
initT: T,
|
||||
xs: seq[tuple[
|
||||
@@ -252,7 +252,7 @@ proc applyParsersSeqToSingle*[T](
|
||||
builderResult
|
||||
)
|
||||
|
||||
proc applyParsersSeqToSeq*[T](
|
||||
func applyParsersSeqToSeq*[T](
|
||||
builderResult: BuilderResult[T],
|
||||
xs: seq[tuple[
|
||||
parsers: seq[Parser -> ParserResult],
|
||||
@@ -273,12 +273,12 @@ proc applyParsersSeqToSeq*[T](
|
||||
builderResult
|
||||
)
|
||||
|
||||
proc applyParsers*[T](
|
||||
func applyParsers*[T](
|
||||
builder: Builder[T],
|
||||
parsers: seq[Parser -> ParserResult],
|
||||
tokenFoldFn: (seq[ParserToken], seq[T]) -> seq[T],
|
||||
): BuilderResult[T] =
|
||||
# proc nested(b: Builder[T]): BuilderResult[T] =
|
||||
# func nested(b: Builder[T]): BuilderResult[T] =
|
||||
let newParser = ParserResult.ok(Parser(
|
||||
state: builder[0].state,
|
||||
tokens: @[]
|
||||
@@ -293,7 +293,7 @@ proc applyParsers*[T](
|
||||
),
|
||||
)
|
||||
|
||||
proc applyParsersSeq*[T](
|
||||
func applyParsersSeq*[T](
|
||||
builder: BuilderResult[T],
|
||||
xs: seq[tuple[
|
||||
parsers: seq[Parser -> ParserResult],
|
||||
@@ -302,7 +302,7 @@ proc applyParsersSeq*[T](
|
||||
xs.foldl(a.flatMap((x: Builder[T]) => x.applyParsers(b[0], b[1])), builder)
|
||||
|
||||
|
||||
proc foldBuilder*[T, T2](
|
||||
func foldBuilder*[T, T2](
|
||||
builderResult: BuilderResult[T],
|
||||
onError: string -> T2,
|
||||
onSuccess: seq[T] -> T2,
|
||||
@@ -313,7 +313,7 @@ proc foldBuilder*[T, T2](
|
||||
let err = builderResult.error()
|
||||
onError(err[1])
|
||||
|
||||
# proc parseBuildOr*[T](
|
||||
# func parseBuildOr*[T](
|
||||
# ## Checks
|
||||
# builderResult: BuilderResult[T],
|
||||
# builders: seq[tuple[
|
||||
@@ -415,20 +415,20 @@ func highlightStreamPosition2(stream: string, position: int): string =
|
||||
|
||||
stream.dup(insert(&"{beforeNewline}{spaceChars}^{lineChars} Char at \"{escapedChar}\"\n", insertMessageAtIndex))
|
||||
|
||||
proc `$`*(x: ParserState): string =
|
||||
func `$`*(x: ParserState): string =
|
||||
&"""ParserState(
|
||||
stream: "{x.stream.highlightStreamPosition(x.position)}",
|
||||
position: {x.position},
|
||||
lastPosition: {x.lastPosition},
|
||||
)"""
|
||||
|
||||
proc `$`*(x: Parser): string =
|
||||
func `$`*(x: Parser): string =
|
||||
&"""Parser(
|
||||
state: {indentAfterNewline($x.state, 2)},
|
||||
tokens: {indentAfterNewline($x.tokens, 2)},
|
||||
)"""
|
||||
|
||||
proc `$`*(x: ParserError): string =
|
||||
func `$`*(x: ParserError): string =
|
||||
case x:
|
||||
of charMismatchErr(expected: @expected, parser: @parser, index: @index, unexpected: @unexpected):
|
||||
# TODO: Only works for single line right now
|
||||
|
||||
11
src_v2/parser/test.nim
Normal file
11
src_v2/parser/test.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
import sugar
|
||||
import results
|
||||
|
||||
func adder_generator(a: int): (int -> int) =
|
||||
return func(b: int): int =
|
||||
a + b
|
||||
|
||||
|
||||
const add_1 = adder_generator(1)
|
||||
|
||||
echo add_1(1)
|
||||
@@ -1,31 +0,0 @@
|
||||
import std/sugar
|
||||
import std/collections/sequtils
|
||||
import results
|
||||
import ./parser_types
|
||||
|
||||
type StringBuilderT* = string
|
||||
type StringBuilder* = Builder[StringBuilderT]
|
||||
type StringBuilderResult* = BuilderResult[StringBuilderT]
|
||||
|
||||
proc stringConcat*(typeInfo: StringBuilderT, seperator = ""):
|
||||
(seq[ParserToken], seq[StringBuilderT]) -> seq[StringBuilderT] =
|
||||
|
||||
return proc(xs: seq[ParserToken], ys: seq[StringBuilderT]): seq[StringBuilderT] =
|
||||
return ys & xs.foldl(a & b.tokenStringValue() & seperator, typeInfo)
|
||||
|
||||
proc initStringBuilder*(str: string): StringBuilderResult =
|
||||
StringBuilderResult
|
||||
.ok(StringBuilder((
|
||||
parser: initParser(str),
|
||||
tree: newSeq[StringBuilderT](),
|
||||
)))
|
||||
|
||||
proc fold*[T, E, T2](
|
||||
self: Result[T, E],
|
||||
onError: E -> T2,
|
||||
onSuccess: T -> T2,
|
||||
): T2 =
|
||||
if self.isOk():
|
||||
onSuccess(self.unsafeGet())
|
||||
else:
|
||||
onError(self.error())
|
||||
Reference in New Issue
Block a user