mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-05-17 10:30:35 +00:00
77 lines
2.3 KiB
Swift
77 lines
2.3 KiB
Swift
//
|
|
// json.swift
|
|
// JSON
|
|
//
|
|
// Created by Nick Lockwood on 12/03/2018.
|
|
// Copyright © 2018 Nick Lockwood. All rights reserved.
|
|
//
|
|
|
|
/// JSON parser
|
|
public func parseJSON(_ input: String) throws -> Any {
|
|
let match = try json.match(input)
|
|
return try match.transform(jsonTransform)!
|
|
}
|
|
|
|
/// JSON compiler
|
|
public func compileJSONParser() -> String {
|
|
return json.compile("parseJSON3", transformFunction: "jsonTransform")
|
|
}
|
|
|
|
/// JSON grammar
|
|
private let space: Consumer<JSONLabel> = .discard(.zeroOrMore(.character(in: " \t\n\r")))
|
|
private let null: Consumer<JSONLabel> = .label(.null, "null")
|
|
private let boolean: Consumer<JSONLabel> = .label(.boolean, "true" | "false")
|
|
private let digit: Consumer<JSONLabel> = .character(in: "0" ... "9")
|
|
private let number: Consumer<JSONLabel> = .label(.number, .flatten([
|
|
.optional("-"),
|
|
.any(["0", [.character(in: "1" ... "9"), .zeroOrMore(digit)]]),
|
|
.optional([".", .oneOrMore(digit)]),
|
|
.optional([
|
|
.character(in: "eE"),
|
|
.optional(.character(in: "+-")),
|
|
.oneOrMore(digit),
|
|
]),
|
|
]))
|
|
private let hexdigit: Consumer<JSONLabel> = digit | .character(in: "a" ... "f") | .character(in: "A" ... "F")
|
|
private let string: Consumer<JSONLabel> = .label(.string, [
|
|
.discard("\""),
|
|
.zeroOrMore(.any([
|
|
.flatten(.oneOrMore(.anyCharacter(except: "\"", "\\"))),
|
|
[.discard("\\"), .any([
|
|
"\"", "\\", "/",
|
|
.replace("b", "\u{8}"),
|
|
.replace("f", "\u{C}"),
|
|
.replace("n", "\n"),
|
|
.replace("r", "\r"),
|
|
.replace("t", "\t"),
|
|
.label(.unichar, .flatten([
|
|
.discard("u"), hexdigit, hexdigit, hexdigit, hexdigit,
|
|
])),
|
|
])],
|
|
])),
|
|
.discard("\""),
|
|
])
|
|
private let array: Consumer<JSONLabel> = .label(.array, [
|
|
.discard("["),
|
|
.optional(.interleaved(
|
|
.reference(.json),
|
|
.discard(",")
|
|
)),
|
|
.discard("]"),
|
|
])
|
|
private let object: Consumer<JSONLabel> = .label(.object, [
|
|
.discard("{"),
|
|
.optional(.interleaved(
|
|
.label(.keyValue, [
|
|
space, string, space,
|
|
.discard(":"),
|
|
.reference(.json),
|
|
]),
|
|
.discard(",")
|
|
)),
|
|
.discard("}"),
|
|
])
|
|
private let json: Consumer<JSONLabel> = .label(.json, [
|
|
space, boolean | null | number | string | object | array, space,
|
|
])
|