Use proc, fn and const dont work

This commit is contained in:
Florian Schroedl
2022-08-19 16:10:42 +02:00
parent f154a6c9ec
commit b8ab82f95c
6 changed files with 79 additions and 178 deletions

View File

@@ -28,7 +28,7 @@
** TODO Headline content parser ** TODO Headline content parser
:LOGBOOK: :LOGBOOK:
CLOCK: [2022-08-09 Tue 17:51] CLOCK: [2022-08-09 Tue 17:51]--[2022-08-09 Tue 19:51] => 2:00
:END: :END:
So I've had some heavy misconceptions while working on the content, So I've had some heavy misconceptions while working on the content,

View File

@@ -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,
),
))

View File

@@ -14,12 +14,12 @@ import ./parser_types
# -- Types # -- Types
type parserFnT = proc(t0: Parser): ParserResult {.nosideeffect.} type parserFnT = proc(t0: Parser): ParserResult
# -- Utilities # -- Utilities
func lookBack*(count: int): (parserFnT) = proc lookBack*(count: int): (parserFnT) =
return func(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
let state = parser.state let state = parser.state
let newIndex = state.position - 1 let newIndex = state.position - 1
@@ -32,10 +32,10 @@ func lookBack*(count: int): (parserFnT) =
tokens: parser.tokens, tokens: parser.tokens,
).ok() ).ok()
# -- Parsing Functions # -- Parsing Proctions
func ch*(expectedChars: set[char]): parserFnT {.inline.} = proc ch*(expectedChars: set[char]): parserFnT {.inline.} =
return func(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
let state = parser.state let state = parser.state
let newIndex = state.position + 1 let newIndex = state.position + 1
@@ -66,8 +66,8 @@ func ch*(expectedChars: set[char]): parserFnT {.inline.} =
parser: parser, parser: parser,
)) ))
func ch*(expectedChar: char): parserFnT {.inline.} = proc ch*(expectedChar: char): parserFnT {.inline.} =
return func(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
let state = parser.state let state = parser.state
let newIndex = state.position + 1 let newIndex = state.position + 1
@@ -98,10 +98,10 @@ func ch*(expectedChar: char): parserFnT {.inline.} =
parser: parser, parser: parser,
)) ))
const anyCh* = ch(AllChars) let anyCh* = ch(AllChars)
func str*(s: string): parserFnT {.inline.} = proc str*(s: string): parserFnT {.inline.} =
return func(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
var p = parser.ok() var p = parser.ok()
for c in s.items: for c in s.items:
p = p.flatMap(ch(c)) p = p.flatMap(ch(c))
@@ -109,9 +109,9 @@ func str*(s: string): parserFnT {.inline.} =
# -- Parsing API # -- Parsing API
func optional*(parserFn: parserFnT): parserFnT {.inline.} = proc optional*(parserFn: parserFnT): parserFnT {.inline.} =
## Parse characters and ignore failure ## Parse characters and ignore failure
return func(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
let newParser = parserFn(parser) let newParser = parserFn(parser)
if newParser.isOk(): if newParser.isOk():
@@ -119,18 +119,18 @@ func optional*(parserFn: parserFnT): parserFnT {.inline.} =
else: else:
parser.ok() parser.ok()
func ignore*(parserFn: parserFnT): parserFnT {.inline.} = proc ignore*(parserFn: parserFnT): parserFnT {.inline.} =
## Parse characters but throw success tokens away ## Parse characters but throw success tokens away
return func(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
return parserFn(parser) return parserFn(parser)
.map((x: Parser) => Parser( .map((x: Parser) => Parser(
state: x.state, state: x.state,
tokens: parser.tokens, 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 ## Parse characters but throw success tokens away
return func(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
let startPosition = parser.state.position let startPosition = parser.state.position
var res: ParserResult = parser.ok() 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) 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 ## Parse characters but throw success tokens away
return func(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
var res: ParserResult = parser.ok() var res: ParserResult = parser.ok()
while res.isOk() and res.flatMap(stopFn).isErr(): while res.isOk() and res.flatMap(stopFn).isErr():
res = res.flatMap(acceptFn) res = res.flatMap(acceptFn)
return res return res
func anyUntil*(stopFn: parserFnT): parserFnT {.inline.} = proc anyUntil*(stopFn: parserFnT): parserFnT {.inline.} =
manyUntil(anyCh, stopFn) manyUntil(anyCh, stopFn)
func choice*(parsers: seq[parserFnT]): parserFnT {.inline} = proc choice*(parsers: seq[parserFnT]): parserFnT {.inline} =
return func(parser: Parser): ParserResult {.closure, nosideeffect.} = return proc(parser: Parser): ParserResult {.closure.} =
var errors: seq[ParserResult] = newSeq[ParserResult]() var errors: seq[ParserResult] = newSeq[ParserResult]()
var found = Nothing[ParserResult]() var found = Nothing[ParserResult]()
@@ -181,7 +181,7 @@ func choice*(parsers: seq[parserFnT]): parserFnT {.inline} =
return found return found
.fold( .fold(
func(): ParserResult = proc(): ParserResult =
let prettyErrors = errors.map((x: ParserResult) => x.error().expected) let prettyErrors = errors.map((x: ParserResult) => x.error().expected)
err(ParserError( err(ParserError(
kind: choiceMismatchErr, kind: choiceMismatchErr,
@@ -190,21 +190,21 @@ func choice*(parsers: seq[parserFnT]): parserFnT {.inline} =
unexpected: errors[0].error().unexpected, unexpected: errors[0].error().unexpected,
parser: parser, 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 ## Parse characters and ignore failure
return func(parser: Parser): ParserResult = return proc(parser: Parser): ParserResult =
parserFnA(parser).flatMap(parserFnB) 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) xs.foldl(a.flatMap(b), parser)
# -- Parsing Aliases # -- Parsing Aliases
func endOfStream*(parser: Parser): ParserResult = proc endOfStream*(parser: Parser): ParserResult =
let index = parser.state.position + 1 let index = parser.state.position + 1
if index == parser.state.stream.len: if index == parser.state.stream.len:
ok(parser) ok(parser)
@@ -216,27 +216,40 @@ func endOfStream*(parser: Parser): ParserResult =
parser: parser, parser: parser,
)) ))
const newlineParser = choice(@[ let newlineParser = choice(@[
ch(NewLines), ch(NewLines),
endOfStream, endOfStream,
]) ])
func newline*(parser: Parser): ParserResult = proc newline*(parser: Parser): ParserResult =
newlineParser(parser) newlineParser(parser)
.mapErr((x: ParserError) => x.setErrorExpectedField("Newline")) .mapErr((x: ParserError) => x.setErrorExpectedField("Newline"))
const whitespaceParser = choice(@[ let whitespaceParser = choice(@[
ch(Whitespace), ch(Whitespace),
newlineParser, newlineParser,
]) ])
func whitespace*(parser: Parser): ParserResult = proc whitespace*(parser: Parser): ParserResult =
whitespaceParser(parser) whitespaceParser(parser)
.mapErr((x: ParserError) => x.setErrorExpectedField("Whitespace")) .mapErr((x: ParserError) => x.setErrorExpectedField("Whitespace"))
# -- Parsing Helpers # -- 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) ignore(start) + anyUntil(stop + whitespace) + ignore(start)
const parseBetweenPair* = func(delimiterParser: parserFnT): parserFnT {.closure.} = let parseBetweenPair* = proc(delimiterParser: parserFnT): parserFnT {.closure.} =
parseBetweenDelimiter(delimiterParser, delimiterParser) 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)

View File

@@ -70,10 +70,10 @@ func initParser*(str: string): Parser =
tokens: newSeq[ParserToken](), tokens: newSeq[ParserToken](),
) )
proc initParserResult*(str: string): ParserResult = func initParserResult*(str: string): ParserResult =
ParserResult.ok(initParser(str)) 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](( Builder[T]((
parser, parser,
tree tree
@@ -113,7 +113,7 @@ func emptyTokens*(parser: Parser): Parser =
tokens: newSeq[ParserToken](), tokens: newSeq[ParserToken](),
) )
proc foldTokens*[T]( func foldTokens*[T](
parserResult: ParserResult, parserResult: ParserResult,
onError: ParserError -> T, onError: ParserError -> T,
onSuccess: seq[ParserToken] -> T, onSuccess: seq[ParserToken] -> T,
@@ -133,13 +133,13 @@ func setErrorExpectedField*(err: ParserError, expected: string): ParserError =
parser: err.parser, parser: err.parser,
) )
proc mapTree*[T](builder: BuilderResult[T], fn: seq[T] -> seq[T]): BuilderResult[T] = func mapTree*[T](builder: BuilderResult[T], fn: seq[T] -> seq[T]): BuilderResult[T] =
builder.map(proc(b: Builder[T]): Builder[T] = Builder(( builder.map(func(b: Builder[T]): Builder[T] = Builder((
parser: b[0], parser: b[0],
tree: fn(b[1]), tree: fn(b[1]),
))) )))
proc tryParser*[T]( func tryParser*[T](
builder: Builder[T], builder: Builder[T],
parser: Parser -> ParserResult, parser: Parser -> ParserResult,
): BuilderResult[T] = ): BuilderResult[T] =
@@ -155,7 +155,7 @@ proc tryParser*[T](
(newTokens: seq[ParserToken]) => BuilderResult[T].ok(builder), (newTokens: seq[ParserToken]) => BuilderResult[T].ok(builder),
) )
proc tryParser*[T]( func tryParser*[T](
builder: BuilderResult[T], builder: BuilderResult[T],
parser: Parser -> ParserResult, parser: Parser -> ParserResult,
): BuilderResult[T] = ): BuilderResult[T] =
@@ -163,7 +163,7 @@ proc tryParser*[T](
## When succesful return the ok builder, otherwise return an error ## When succesful return the ok builder, otherwise return an error
builder.flatMap((x: Builder[T]) => tryParser(x, parser)) builder.flatMap((x: Builder[T]) => tryParser(x, parser))
proc applyParsersToSingle*[T]( func applyParsersToSingle*[T](
builder: Builder[T], builder: Builder[T],
parsers: seq[Parser -> ParserResult], parsers: seq[Parser -> ParserResult],
tokenFoldFn: (seq[ParserToken], T) -> T, tokenFoldFn: (seq[ParserToken], T) -> T,
@@ -200,7 +200,7 @@ proc applyParsersToSingle*[T](
) )
## TODO Implement applyParsersSeqToSingle with this function by forming the concatFn ## TODO Implement applyParsersSeqToSingle with this function by forming the concatFn
proc applyParsersToSeq*[T]( func applyParsersToSeq*[T](
builder: Builder[T], builder: Builder[T],
parsers: seq[Parser -> ParserResult], parsers: seq[Parser -> ParserResult],
tokenFoldFn: (seq[ParserToken], T) -> T, tokenFoldFn: (seq[ParserToken], T) -> T,
@@ -231,7 +231,7 @@ proc applyParsersToSeq*[T](
) )
) )
proc applyParsersSeqToSingle*[T]( func applyParsersSeqToSingle*[T](
builderResult: BuilderResult[T], builderResult: BuilderResult[T],
initT: T, initT: T,
xs: seq[tuple[ xs: seq[tuple[
@@ -252,7 +252,7 @@ proc applyParsersSeqToSingle*[T](
builderResult builderResult
) )
proc applyParsersSeqToSeq*[T]( func applyParsersSeqToSeq*[T](
builderResult: BuilderResult[T], builderResult: BuilderResult[T],
xs: seq[tuple[ xs: seq[tuple[
parsers: seq[Parser -> ParserResult], parsers: seq[Parser -> ParserResult],
@@ -273,12 +273,12 @@ proc applyParsersSeqToSeq*[T](
builderResult builderResult
) )
proc applyParsers*[T]( func applyParsers*[T](
builder: Builder[T], builder: Builder[T],
parsers: seq[Parser -> ParserResult], parsers: seq[Parser -> ParserResult],
tokenFoldFn: (seq[ParserToken], seq[T]) -> seq[T], tokenFoldFn: (seq[ParserToken], seq[T]) -> seq[T],
): BuilderResult[T] = ): BuilderResult[T] =
# proc nested(b: Builder[T]): BuilderResult[T] = # func nested(b: Builder[T]): BuilderResult[T] =
let newParser = ParserResult.ok(Parser( let newParser = ParserResult.ok(Parser(
state: builder[0].state, state: builder[0].state,
tokens: @[] tokens: @[]
@@ -293,7 +293,7 @@ proc applyParsers*[T](
), ),
) )
proc applyParsersSeq*[T]( func applyParsersSeq*[T](
builder: BuilderResult[T], builder: BuilderResult[T],
xs: seq[tuple[ xs: seq[tuple[
parsers: seq[Parser -> ParserResult], 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) 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], builderResult: BuilderResult[T],
onError: string -> T2, onError: string -> T2,
onSuccess: seq[T] -> T2, onSuccess: seq[T] -> T2,
@@ -313,7 +313,7 @@ proc foldBuilder*[T, T2](
let err = builderResult.error() let err = builderResult.error()
onError(err[1]) onError(err[1])
# proc parseBuildOr*[T]( # func parseBuildOr*[T](
# ## Checks # ## Checks
# builderResult: BuilderResult[T], # builderResult: BuilderResult[T],
# builders: seq[tuple[ # 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)) stream.dup(insert(&"{beforeNewline}{spaceChars}^{lineChars} Char at \"{escapedChar}\"\n", insertMessageAtIndex))
proc `$`*(x: ParserState): string = func `$`*(x: ParserState): string =
&"""ParserState( &"""ParserState(
stream: "{x.stream.highlightStreamPosition(x.position)}", stream: "{x.stream.highlightStreamPosition(x.position)}",
position: {x.position}, position: {x.position},
lastPosition: {x.lastPosition}, lastPosition: {x.lastPosition},
)""" )"""
proc `$`*(x: Parser): string = func `$`*(x: Parser): string =
&"""Parser( &"""Parser(
state: {indentAfterNewline($x.state, 2)}, state: {indentAfterNewline($x.state, 2)},
tokens: {indentAfterNewline($x.tokens, 2)}, tokens: {indentAfterNewline($x.tokens, 2)},
)""" )"""
proc `$`*(x: ParserError): string = func `$`*(x: ParserError): string =
case x: case x:
of charMismatchErr(expected: @expected, parser: @parser, index: @index, unexpected: @unexpected): of charMismatchErr(expected: @expected, parser: @parser, index: @index, unexpected: @unexpected):
# TODO: Only works for single line right now # TODO: Only works for single line right now

11
src_v2/parser/test.nim Normal file
View 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)

View File

@@ -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())