From 659bd8b797d341500fffd3bb681d99278e38bf3c Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Fri, 31 Jan 2025 20:34:00 -0500 Subject: [PATCH] feat: Working, unless it ends with a list, however using terminator isn't working at the moment. --- Sources/main.swift | 181 +++++++++++++++------------------------------ 1 file changed, 59 insertions(+), 122 deletions(-) diff --git a/Sources/main.swift b/Sources/main.swift index d63cfc9..6a462ad 100644 --- a/Sources/main.swift +++ b/Sources/main.swift @@ -2,7 +2,6 @@ import Foundation @preconcurrency import Parsing let yamlString = """ ---- author: Michael Housh categories: - HVAC @@ -14,130 +13,20 @@ date: 2023-10-21 lastmod: 2023-10-21 image: banner.png featuredImage: banner.png -series: - - General tags: - HVAC - General - Programming - ---- +title: "You Should Learn Markdown" """ _ = """ +series: + - General title: "You Should Learn Markdown" slug: "you-should-learn-markdown" """ -enum YamlItem { - case boolean(Bool) - case date(year: Int, month: Int, day: Int) - case string(String) - case listItem(String) - - private static let dateParser = Parse(input: Substring.UTF8View.self) { - Digits(4) - "-".utf8 - Digits(2) - "-".utf8 - Digits(2) - }.map { Self.date(year: $0.0, month: $0.1, day: $0.2) } - - private static let booleanParser = Parse(input: Substring.UTF8View.self) { - Bool.parser() - }.map { Self.boolean($0) } - - private static let quotedString = Parse(input: Substring.UTF8View.self) { - "\"".utf8 - PrefixUpTo("\"".utf8) - "\"".utf8 - } - - private static let stringParser = Parse(input: Substring.UTF8View.self) { - OneOf { - quotedString - Rest() - } - }.map { Self.string(String(Substring($0))) } - - private static let listItemParser = Parse(input: Substring.UTF8View.self) { - Skip { Whitespace() } - "- ".utf8 - Rest() - }.map { Self.listItem(String(Substring($0))) } - - static let parser = OneOf { - dateParser - booleanParser - listItemParser - stringParser - } -} - -let yamlBlockParser = Parse(input: Substring.UTF8View.self) { - "---\n".utf8 - Many { - PrefixUpTo(":".utf8) - ":".utf8 - Optionally { YamlItem.parser } - // PrefixUpTo("\n".utf8) - // From(.substring) { YamlLine.parser } - } separator: { - "\n".utf8 - } terminator: { - // "\n".utf8 - "---".utf8 - } -} - -let stringLine = #"author: "Michael Housh""# -// let parsedLine = try yamlLineParser.parse(stringLine[...].utf8) -// print(parsedLine) - -let stringItem = "foo" -let quotedItem = "\"foo\"" -let dateItem = "2025-01-29" -let boolItem = "true" - -try print(YamlItem.parser.parse(stringItem[...])) -try print(YamlItem.parser.parse(quotedItem[...])) -try print(YamlItem.parser.parse(dateItem[...])) -try print(YamlItem.parser.parse(boolItem[...])) - -let kvLine = "author: Michael Housh" -var listLine = #""" - - HVAC - - General - - Programming - -"""#[...] - -struct YamlList: Parser { - - var body: some Parser { - Many(into: [String]()) { array, string in - array.append(string) - } element: { - Whitespace() - "-".utf8 - Whitespace() - PrefixUpTo("\n".utf8).map(.string) - "\n".utf8 - } - } -} - -try print(YamlList().parse(listLine)) - -var yamlLines = """ -author: Michael Housh -test: - - HVAC - - General - - Programming - -"""[...] - struct SimpleYamlValue: Parser { enum Output: Equatable { case array([String]) @@ -169,17 +58,47 @@ struct SimpleYamlValue: Parser { } } -// This works, but doesn't handle lists well. struct SimpleYamlParser: Parser { - var body: some Parser { - Many(into: [String: SimpleYamlValue.Output]()) { (dict: inout [String: SimpleYamlValue.Output], pair: (String, SimpleYamlValue.Output)) in + + typealias Output = [String: SimpleYamlValue.Output] + + var body: some Parser { + Many(into: Output()) { (dict: inout Output, pair: (String, SimpleYamlValue.Output)) in let (key, value) = pair dict[key] = value } element: { - PrefixUpTo(":".utf8).map(.string) - ":".utf8 - Whitespace() - SimpleYamlValue() + // Parses a key and array. + OneOf { + Parse { + PrefixUpTo(":".utf8).map(.string) + ":\n".utf8 + Many(into: [String]()) { array, string in + array.append(string) + } element: { + From(.substring) { Whitespace() } + "-".utf8 + From(.substring) { Whitespace() } + PrefixUpTo("\n".utf8).map(.string) + } separator: { + "\n".utf8 + } + // terminator: { + // OneOf { + // Peek { PrefixUpTo(":".utf8) } + // End() + // } + // } + } + .map { ($0.0, SimpleYamlValue.Output.array($0.1)) } + + // Parse a key and a single value. + Parse { + PrefixUpTo(":".utf8).map(.string) + ":".utf8 + Whitespace() + SimpleYamlValue() + } + } } separator: { "\n".utf8 } terminator: { @@ -196,13 +115,31 @@ date: 2023-10-21 lastmod: 2023-10-21 image: banner.png featuredImage: banner.png +test: + - HVAC + - General + - Programming +foo: Bar """# +var keyedList = """ +test: + - HVAC + - General + - Programming +foo: Bar +"""[...].utf8 + +// let parsedList = try keyedListParser.parse(&keyedList) +// print(parsedList) + let parsed = try SimpleYamlParser().parse(simpleYamlString[...].utf8) -// print(parsed) +// let parsed = try SimpleYamlParser().parse(yamlString[...].utf8) for (key, value) in parsed { print("\(key): \(value)") } +// assert(parsed.keys.count == 10) + // try print(SimpleYamlParser().parse(simpleYamlString[...].utf8))