Restore delimiter parsers

This commit is contained in:
Florian Schroedl
2022-08-27 15:53:41 +02:00
parent 67e5a44d49
commit 19d2cae392
4 changed files with 354 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
import std/[
collections/sequtils,
sugar,
]
import fp/[
resultM,
]
import ./org_types
import ../parser/parser
# -- OrgInlineBlock.Builder.Type
type OrgInlineBuilderT* = OrgInlineBlock
type OrgInlineBuilder* = Builder[OrgInlineBuilderT]
type OrgInlineBuilderResult* = BuilderResult[OrgInlineBuilderT]
# -- OrgInlineBlock.Builder.Initializers
func initOrgInlineBuilder*(content: string): OrgInlineBuilderResult =
return OrgInlineBuilderResult.ok(OrgInlineBuilder((
parser: initParser(content),
tree: newSeq[OrgInlineBuilderT](),
)))
func convertTokens*(kind: orgInlineBlockKind): seq[ParserToken] -> seq[OrgInlineBuilderT] =
return func(tokens: seq[ParserToken]): seq[OrgInlineBuilderT] =
return @[
OrgInlineBuilderT(
kind: kind,
content: tokens.tokensToString(),
)
]
# func rawTextTokenizer*(kind: orgInlineBlockKind): string -> OrgInlineBuilderT =
# return func(content: string): OrgInlineBuilderT =
# return OrgInlineBuilderT(
# kind: kind,
# content: content,
# )
# ## Blocks
# type OrgBuilderT* = OrgBlock
# type OrgBuilder* = Builder[OrgBuilderT]
# type OrgBuilderResult* = BuilderResult[OrgBuilderT]
# func initOrgBuilder*(content: string): OrgBuilderResult =
# return OrgBuilderResult.ok(OrgBuilder((
# parser: initParser(content),
# tree: newSeq[OrgBuilderT](),
# )))
# # proc orgBuilderConcat*(typeInfo: OrgBuilderT, concatFn: (ParserToken, OrgBuilderT) -> OrgBuilderT):
# # (seq[ParserToken], OrgBuilderT) -> OrgBuilderT =
# # return proc(xs: seq[ParserToken], builder: OrgBuilderT): OrgBuilderT =
# # return xs.foldl(concatFn(b, a), typeInfo)
# proc orgBuilderApply*(concatFn: (ParserToken, OrgBuilderT) -> OrgBuilderT):
# (seq[ParserToken], OrgBuilderT) -> OrgBuilderT =
# return proc(tokens: seq[ParserToken], builder: OrgBuilderT): OrgBuilderT =
# tokens.foldl(concatFn(b, a), builder)

View File

@@ -0,0 +1,80 @@
import std/[
collections/sequtils,
strformat,
strutils,
sugar,
]
import fp/[
resultM,
]
import ./org_types
import ./org_builder
import ../parser/parser
# import ./org_text_link
# import ../utils/fp
# import ../parser/parser_internals
# import ../parser/parser_types
# import ../parser/builder_api
# -- Parsers
let boldParser* = anyBetweenPair(ch('*'))
let italicParser* = anyBetweenPair(ch('/'))
let underlineParser* = anyBetweenPair(ch('_'))
let verbatimParser* = anyBetweenPair(ch('='))
let codeParser* = anyBetweenPair(ch('~'))
let strikeThroughParser* = anyBetweenPair(ch('+'))
# let rawTokenizer* = rawTextTokenizer(orgRawText)
# let boldTokenizer* = textTokenizer(orgBoldText)
# let italicTokenizer* = textTokenizer(orgItalicText)
# let underlineTokenizer* = textTokenizer(orgUnderlineText)
# let verbatimTokenizer* = textTokenizer(orgVerbatimText)
# let codeTokenizer* = textTokenizer(orgCodeText)
# let strikeThroughTokenizer* = textTokenizer(orgStrikeThroughText)
# let tok = linkTokenizerSeq
# let orgStyledTextBuilders = @[
# (boldParser, boldTokenizer),
# (italicParser, italicTokenizer),
# (underlineParser, underlineTokenizer),
# (verbatimParser, verbatimTokenizer),
# (codeParser, codeTokenizer),
# (strikeThroughParser, strikeThroughTokenizer),
# (linkParser, linkTokenizerSeq),
# ]
# proc makeRawTokenOrEmpty(tokens: seq[ParserToken]): seq[OrgInlineBuilderT] =
# ## Merge all parser `tokens` into a string to tokenize for the builder.
# ## Unless the string is empty, in this case return an empty list.
# let str = tokens.foldl(a & b.tokenStringValue(), "")
# if str.len == 0: @[]
# else: @[rawTokenizer(str)]
# proc tryBuildInline*(content: string): OrgInlineBuilderResult =
# initOrgInlineBuilder(content)
# .flatMap((builder: OrgInlineBuilder) => tryParseBuild(
# builder = builder,
# builderFns = orgStyledTextBuilders,
# defaultBuilderFn = makeRawTokenOrEmpty,
# ))
# when isMainModule:
# let test = tryBuildInline(
# "Regular *bold* [[placeholder.com]] /italic/ _underline_ =verbatim= ~code~ +strikethrough+ [[https://placeholder.com][title]]"
# )
# echo test
when isMainModule:
block testParsers:
proc testParser(str: string, parser: parserFnT): string =
initParserResult(str).flatMap(parser).tokensToString()
assert testParser("*bold*", boldParser) == "bold"
assert testParser("/italic/", italicParser) == "italic"
assert testParser("_underline_", underlineParser) == "underline"
assert testParser("=verbatim=", verbatimParser) == "verbatim"
assert testParser("~code~", codeParser) == "code"
assert testParser("+strikeThrough+", strikeThroughParser) == "strikeThrough"

209
src_v2/org/org_types.nim Normal file
View File

@@ -0,0 +1,209 @@
import std/[
sequtils,
strutils,
sugar,
]
import fp/[
option,
]
import ../utils/printers
# -- OrgInlineBlock.Type
type
orgInlineBlockKind* = enum
orgRawText,
orgText,
# Formating
orgBoldText,
orgItalicText,
orgUnderlineText,
orgVerbatimText,
orgCodeText,
orgStrikeThroughText,
# Links
orgLink,
OrgInlineBlock* = ref object
children*: seq[OrgInlineBlock]
content*: string
case kind*: orgInlineBlockKind
of orgRawText: discard
of orgText: discard
# Formating
of orgBoldText: discard
of orgItalicText: discard
of orgUnderlineText: discard
of orgVerbatimText: discard
of orgCodeText: discard
of orgStrikeThroughText: discard
# Links
of orgLink:
linkUrl*: string
linkDescription*: Option[string]
# -- OrgInlineBlock.PrettyPrinters
proc `$`*(x: orgInlineBlockKind): string =
case x:
of orgRawText: "Text (Raw)"
of orgText: "Text"
# Formating
of orgBoldText: "Text (Bold)"
of orgItalicText: "Text (Italic)"
of orgUnderlineText: "Text (Underline)"
of orgVerbatimText: "Text (Verbatim)"
of orgCodeText: "Text (Code)"
of orgStrikeThroughText: "Text (StrikeThrough)"
# Links
of orgLink: "Link"
const PPRINT_INDENT_SIZE* = 2
func pprint*(x: OrgInlineBlock, indent = 0): string =
let specialFields = case x.kind:
of orgLink:
@[
("linkUrl", $x.linkUrl, true),
("linkDescription", x.linkDescription.getOrElse(""), x.linkDescription.isSome()),
]
else: @[]
let fields = @[
("kind", $x.kind, true),
("content", $x.content, x.content.len != 0),
]
.concat(specialFields)
.stringifyFields()
stringifyBlock(
"OrgInlineBlock",
indent,
fields,
)
func `$`*(x: OrgInlineBlock): string = pprint(x)
func pprint*(xs: seq[OrgInlineBlock], indent = 0): string =
stringifySeq(xs, (x: OrgInlineBlock) => pprint(x, indent), indent)
func `$`*(xs: seq[OrgInlineBlock]): string = pprint(xs)
## -- OrgBlock.Type
type
orgBlockKind* = enum
orgHeading
orgParagraph
orgNewline
OrgBlock* = ref object
children*: seq[OrgInlineBlock]
case kind*: orgBlockKind
of orgHeading:
level*: int
todo*: Option[string]
headlineContent*: seq[OrgInlineBlock]
content*: seq[OrgBlock]
of orgParagraph:
paragraphContent: seq[OrgInlineBlock]
of orgNewline: discard
## -- OrgBlock.PrettyPrinters
func pprint*(x: OrgBlock, indent = 0): string =
let fields = case x.kind:
of orgHeading:
@[
("kind", $x.kind, true),
("level", $x.level, true),
("todo", $x.todo, x.todo.isSome()),
("headlineContent", $x.headlineContent, x.headlineContent.len != 0),
("children", $x.children, x.children.len != 0),
(
"content",
("@[\n" &
x.content.map((x) => pprint(x)).join(",\n").indent(PPRINT_INDENT_SIZE) &
",\n],"
).indent(indent),
x.content.len != 0
),
]
of orgParagraph:
@[
("kind", $x.kind, true),
("paragraphContent", $x.paragraphContent, x.paragraphContent.len != 0),
]
else:
@[
("kind", $x.kind, true),
]
stringifyBlock(
"OrgBlock",
indent,
fields.stringifyFields(),
)
func `$`*(x: OrgBlock): string = pprint(x)
func pprint*(xs: seq[OrgBlock], indent = 0): string =
stringifySeq(xs, (x: OrgBlock) => pprint(x, indent), indent)
func `$`*(xs: seq[OrgBlock]): string = pprint(xs)
# -- OrgDocument.Type
type
OrgDocument* = ref object
children*: seq[OrgBlock]
# -- OrgDocument.PrettyPrinters
func pprint*(x: OrgDocument, indent = 0): string =
let fields = @[
("children", $x.children, true),
]
.stringifyFields()
stringifyBlock(
"OrgDocument",
indent,
fields,
)
func `$`*(xs: OrgDocument): string = pprint(xs)
when isMainModule:
let doc = OrgDocument(
children: @[
OrgBlock(
kind: orgHeading,
children: @[
OrgInlineBlock(
kind: orgLink,
linkUrl: "https://placeholder.com",
linkDescription: "Placeholder".some(),
),
],
content: @[
OrgBlock(
kind: orgNewline,
),
OrgBlock(
kind: orgNewline,
)
],
),
OrgBlock(kind: orgHeading, level: 1),
OrgBlock(kind: orgHeading),
]
)
echo doc

View File

@@ -143,6 +143,9 @@ func tokensToString*(parserResult: ParserResult, fallback = ""): string =
xs => xs.toString(),
)
func tokensToString*(tokens: seq[ParserToken]): string =
tokens.foldl(a & b.toString(), "")
func setErrorExpectedField*(err: ParserError, expected: string): ParserError =
ParserError(
kind: err.kind,
@@ -329,3 +332,4 @@ when isMainModule:
# tokensToString
assert testTokensSeqParserResult.tokensToString() == testExpectedStr
assert testTokensSeq.tokensToString() == testExpectedStr