From 29250af57949705c3350c28d5360261b1d152a7b Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 13:31:09 -0400 Subject: [PATCH 01/15] stub JSONParserTests --- prototype/Doubt.xcodeproj/project.pbxproj | 44 ++++++++++++---------- prototype/DoubtTests/JSONParserTests.swift | 20 ++++++++++ 2 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 prototype/DoubtTests/JSONParserTests.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 241cf7aa1..272ca8764 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -8,18 +8,19 @@ /* Begin PBXBuildFile section */ D18FF8821BD0404700D18F2D /* Madness.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D18FF8811BD0404700D18F2D /* Madness.framework */; }; - D1A0934E1BD18969005A6326 /* JSONLeaf.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934C1BD188F5005A6326 /* JSONLeaf.swift */; settings = {ASSET_TAGS = (); }; }; - D1A0934F1BD189B4005A6326 /* JSONParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934A1BD188CA005A6326 /* JSONParser.swift */; settings = {ASSET_TAGS = (); }; }; - D40B89C41BC319070078E098 /* Matrix.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40B89C31BC319070078E098 /* Matrix.swift */; settings = {ASSET_TAGS = (); }; }; + D1A0934E1BD18969005A6326 /* JSONLeaf.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934C1BD188F5005A6326 /* JSONLeaf.swift */; }; + D1A0934F1BD189B4005A6326 /* JSONParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934A1BD188CA005A6326 /* JSONParser.swift */; }; + D1F5FE201BDE891F0048BAE4 /* JSONParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F5FE1F1BDE891F0048BAE4 /* JSONParserTests.swift */; }; + D40B89C41BC319070078E098 /* Matrix.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40B89C31BC319070078E098 /* Matrix.swift */; }; D40B89C81BC439000078E098 /* Assertions.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40B89C71BC439000078E098 /* Assertions.framework */; }; - D40D72541BCEEB1F001B7A9E /* InterpreterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D72531BCEEB1F001B7A9E /* InterpreterTests.swift */; settings = {ASSET_TAGS = (); }; }; - D40D72561BCFF360001B7A9E /* Interpreter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D72551BCFF360001B7A9E /* Interpreter.swift */; settings = {ASSET_TAGS = (); }; }; + D40D72541BCEEB1F001B7A9E /* InterpreterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D72531BCEEB1F001B7A9E /* InterpreterTests.swift */; }; + D40D72561BCFF360001B7A9E /* Interpreter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D72551BCFF360001B7A9E /* Interpreter.swift */; }; D40D725A1BD15321001B7A9E /* SwiftCheck.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40D72591BD15321001B7A9E /* SwiftCheck.framework */; }; - D40D725C1BD15417001B7A9E /* RangedTerm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D725B1BD15417001B7A9E /* RangedTerm.swift */; settings = {ASSET_TAGS = (); }; }; - D40D725E1BD1826C001B7A9E /* TermTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D725D1BD1826C001B7A9E /* TermTests.swift */; settings = {ASSET_TAGS = (); }; }; - D40D72601BD19E69001B7A9E /* DiffTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D725F1BD19E69001B7A9E /* DiffTests.swift */; settings = {ASSET_TAGS = (); }; }; - D40D72621BD1A07E001B7A9E /* UnannotatedTerm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D72611BD1A07E001B7A9E /* UnannotatedTerm.swift */; settings = {ASSET_TAGS = (); }; }; - D40D72641BD1A0C1001B7A9E /* RangedDiff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D72631BD1A0C1001B7A9E /* RangedDiff.swift */; settings = {ASSET_TAGS = (); }; }; + D40D725C1BD15417001B7A9E /* RangedTerm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D725B1BD15417001B7A9E /* RangedTerm.swift */; }; + D40D725E1BD1826C001B7A9E /* TermTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D725D1BD1826C001B7A9E /* TermTests.swift */; }; + D40D72601BD19E69001B7A9E /* DiffTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D725F1BD19E69001B7A9E /* DiffTests.swift */; }; + D40D72621BD1A07E001B7A9E /* UnannotatedTerm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D72611BD1A07E001B7A9E /* UnannotatedTerm.swift */; }; + D40D72641BD1A0C1001B7A9E /* RangedDiff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D72631BD1A0C1001B7A9E /* RangedDiff.swift */; }; D42F096B1BCCC41600B95610 /* Either.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42F09671BCCC41600B95610 /* Either.framework */; }; D42F096C1BCCC41600B95610 /* Memo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42F09681BCCC41600B95610 /* Memo.framework */; }; D42F096D1BCCC41600B95610 /* Prelude.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42F09691BCCC41600B95610 /* Prelude.framework */; }; @@ -32,25 +33,25 @@ D42F09781BCCC5DC00B95610 /* Memo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42F09681BCCC41600B95610 /* Memo.framework */; }; D42F09791BCCC5DC00B95610 /* Prelude.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42F09691BCCC41600B95610 /* Prelude.framework */; }; D42F097A1BCCC5DC00B95610 /* Stream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42F096A1BCCC41600B95610 /* Stream.framework */; }; - D42F097C1BCE914A00B95610 /* Cofree.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42F097B1BCE914A00B95610 /* Cofree.swift */; settings = {ASSET_TAGS = (); }; }; - D42F097E1BCEAEDA00B95610 /* Operation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42F097D1BCEAEDA00B95610 /* Operation.swift */; settings = {ASSET_TAGS = (); }; }; - D42F09801BCECB7900B95610 /* TermType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42F097F1BCECB7900B95610 /* TermType.swift */; settings = {ASSET_TAGS = (); }; }; + D42F097C1BCE914A00B95610 /* Cofree.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42F097B1BCE914A00B95610 /* Cofree.swift */; }; + D42F097E1BCEAEDA00B95610 /* Operation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42F097D1BCEAEDA00B95610 /* Operation.swift */; }; + D42F09801BCECB7900B95610 /* TermType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42F097F1BCECB7900B95610 /* TermType.swift */; }; D432D4711BA9AC0B00F3FABC /* SESTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4701BA9AC0B00F3FABC /* SESTests.swift */; }; D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; - D45A36C91BBC667D00BE3DDE /* Categorizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45A36C81BBC667D00BE3DDE /* Categorizable.swift */; settings = {ASSET_TAGS = (); }; }; - D49FCBC41BBEF98E00C5E9C3 /* Free.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC31BBEF98E00C5E9C3 /* Free.swift */; settings = {ASSET_TAGS = (); }; }; - D49FCBC61BBF214300C5E9C3 /* Patch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC51BBF214300C5E9C3 /* Patch.swift */; settings = {ASSET_TAGS = (); }; }; - D49FCBC81BBF2C4300C5E9C3 /* Algorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC71BBF2C4300C5E9C3 /* Algorithm.swift */; settings = {ASSET_TAGS = (); }; }; + D45A36C91BBC667D00BE3DDE /* Categorizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45A36C81BBC667D00BE3DDE /* Categorizable.swift */; }; + D49FCBC41BBEF98E00C5E9C3 /* Free.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC31BBEF98E00C5E9C3 /* Free.swift */; }; + D49FCBC61BBF214300C5E9C3 /* Patch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC51BBF214300C5E9C3 /* Patch.swift */; }; + D49FCBC81BBF2C4300C5E9C3 /* Algorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC71BBF2C4300C5E9C3 /* Algorithm.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* RangeReplaceableCollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */; }; D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53A1B5AE2D0004E581F /* Operators.swift */; }; D4AAE5471B5AE2D0004E581F /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53C1B5AE2D0004E581F /* Optional.swift */; }; D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */; }; D4AAE54A1B5AE2D0004E581F /* Syntax.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53F1B5AE2D0004E581F /* Syntax.swift */; }; - D4DF96ED1BC46B630040F41F /* SES.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DF96EC1BC46B630040F41F /* SES.swift */; settings = {ASSET_TAGS = (); }; }; - D4DF970A1BC5DF800040F41F /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DF97091BC5DF800040F41F /* main.swift */; settings = {ASSET_TAGS = (); }; }; - D4DF970C1BC5DF9E0040F41F /* BoundsCheckedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D435B7521BB31BBC000902F6 /* BoundsCheckedArray.swift */; settings = {ASSET_TAGS = (); }; }; + D4DF96ED1BC46B630040F41F /* SES.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DF96EC1BC46B630040F41F /* SES.swift */; }; + D4DF970A1BC5DF800040F41F /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DF97091BC5DF800040F41F /* main.swift */; }; + D4DF970C1BC5DF9E0040F41F /* BoundsCheckedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D435B7521BB31BBC000902F6 /* BoundsCheckedArray.swift */; }; D4DF970D1BC5E1B40040F41F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; /* End PBXBuildFile section */ @@ -68,6 +69,7 @@ D18FF8811BD0404700D18F2D /* Madness.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Madness.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Doubt-gibmbsxjgxflybarnuoisglmgdll/Build/Products/Debug/Madness.framework"; sourceTree = ""; }; D1A0934A1BD188CA005A6326 /* JSONParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONParser.swift; sourceTree = ""; }; D1A0934C1BD188F5005A6326 /* JSONLeaf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONLeaf.swift; sourceTree = ""; }; + D1F5FE1F1BDE891F0048BAE4 /* JSONParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONParserTests.swift; sourceTree = ""; }; D40B89C31BC319070078E098 /* Matrix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Matrix.swift; sourceTree = ""; }; D40B89C71BC439000078E098 /* Assertions.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Assertions.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D40D72531BCEEB1F001B7A9E /* InterpreterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterpreterTests.swift; sourceTree = ""; }; @@ -215,6 +217,7 @@ D4AAE5111B5AE22E004E581F /* DoubtTests */ = { isa = PBXGroup; children = ( + D1F5FE1F1BDE891F0048BAE4 /* JSONParserTests.swift */, D432D4701BA9AC0B00F3FABC /* SESTests.swift */, D40D72531BCEEB1F001B7A9E /* InterpreterTests.swift */, D40D725B1BD15417001B7A9E /* RangedTerm.swift */, @@ -400,6 +403,7 @@ files = ( D40D72641BD1A0C1001B7A9E /* RangedDiff.swift in Sources */, D40D725E1BD1826C001B7A9E /* TermTests.swift in Sources */, + D1F5FE201BDE891F0048BAE4 /* JSONParserTests.swift in Sources */, D40D72601BD19E69001B7A9E /* DiffTests.swift in Sources */, D432D4711BA9AC0B00F3FABC /* SESTests.swift in Sources */, D40D72621BD1A07E001B7A9E /* UnannotatedTerm.swift in Sources */, diff --git a/prototype/DoubtTests/JSONParserTests.swift b/prototype/DoubtTests/JSONParserTests.swift new file mode 100644 index 000000000..6dbf19211 --- /dev/null +++ b/prototype/DoubtTests/JSONParserTests.swift @@ -0,0 +1,20 @@ +import Assertions +import Doubt +import Prelude +import Madness +import XCTest + +final class JSONParserTests: XCTestCase { + func testCapturesKeysInKeyedElements() { + let dictWithArray = "{\"hello\": [\"world\"],\"sup\": [\"cat\", \"dog\", \"keith\"] }" + + let expected: Cofree> = Cofree(0..<61, .Keyed([ + "hello": Cofree(11..<42, .Indexed([ + Cofree(17..<24, "world"), + Cofree(30..<38, "sailor") + ])), + "goodbye": Cofree(57..<59, .Indexed([])) + ])) + +// assert(Madness.parse(Doubt.json, input: dictWithArray).right, == , ) + } From d40ec59f6103003ad348a99e6198d1bae7c7c336 Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 13:31:25 -0400 Subject: [PATCH 02/15] WIP .Fixed dictionaries --- prototype/Doubt/JSONParser.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index 90b503f11..08fb01cdb 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -92,7 +92,13 @@ let json: JSONParser = fix { json in <* %"}" <* whitespace --> { (_, range, values) in - Cofree(range, .Keyed(Dictionary(elements: values))) + let vs: [CofreeJSON] = values.map({ (string, value) in + let valueRange = value.extract + let newRange = Range(start: range.startIndex, end: valueRange.endIndex) + return Cofree(newRange, .Keyed([string: value])) + }) + + return Cofree(range, .Fixed(vs)) } "object" let doubleParser: DoubleParser = number From 3802854f4e0aa1410730d774357c4cf5dcc0472d Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 15:05:58 -0400 Subject: [PATCH 03/15] Add failing test --- prototype/DoubtTests/JSONParserTests.swift | 26 ++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/prototype/DoubtTests/JSONParserTests.swift b/prototype/DoubtTests/JSONParserTests.swift index 6dbf19211..e9fb78cb7 100644 --- a/prototype/DoubtTests/JSONParserTests.swift +++ b/prototype/DoubtTests/JSONParserTests.swift @@ -6,15 +6,23 @@ import XCTest final class JSONParserTests: XCTestCase { func testCapturesKeysInKeyedElements() { - let dictWithArray = "{\"hello\": [\"world\"],\"sup\": [\"cat\", \"dog\", \"keith\"] }" + let dictWithArray = "{ \"hello\":\n [\"world\",\n \"sailor\"\n ]}" + let array: Cofree> = Cofree(15..<41, .Indexed([ + Cofree(16..<23, .Leaf(.String("world"))), + Cofree(29..<37, .Leaf(.String("sailor"))) + ])) - let expected: Cofree> = Cofree(0..<61, .Keyed([ - "hello": Cofree(11..<42, .Indexed([ - Cofree(17..<24, "world"), - Cofree(30..<38, "sailor") - ])), - "goodbye": Cofree(57..<59, .Indexed([])) - ])) + let fixedPairs: Cofree> = Cofree(2..<41, .Keyed(["hello": array])) -// assert(Madness.parse(Doubt.json, input: dictWithArray).right, == , ) + let expected: Cofree> = Cofree(0..<42, .Fixed([fixedPairs])) + let actual = Madness.parse(json, input: dictWithArray).right! + let firstIndex = actual.extract + let new: Cofree> = actual.map({ range in + let startI: Int = firstIndex.startIndex.distanceTo(range.startIndex) + let endI: Int = firstIndex.startIndex.distanceTo(range.endIndex) + return Range(start: startI, end: endI) + }) + + assert(new, == , expected) } +} From 92539dec5495c60cf1bc7191e3183cac3d143e4e Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 15:06:33 -0400 Subject: [PATCH 04/15] Make JSONLeaf and JSONParser public --- prototype/Doubt.xcodeproj/project.pbxproj | 6 ++++-- prototype/Doubt/JSONLeaf.swift | 9 ++++----- prototype/Doubt/JSONParser.swift | 7 +++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 272ca8764..7493bf2b0 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -9,8 +9,9 @@ /* Begin PBXBuildFile section */ D18FF8821BD0404700D18F2D /* Madness.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D18FF8811BD0404700D18F2D /* Madness.framework */; }; D1A0934E1BD18969005A6326 /* JSONLeaf.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934C1BD188F5005A6326 /* JSONLeaf.swift */; }; - D1A0934F1BD189B4005A6326 /* JSONParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934A1BD188CA005A6326 /* JSONParser.swift */; }; D1F5FE201BDE891F0048BAE4 /* JSONParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F5FE1F1BDE891F0048BAE4 /* JSONParserTests.swift */; }; + D1F5FE211BDE9C450048BAE4 /* JSONLeaf.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934C1BD188F5005A6326 /* JSONLeaf.swift */; }; + D1F5FE221BDE9CC10048BAE4 /* JSONParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934A1BD188CA005A6326 /* JSONParser.swift */; }; D40B89C41BC319070078E098 /* Matrix.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40B89C31BC319070078E098 /* Matrix.swift */; }; D40B89C81BC439000078E098 /* Assertions.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40B89C71BC439000078E098 /* Assertions.framework */; }; D40D72541BCEEB1F001B7A9E /* InterpreterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40D72531BCEEB1F001B7A9E /* InterpreterTests.swift */; }; @@ -382,6 +383,7 @@ D42F097E1BCEAEDA00B95610 /* Operation.swift in Sources */, D45A36C91BBC667D00BE3DDE /* Categorizable.swift in Sources */, D4DF96ED1BC46B630040F41F /* SES.swift in Sources */, + D1F5FE221BDE9CC10048BAE4 /* JSONParser.swift in Sources */, D42F09801BCECB7900B95610 /* TermType.swift in Sources */, D4AAE5401B5AE2D0004E581F /* RangeReplaceableCollectionType.swift in Sources */, D49FCBC41BBEF98E00C5E9C3 /* Free.swift in Sources */, @@ -393,6 +395,7 @@ D40B89C41BC319070078E098 /* Matrix.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */, + D1F5FE211BDE9C450048BAE4 /* JSONLeaf.swift in Sources */, D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -418,7 +421,6 @@ files = ( D4DF970A1BC5DF800040F41F /* main.swift in Sources */, D1A0934E1BD18969005A6326 /* JSONLeaf.swift in Sources */, - D1A0934F1BD189B4005A6326 /* JSONParser.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/prototype/Doubt/JSONLeaf.swift b/prototype/Doubt/JSONLeaf.swift index aa89e6961..d1afc4639 100644 --- a/prototype/Doubt/JSONLeaf.swift +++ b/prototype/Doubt/JSONLeaf.swift @@ -7,12 +7,11 @@ // import Foundation -import Doubt typealias Term = Cofree> typealias Diff = Free> -enum JSONLeaf: CustomJSONConvertible, CustomStringConvertible, Equatable { +public enum JSONLeaf: CustomJSONConvertible, CustomStringConvertible, Equatable { case Number(Double) case Boolean(Bool) case String(Swift.String) @@ -21,7 +20,7 @@ enum JSONLeaf: CustomJSONConvertible, CustomStringConvertible, Equatable { // MARK: CustomJSONConvertible - var JSON: Doubt.JSON { + public var JSON: Doubt.JSON { switch self { case let .Number(n): return .Number(n) @@ -37,7 +36,7 @@ enum JSONLeaf: CustomJSONConvertible, CustomStringConvertible, Equatable { // MARK: CustomStringConvertible - var description: Swift.String { + public var description: Swift.String { switch self { case let .Number(n): return Swift.String(n) @@ -51,7 +50,7 @@ enum JSONLeaf: CustomJSONConvertible, CustomStringConvertible, Equatable { } } -func == (left: JSONLeaf, right: JSONLeaf) -> Bool { +public func == (left: JSONLeaf, right: JSONLeaf) -> Bool { switch (left, right) { case let (.Number(a), .Number(b)): return a == b diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index 08fb01cdb..87d36725a 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -10,10 +10,9 @@ import Foundation import Madness import Either import Prelude -import Doubt -typealias CofreeJSON = Cofree> -typealias JSONParser = Parser.Function +public typealias CofreeJSON = Cofree> +public typealias JSONParser = Parser.Function extension String: CollectionType { public var count: Index.Distance { @@ -70,7 +69,7 @@ func elements(json: JSONParser) -> ValuesParser { return sepBy(value, %",") } -let json: JSONParser = fix { json in +public let json: JSONParser = fix { json in // TODO: Parse backslashed escape characters let string: JSONParser = quoted --> { From e59946aa0ab697e79a68304f3dcbd48d2f99b25d Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 15:06:45 -0400 Subject: [PATCH 05/15] Return Members as Fixed --- prototype/Doubt/JSONParser.swift | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index 87d36725a..99706ea94 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -39,16 +39,18 @@ let stringBody: StringParser = { $0.map({ String($0) }).joinWithSeparator("") } String.lift(noneOf("\"")*) let quoted = %"\"" *> stringBody <* %"\"" <* whitespace -typealias MembersParser = Parser.Function; +typealias MembersParser = Parser.Function; // Parses an array of (String, CofreeJSON) object members func members(json: JSONParser) -> MembersParser { - let pairs: Parser.Function = (curry(pair) <^> + let pairs: Parser.Function = (curry(pair) <^> quoted <* whitespace <* %":" <* whitespace - <*> json) + <*> json) --> { (_, range, values) in + Cofree(range, .Keyed(Dictionary(dictionaryLiteral: values))) + } let separatedPairs: MembersParser = (%"," *> whitespace *> pairs <* whitespace)* @@ -91,13 +93,7 @@ public let json: JSONParser = fix { json in <* %"}" <* whitespace --> { (_, range, values) in - let vs: [CofreeJSON] = values.map({ (string, value) in - let valueRange = value.extract - let newRange = Range(start: range.startIndex, end: valueRange.endIndex) - return Cofree(newRange, .Keyed([string: value])) - }) - - return Cofree(range, .Fixed(vs)) + Cofree(range, .Fixed(values)) } "object" let doubleParser: DoubleParser = number From 98d8d520487d31dd206969ccb9dd148956f6930a Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 16:36:22 -0400 Subject: [PATCH 06/15] sepBy --- prototype/Doubt/JSONParser.swift | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index 99706ea94..928d1aa90 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -52,14 +52,7 @@ func members(json: JSONParser) -> MembersParser { Cofree(range, .Keyed(Dictionary(dictionaryLiteral: values))) } - let separatedPairs: MembersParser = (%"," *> whitespace *> pairs <* whitespace)* - - let oneOrMore: MembersParser = curry { [$0] + $1 } <^> - pairs - <* whitespace - <*> separatedPairs - - return oneOrMore <|> pure([]) + return sepBy(pairs, %",") } typealias ValuesParser = Parser.Function; From 14fac1df3c35fa14fc61e5066dd35f76dded275d Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 16:37:34 -0400 Subject: [PATCH 07/15] don't parse whitespace ranges along with syntax --- prototype/Doubt/JSONParser.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index 928d1aa90..ee672b55e 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -35,9 +35,8 @@ let whitespace: CharacterParser = String.lift(satisfy({ whitespaceChars.contains // Quoted strings parser // TODO: Improve string parsing -let stringBody: StringParser = { $0.map({ String($0) }).joinWithSeparator("") } <^> - String.lift(noneOf("\"")*) -let quoted = %"\"" *> stringBody <* %"\"" <* whitespace +let stringBody: StringParser = { $0.joinWithSeparator("") } <^> many(charP) +let quoted = %"\"" *> stringBody <* %"\"" typealias MembersParser = Parser.Function; @@ -59,8 +58,7 @@ typealias ValuesParser = Parser.Function; // Parses an array of CofreeJSON array values func elements(json: JSONParser) -> ValuesParser { - let value: Parser.Function = whitespace *> json <* whitespace - + let value: Parser.Function = whitespace *> json return sepBy(value, %",") } @@ -74,8 +72,9 @@ public let json: JSONParser = fix { json in let array: JSONParser = %"[" <* whitespace *> elements(json) + <* whitespace <* %"]" - <* whitespace --> { + --> { Cofree($1, .Indexed($2)) } "array" @@ -84,7 +83,6 @@ public let json: JSONParser = fix { json in *> members(json) <* whitespace <* %"}" - <* whitespace --> { (_, range, values) in Cofree(range, .Fixed(values)) } "object" @@ -106,5 +104,5 @@ public let json: JSONParser = fix { json in // TODO: This should be JSON = dict <|> array and // Value = dict | array | string | number | null | bool - return object <|> array <|> string <|> numberParser <|> boolean <|> null + return (object <|> array <|> string <|> numberParser <|> boolean <|> null) <* whitespace } From 3d84c3be73f75e307a1f6bd72623a8e856296c86 Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 16:37:50 -0400 Subject: [PATCH 08/15] Improve escape character parsing --- prototype/Doubt/JSONParser.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index ee672b55e..44da2bef7 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -33,6 +33,13 @@ typealias CharacterParser = Parser.Function let whitespaceChars: [Character] = [" ", "\n", "\t", "\r"] let whitespace: CharacterParser = String.lift(satisfy({ whitespaceChars.contains($0) })*) +// TODO: Parse unicode escape sequence +let escapeChar: StringParser = %"\\\\" <|> %"\\\"" <|> %"\\b" <|> %"\\f" <|> %"\\n" <|> %"\\r" <|> %"\\t" +let otherChar: StringParser = { String($0) } <^> satisfy { c in + c != "\"" && c != "\\" +} +let charP: StringParser = escapeChar <|> otherChar + // Quoted strings parser // TODO: Improve string parsing let stringBody: StringParser = { $0.joinWithSeparator("") } <^> many(charP) From b9be03e540f994bcb5124ed3c5a534a5c1a210bd Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 16:38:07 -0400 Subject: [PATCH 09/15] Add Fixed case to Syntax.equals --- prototype/Doubt/Syntax.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index 191232e64..0db5f3f37 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -91,6 +91,8 @@ extension Syntax { return leaf(l1, l2) case let (.Indexed(v1), .Indexed(v2)): return v1.count == v2.count && zip(v1, v2).lazy.map(recur).reduce(true) { $0 && $1 } + case let (.Fixed(v1), .Fixed(v2)): + return v1.count == v2.count && zip(v1, v2).lazy.map(recur).reduce(true) { $0 && $1 } case let (.Keyed(d1), .Keyed(d2)): return Set(d1.keys) == Set(d2.keys) && d1.keys.map { recur(d1[$0]!, d2[$0]!) }.reduce(true) { $0 && $1 } default: From 3d8b7c183264ae4d4afecd2c277b2c30109799b1 Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 16:45:09 -0400 Subject: [PATCH 10/15] Remove JSONLeaf from doubt-swift target --- prototype/Doubt.xcodeproj/project.pbxproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 7493bf2b0..7c6aaaae0 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ D18FF8821BD0404700D18F2D /* Madness.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D18FF8811BD0404700D18F2D /* Madness.framework */; }; - D1A0934E1BD18969005A6326 /* JSONLeaf.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934C1BD188F5005A6326 /* JSONLeaf.swift */; }; D1F5FE201BDE891F0048BAE4 /* JSONParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F5FE1F1BDE891F0048BAE4 /* JSONParserTests.swift */; }; D1F5FE211BDE9C450048BAE4 /* JSONLeaf.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934C1BD188F5005A6326 /* JSONLeaf.swift */; }; D1F5FE221BDE9CC10048BAE4 /* JSONParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A0934A1BD188CA005A6326 /* JSONParser.swift */; }; @@ -420,7 +419,6 @@ buildActionMask = 2147483647; files = ( D4DF970A1BC5DF800040F41F /* main.swift in Sources */, - D1A0934E1BD18969005A6326 /* JSONLeaf.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 3a1c4a3b0ddcc1860a03226b2657163ccbd1a5a7 Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 26 Oct 2015 16:52:30 -0400 Subject: [PATCH 11/15] parse whitespace around separators --- prototype/Doubt/JSONParser.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index 44da2bef7..dcadbbf86 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -58,7 +58,7 @@ func members(json: JSONParser) -> MembersParser { Cofree(range, .Keyed(Dictionary(dictionaryLiteral: values))) } - return sepBy(pairs, %",") + return sepBy(pairs, whitespace <* %"," <* whitespace) } typealias ValuesParser = Parser.Function; @@ -66,7 +66,7 @@ typealias ValuesParser = Parser.Function; // Parses an array of CofreeJSON array values func elements(json: JSONParser) -> ValuesParser { let value: Parser.Function = whitespace *> json - return sepBy(value, %",") + return sepBy(value, whitespace <* %"," <* whitespace) } public let json: JSONParser = fix { json in From 57f15afc08f034d0ca18eb8e9fb5cf15c0a679c9 Mon Sep 17 00:00:00 2001 From: joshvera Date: Tue, 27 Oct 2015 11:18:52 -0400 Subject: [PATCH 12/15] Change dict to be a .Keyed(.Keyed) node --- prototype/Doubt/JSONParser.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index dcadbbf86..d823ef0b0 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -45,17 +45,18 @@ let charP: StringParser = escapeChar <|> otherChar let stringBody: StringParser = { $0.joinWithSeparator("") } <^> many(charP) let quoted = %"\"" *> stringBody <* %"\"" -typealias MembersParser = Parser.Function; +typealias MembersParser = Parser.Function; // Parses an array of (String, CofreeJSON) object members func members(json: JSONParser) -> MembersParser { - let pairs: Parser.Function = (curry(pair) <^> + let pairs: Parser.Function = (curry(pair) <^> quoted <* whitespace <* %":" <* whitespace - <*> json) --> { (_, range, values) in - Cofree(range, .Keyed(Dictionary(dictionaryLiteral: values))) + <*> json) --> { (_, range: Range, values: (String, CofreeJSON)) in + let dict = Dictionary(dictionaryLiteral: values) + return (values.0, Cofree(range, .Keyed(dict))) } return sepBy(pairs, whitespace <* %"," <* whitespace) @@ -90,8 +91,8 @@ public let json: JSONParser = fix { json in *> members(json) <* whitespace <* %"}" - --> { (_, range, values) in - Cofree(range, .Fixed(values)) + --> { (_, range, values: [(String, CofreeJSON)]) in + Cofree(range, .Keyed(Dictionary(elements: values))) } "object" let doubleParser: DoubleParser = number From 007a984c02ee7ad7f94666972faf1c5649d6141e Mon Sep 17 00:00:00 2001 From: joshvera Date: Tue, 27 Oct 2015 11:23:12 -0400 Subject: [PATCH 13/15] fix test --- prototype/DoubtTests/JSONParserTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/DoubtTests/JSONParserTests.swift b/prototype/DoubtTests/JSONParserTests.swift index e9fb78cb7..9945277ab 100644 --- a/prototype/DoubtTests/JSONParserTests.swift +++ b/prototype/DoubtTests/JSONParserTests.swift @@ -14,7 +14,7 @@ final class JSONParserTests: XCTestCase { let fixedPairs: Cofree> = Cofree(2..<41, .Keyed(["hello": array])) - let expected: Cofree> = Cofree(0..<42, .Fixed([fixedPairs])) + let expected: Cofree> = Cofree(0..<42, .Keyed(["hello": fixedPairs])) let actual = Madness.parse(json, input: dictWithArray).right! let firstIndex = actual.extract let new: Cofree> = actual.map({ range in From 96bcc25b2327d22c0b608eff749d8dd670e02ab7 Mon Sep 17 00:00:00 2001 From: joshvera Date: Tue, 27 Oct 2015 13:15:56 -0400 Subject: [PATCH 14/15] Calculate the key range from the previous range --- prototype/Doubt/JSONParser.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index d823ef0b0..46c77ea69 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -54,9 +54,12 @@ func members(json: JSONParser) -> MembersParser { <* whitespace <* %":" <* whitespace - <*> json) --> { (_, range: Range, values: (String, CofreeJSON)) in - let dict = Dictionary(dictionaryLiteral: values) - return (values.0, Cofree(range, .Keyed(dict))) + <*> json) --> { (_, range, values) in + let key = values.0 + let keyRange = Range(start: range.startIndex, end: range.startIndex.advancedBy(key.characters.count)) + let cofreeKey: CofreeJSON = Cofree(keyRange, .Leaf(.String(key))) + + return (key, Cofree(range, .Fixed([cofreeKey, values.1]))) } return sepBy(pairs, whitespace <* %"," <* whitespace) From 0718e49343b3f8d89ff35b4d6c7f6fa97f790949 Mon Sep 17 00:00:00 2001 From: joshvera Date: Tue, 27 Oct 2015 13:28:35 -0400 Subject: [PATCH 15/15] Capture the quoted range in members' keys --- prototype/Doubt/JSONParser.swift | 11 +++++------ prototype/DoubtTests/JSONParserTests.swift | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/prototype/Doubt/JSONParser.swift b/prototype/Doubt/JSONParser.swift index 46c77ea69..7208f076f 100644 --- a/prototype/Doubt/JSONParser.swift +++ b/prototype/Doubt/JSONParser.swift @@ -50,16 +50,15 @@ typealias MembersParser = Parser.Function; // Parses an array of (String, CofreeJSON) object members func members(json: JSONParser) -> MembersParser { let pairs: Parser.Function = (curry(pair) <^> - quoted + (quoted --> { (_, range, key) -> (String, CofreeJSON) in + return (key, Cofree(range, .Leaf(.String(key)))) + }) <* whitespace <* %":" <* whitespace <*> json) --> { (_, range, values) in - let key = values.0 - let keyRange = Range(start: range.startIndex, end: range.startIndex.advancedBy(key.characters.count)) - let cofreeKey: CofreeJSON = Cofree(keyRange, .Leaf(.String(key))) - - return (key, Cofree(range, .Fixed([cofreeKey, values.1]))) + let key = values.0.0 + return (key, Cofree(range, .Fixed([values.0.1, values.1]))) } return sepBy(pairs, whitespace <* %"," <* whitespace) diff --git a/prototype/DoubtTests/JSONParserTests.swift b/prototype/DoubtTests/JSONParserTests.swift index 9945277ab..84a5d4bc0 100644 --- a/prototype/DoubtTests/JSONParserTests.swift +++ b/prototype/DoubtTests/JSONParserTests.swift @@ -12,7 +12,7 @@ final class JSONParserTests: XCTestCase { Cofree(29..<37, .Leaf(.String("sailor"))) ])) - let fixedPairs: Cofree> = Cofree(2..<41, .Keyed(["hello": array])) + let fixedPairs: Cofree> = Cofree(2..<41, .Fixed([Cofree(2..<9, .Leaf(.String("hello"))), array])) let expected: Cofree> = Cofree(0..<42, .Keyed(["hello": fixedPairs])) let actual = Madness.parse(json, input: dictWithArray).right!