// // 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 = .discard(.zeroOrMore(.character(in: " \t\n\r"))) private let null: Consumer = .label(.null, "null") private let boolean: Consumer = .label(.boolean, "true" | "false") private let digit: Consumer = .character(in: "0" ... "9") private let number: Consumer = .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 = digit | .character(in: "a" ... "f") | .character(in: "A" ... "F") private let string: Consumer = .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 = .label(.array, [ .discard("["), .optional(.interleaved( .reference(.json), .discard(",") )), .discard("]"), ]) private let object: Consumer = .label(.object, [ .discard("{"), .optional(.interleaved( .label(.keyValue, [ space, string, space, .discard(":"), .reference(.json), ]), .discard(",") )), .discard("}"), ]) private let json: Consumer = .label(.json, [ space, boolean | null | number | string | object | array, space, ])