import Foundation @preconcurrency import Parsing let yamlString = """ --- author: Michael Housh categories: - HVAC - General - Programming copy: true draft: false 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" 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]) case bool(Bool) case date(year: Int, month: Int, day: Int) case string(String) } var body: some Parser { OneOf { // YamlList().map { Output.array($0) } DateParser() Bool.parser().map(.case(Output.bool)) PrefixUpTo("\n".utf8).map(.string).map(.case(Output.string)) Rest().map(.string).map(.case(Output.string)) } } struct DateParser: Parser { var body: some Parser { Parse { Digits(4) "-".utf8 Digits(2) "-".utf8 Digits(2) }.map(.case(Output.date)) } } } // 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 let (key, value) = pair dict[key] = value } element: { PrefixUpTo(":".utf8).map(.string) ":".utf8 Whitespace() SimpleYamlValue() } separator: { "\n".utf8 } terminator: { End() } } } let simpleYamlString = #""" author: Michael Housh copy: true draft: false date: 2023-10-21 lastmod: 2023-10-21 image: banner.png featuredImage: banner.png """# let parsed = try SimpleYamlParser().parse(simpleYamlString[...].utf8) // print(parsed) for (key, value) in parsed { print("\(key): \(value)") } // try print(SimpleYamlParser().parse(simpleYamlString[...].utf8))