Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

Converted to Swift 2 and updated dependencies #13

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ build/
!default.perspectivev3
xcuserdata
*.xccheckout
*.xcscmblueprint
*.moved-aside
DerivedData
*.hmap
Expand Down
5 changes: 1 addition & 4 deletions Cartfile
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
github "robrix/Madness" "significant-indentation"
github "robrix/Either" ~> 1.1
github "robrix/Box" ~> 1.0.1
github "robrix/Prelude" ~> 1.4
github "robrix/Madness" "master"
4 changes: 2 additions & 2 deletions Cartfile.private
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
github "jspahrsummers/xcconfigs"
github "Quick/Quick" ~> 0.2.2
github "Quick/Nimble" ~> 0.2
github "Quick/Quick" ~> 0.8.0
github "Quick/Nimble" ~> 3.0.0
13 changes: 6 additions & 7 deletions Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
github "robrix/Box" "1.0.1"
github "robrix/Either" "1.1"
github "robrix/Madness" "b5e2882e924b2377da83adcdb59592ba7fdab52a"
github "Quick/Nimble" "v0.2.0"
github "robrix/Prelude" "1.4"
github "Quick/Quick" "v0.2.2"
github "jspahrsummers/xcconfigs" "0.7.1"
github "Quick/Nimble" "v3.0.0"
github "robrix/Prelude" "bd23a25d8c7c90a7a4b2505be65ad511c9d1db81"
github "Quick/Quick" "v0.8.0"
github "jspahrsummers/xcconfigs" "0.8.1"
github "robrix/Either" "1.3.1"
github "robrix/Madness" "d682f7854596dc01d1298446a8c49c8c70ffe5f8"
2 changes: 1 addition & 1 deletion Carthage/Checkouts/Madness
Submodule Madness updated 57 files
+8 −2 .gitmodules
+1 −0 Cartfile
+1 −0 Cartfile.private
+4 −0 Cartfile.resolved
+1 −0 Carthage/Checkouts/Assertions
+1 −0 Carthage/Checkouts/Either
+1 −0 Carthage/Checkouts/Prelude
+2 −2 Documentation/Collections.playground/contents.xcplayground
+3 −0 Documentation/Collections.playground/section-1.swift
+16 −0 Documentation/Collections.playground/section-2.swift
+0 −0 Documentation/Collections.playground/timeline.xctimeline
+8 −0 Documentation/Colours.playground/contents.xcplayground
+4 −0 Documentation/Colours.playground/section-1.swift
+22 −0 Documentation/Colours.playground/section-2.swift
+6 −0 Documentation/Colours.playground/timeline.xctimeline
+8 −0 Documentation/Lambda Calculus.playground/contents.xcplayground
+3 −0 Documentation/Lambda Calculus.playground/section-1.swift
+32 −0 Documentation/Lambda Calculus.playground/section-2.swift
+6 −0 Documentation/Lambda Calculus.playground/timeline.xctimeline
+0 −64 Documentation/Madness.playground/section-1.swift
+0 −12 Documentation/Madness.playground/timeline.xctimeline
+0 −2 Documentation/Significant Indentation.playground/section-2.swift
+1 −0 Documentation/Subset of Common Markdown.playground/contents.xcplayground
+0 −1 Documentation/Subset of Common Markdown.playground/section-1.swift
+66 −0 Documentation/Subset of Common Markdown.playground/section-2.swift
+40 −0 Documentation/Subset of Common Markdown.playground/timeline.xctimeline
+0 −1 External/Either
+372 −41 Madness.xcodeproj/project.pbxproj
+16 −13 Madness.xcodeproj/xcshareddata/xcschemes/Madness-Mac.xcscheme
+113 −0 Madness.xcodeproj/xcshareddata/xcschemes/Madness-iOS.xcscheme
+11 −5 Madness.xcworkspace/contents.xcworkspacedata
+37 −0 Madness.xcworkspace/xcshareddata/Madness.xcscmblueprint
+86 −0 Madness/Alternation.swift
+35 −0 Madness/Concatenation.swift
+90 −0 Madness/Error.swift
+1 −1 Madness/Info.plist
+81 −0 Madness/Map.swift
+103 −185 Madness/Parser.swift
+20 −0 Madness/Reduction.swift
+70 −0 Madness/Repetition.swift
+56 −0 Madness/SourcePos.swift
+74 −8 Madness/String.swift
+98 −0 MadnessTests/AlternationTests.swift
+0 −59 MadnessTests/Assertions.swift
+0 −69 MadnessTests/BindTests.swift
+27 −0 MadnessTests/CollectionTests.swift
+66 −0 MadnessTests/ConcatenationTests.swift
+35 −0 MadnessTests/ErrorTests.swift
+47 −0 MadnessTests/Fixtures.swift
+28 −0 MadnessTests/IgnoreTests.swift
+1 −1 MadnessTests/Info.plist
+111 −0 MadnessTests/MapTests.swift
+29 −223 MadnessTests/ParserTests.swift
+35 −0 MadnessTests/ReductionTests.swift
+201 −0 MadnessTests/RepetitionTests.swift
+61 −0 MadnessTests/StringTests.swift
+35 −13 README.md
2 changes: 1 addition & 1 deletion Carthage/Checkouts/Nimble
Submodule Nimble updated 107 files
2 changes: 1 addition & 1 deletion Carthage/Checkouts/Quick
Submodule Quick updated 75 files
+11 −0 .gitignore
+1 −0 .travis.yml
+24 −1 CONTRIBUTING.md
+220 −0 Documentation/ArrangeActAssert.md
+87 −0 Documentation/BehavioralTesting.md
+103 −0 Documentation/ConfiguringQuick.md
+28 −0 Documentation/InstallingFileTemplates.md
+177 −0 Documentation/InstallingQuick.md
+28 −0 Documentation/MoreResources.md
+106 −0 Documentation/NimbleAssertions.md
+488 −0 Documentation/QuickExamplesAndGroups.md
+53 −0 Documentation/QuickInObjectiveC.md
+42 −0 Documentation/README.md
+76 −0 Documentation/SettingUpYourXcodeProject.md
+125 −0 Documentation/SharedExamples.md
+179 −0 Documentation/TestingApps.md
+1 −1 Externals/Nimble
+6 −0 Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.h
+10 −0 Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.m
+8 −0 Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift
+ Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns
+73 −0 Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist
+14 −4 Quick.podspec
+545 −81 Quick.xcodeproj/project.pbxproj
+0 −1,348 Quick.xcodeproj/project.pbxproj.orig
+4 −1 Quick.xcodeproj/xcshareddata/xcschemes/Quick-OSX.xcscheme
+4 −1 Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme
+109 −0 Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme
+3 −3 Quick/Callsite.swift
+5 −5 Quick/Configuration/Configuration.swift
+1 −1 Quick/Configuration/QuickConfiguration.m
+47 −47 Quick/DSL/DSL.swift
+39 −16 Quick/DSL/QCKDSL.h
+13 −4 Quick/DSL/QCKDSL.m
+20 −0 Quick/DSL/World+DSL.h
+25 −23 Quick/DSL/World+DSL.swift
+7 −3 Quick/Example.swift
+12 −8 Quick/ExampleGroup.swift
+1 −1 Quick/ExampleMetadata.swift
+0 −16 Quick/Failure.swift
+3 −1 Quick/Filter.swift
+1 −1 Quick/Info.plist
+3 −5 Quick/Quick.h
+24 −7 Quick/QuickSpec.m
+17 −0 Quick/World.h
+16 −16 Quick/World.swift
+8 −8 QuickFocusedTests/FocusedTests+ObjC.m
+1 −1 QuickFocusedTests/Info.plist
+0 −25 QuickTests/ExampleMetadataFunctionalTests.swift
+1 −1 QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift
+0 −27 QuickTests/Fixtures/Person.swift
+0 −11 QuickTests/Fixtures/Poet.swift
+0 −65 QuickTests/FunctionalTests+ObjC.m
+0 −156 QuickTests/FunctionalTests.swift
+4 −4 QuickTests/FunctionalTests/AfterEachTests+ObjC.m
+42 −0 QuickTests/FunctionalTests/AfterSuiteTests+ObjC.m
+1 −1 QuickTests/FunctionalTests/AfterSuiteTests.swift
+4 −4 QuickTests/FunctionalTests/BeforeEachTests+ObjC.m
+6 −6 QuickTests/FunctionalTests/BeforeSuiteTests+ObjC.m
+1 −1 QuickTests/FunctionalTests/BeforeSuiteTests.swift
+15 −19 QuickTests/FunctionalTests/FailureTests+ObjC.m
+55 −0 QuickTests/FunctionalTests/FailureUsingXCTAssertTests+ObjC.m
+6 −8 QuickTests/FunctionalTests/ItTests+ObjC.m
+1 −1 QuickTests/FunctionalTests/ItTests.swift
+6 −6 QuickTests/FunctionalTests/PendingTests+ObjC.m
+59 −0 QuickTests/FunctionalTests/SharedExamples+BeforeEachTests+ObjC.m
+65 −0 QuickTests/FunctionalTests/SharedExamplesTests+ObjC.m
+0 −21 QuickTests/FunctionalTests/WorldExampleMetadataFunctionalTests.swift
+12 −4 QuickTests/Helpers/QCKSpecRunner.m
+1 −6 QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h
+1 −1 QuickTests/Info.plist
+25 −938 README.md
+1 −1 Rakefile
+18 −0 circle.yml
+199 −0 script/release
2 changes: 1 addition & 1 deletion Carthage/Checkouts/xcconfigs
5 changes: 1 addition & 4 deletions OGDL.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@
/* Begin PBXBuildFile section */
D00F9CDB1A5DC12500B4851E /* OGDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00F9CD01A5DC12500B4851E /* OGDL.framework */; };
D00F9CEA1A5DC1C900B4851E /* OGDL.h in Headers */ = {isa = PBXBuildFile; fileRef = D0BBBFC01A5DBF26007913DA /* OGDL.h */; settings = {ATTRIBUTES = (Public, ); }; };
D00F9CEF1A5DC45D00B4851E /* Box.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00F9CEB1A5DC45D00B4851E /* Box.framework */; };
D00F9CF01A5DC45D00B4851E /* Either.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00F9CEC1A5DC45D00B4851E /* Either.framework */; };
D00F9CF11A5DC45D00B4851E /* Madness.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00F9CED1A5DC45D00B4851E /* Madness.framework */; };
D00F9CF21A5DC45D00B4851E /* Prelude.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00F9CEE1A5DC45D00B4851E /* Prelude.framework */; };
D00F9CF31A5DC47500B4851E /* Box.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00F9CEB1A5DC45D00B4851E /* Box.framework */; };
D00F9CF41A5DC47500B4851E /* Either.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00F9CEC1A5DC45D00B4851E /* Either.framework */; };
D00F9CF51A5DC47500B4851E /* Madness.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00F9CED1A5DC45D00B4851E /* Madness.framework */; };
D00F9CF61A5DC47500B4851E /* Prelude.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00F9CEE1A5DC45D00B4851E /* Prelude.framework */; };
Expand Down Expand Up @@ -110,7 +108,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D00F9CEF1A5DC45D00B4851E /* Box.framework in Frameworks */,
D00F9CF01A5DC45D00B4851E /* Either.framework in Frameworks */,
D00F9CF11A5DC45D00B4851E /* Madness.framework in Frameworks */,
D00F9CF21A5DC45D00B4851E /* Prelude.framework in Frameworks */,
Expand All @@ -122,7 +119,6 @@
buildActionMask = 2147483647;
files = (
D0BBBFC71A5DBF26007913DA /* OGDL.framework in Frameworks */,
D00F9CF31A5DC47500B4851E /* Box.framework in Frameworks */,
D00F9CF41A5DC47500B4851E /* Either.framework in Frameworks */,
D00F9CFD1A5DC51300B4851E /* Nimble.framework in Frameworks */,
D00F9CF51A5DC47500B4851E /* Madness.framework in Frameworks */,
Expand Down Expand Up @@ -364,6 +360,7 @@
D0BBBFB21A5DBF26007913DA /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0710;
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = Carthage;
TargetAttributes = {
Expand Down
3 changes: 0 additions & 3 deletions OGDL.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions OGDL/Graph.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extension Node: Hashable {
}
}

extension Node: Printable {
extension Node: CustomStringConvertible {
public var description: String {
var string = ""
if value.rangeOfCharacterFromSet(NSCharacterSet.alphanumericCharacterSet().invertedSet) == nil {
Expand All @@ -47,8 +47,8 @@ extension Node: Printable {
}

if !children.isEmpty {
let childDescriptions = map(children) { $0.description }
string += " (" + join(", ", childDescriptions) + ")"
let childDescriptions = children.map { $0.description }
string += " (" + childDescriptions.joinWithSeparator(", ") + ")"
}

return string
Expand Down
151 changes: 78 additions & 73 deletions OGDL/Parser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,32 @@ import Madness
import Prelude

/// Returns a parser which parses one character from the given set.
internal prefix func % (characterSet: NSCharacterSet) -> Parser<String>.Function {
return { string in
let scalars = string.unicodeScalars

if let scalar = first(scalars) {
if characterSet.longCharacterIsMember(scalar.value) {
return (String(scalar), String(dropFirst(scalars)))
internal func memberOf(characterSet: NSCharacterSet) -> CharacterParser {
return { input, sourcePos in
if sourcePos.index != input.endIndex {
let character = input[sourcePos.index]
if let scalar = String(character).unicodeScalars.first where sourcePos.index != input.endIndex && characterSet.longCharacterIsMember(scalar.value) {
return .Right((character, updateIndex(sourcePos, sourcePos.index.successor())))
}
}

return nil
return .Left(.leaf("Character is not present in NSCharacterSet", sourcePos))
}
}

/// Removes the characters in the given string from the character set.
internal func - (characterSet: NSCharacterSet, characters: String) -> NSCharacterSet {
let mutableSet = characterSet.mutableCopy() as NSMutableCharacterSet
let mutableSet = characterSet.mutableCopy() as! NSMutableCharacterSet
mutableSet.removeCharactersInString(characters)
return mutableSet
}

/// Removes characters in the latter set from the former.
internal func - (characterSet: NSCharacterSet, subtrahend: NSCharacterSet) -> NSCharacterSet {
let mutableSet = characterSet.mutableCopy() as NSMutableCharacterSet
let mutableSet = characterSet.mutableCopy() as! NSMutableCharacterSet
mutableSet.formIntersectionWithCharacterSet(subtrahend.invertedSet)
return mutableSet
}

/// Optional matching operator.
postfix operator |? {}

/// Matches zero or one occurrence of the given parser.
internal postfix func |? <T>(parser: Parser<T>.Function) -> Parser<T?>.Function {
return (parser * (0..<2)) --> first
}

private let char_control = NSCharacterSet.controlCharacterSet()
private let char_text = char_control.invertedSet - NSCharacterSet.newlineCharacterSet()
private let char_word = char_text - ",()" - NSCharacterSet.whitespaceCharacterSet()
Expand All @@ -57,124 +47,139 @@ private let char_break = NSCharacterSet.newlineCharacterSet()
// TODO: Use this somewhere.
private let char_end = char_control - NSCharacterSet.whitespaceAndNewlineCharacterSet()

private let wordStart: Parser<String>.Function = %(char_word - "#'\"")
private let wordChars: Parser<String>.Function = (%(char_word - "'\""))* --> { strings in join("", strings) }
private let word: Parser<String>.Function = wordStart ++ wordChars --> (+)
private let br: Parser<()>.Function = ignore(%char_break)
private let eof: Parser<()>.Function = { $0 == "" ? ((), "") : nil }
private let comment: Parser<()>.Function = ignore(%"#" ++ (%char_text)+ ++ (br | eof))
private let wordStart = memberOf(char_word - "#'\"")
private let wordChars = many(memberOf(char_word - "'\""))
private let word = prepend <^> wordStart <*> wordChars
private let br = memberOf(char_break)
private let eof = %""

private let br_eof = br <|> eof
private let comment = char("#") *> some(memberOf(char_text)) <* br_eof

// Map helper functions
private func prepend<T>(value: T) -> [T] -> [T] {
return { [value] + $0 }
}

public func concat<T>(left: [T]) -> [T] -> [T] {
return { right in left + right }
}

public func pure<T>(value: T) -> [T] {
return [value]
}

public func flatten<T>(value: [[T]]) -> [T] {
return value.flatMap(id)
}

// TODO: Escape sequences.
private let singleQuotedChars: Parser<String>.Function = (%(char_text - "'"))* --> { strings in join("", strings) }
private let singleQuoted: Parser<String>.Function = ignore(%"'") ++ singleQuotedChars ++ ignore(%"'")
private let doubleQuotedChars: Parser<String>.Function = (%(char_text - "\""))* --> { strings in join("", strings) }
private let doubleQuoted: Parser<String>.Function = ignore(%"\"") ++ doubleQuotedChars ++ ignore(%"\"")
private let quoted: Parser<String>.Function = singleQuoted | doubleQuoted
private let requiredSpace: Parser<()>.Function = ignore((comment | %char_space)+)
private let optionalSpace: Parser<()>.Function = ignore((comment | %char_space)*)
private let separator: Parser<()>.Function = ignore(optionalSpace ++ %"," ++ optionalSpace)
private let singleQuotedChars = many(memberOf(char_text - "'"))
private let singleQuoted = char("'") *> singleQuotedChars <* char("'")
private let doubleQuotedChars = many(memberOf(char_text - "\""))
private let doubleQuoted = char("\"") *> doubleQuotedChars <* char("\"")
private let quoted = singleQuoted <|> doubleQuoted
private let requiredSpace = some(comment <|> memberOf(char_space))
private let optionalSpace = many(comment <|> memberOf(char_space))
private let separator = optionalSpace *> char(",") <* optionalSpace

private let value: Parser<String>.Function = word | quoted
private let value = String.init <^> (word <|> quoted)

/// A function taking an Int and returning a parser which parses at least that many
/// indentation characters.
func indentation(n: Int) -> Parser<Int>.Function {
return (%char_space * (n..<Int.max)) --> { $0.count }
func indentation(n: Int) -> Parser<String.CharacterView, Int>.Function {
return { $0.count } <^> (memberOf(char_space) * (n..<Int.max))
}

// MARK: Generic combinators
// FIXME: move these into Madness.

/// Delays the evaluation of a parser so that it can be used in a recursive grammar without deadlocking Swift at runtime.
private func lazy<T>(parser: () -> Parser<T>.Function) -> Parser<T>.Function {
return { parser()($0) }
}

/// Returns a parser which produces an array of parse trees produced by `parser` interleaved with ignored parses of `separator`.
///
/// This is convenient for e.g. comma-separated lists.
private func interleave<T, U>(separator: Parser<U>.Function, parser: Parser<T>.Function) -> Parser<[T]>.Function {
return (parser ++ (ignore(separator) ++ parser)*) --> { [$0] + $1 }
private func interleave<C: CollectionType, T, U>(separator: Parser<C, U>.Function, _ parser: Parser<C, T>.Function) -> Parser<C, [T]>.Function {
return prepend <^> parser <*> many(separator *> parser)
}

private func foldr<S: SequenceType, Result>(sequence: S, initial: Result, combine: (S.Generator.Element, Result) -> Result) -> Result {
var generator = sequence.generate()
return foldr(&generator, initial, combine)
return foldr(&generator, initial: initial, combine: combine)
}

private func foldr<G: GeneratorType, Result>(inout generator: G, initial: Result, combine: (G.Element, Result) -> Result) -> Result {
return generator.next().map { combine($0, foldr(&generator, initial, combine)) } ?? initial
return generator.next().map { combine($0, foldr(&generator, initial: initial, combine: combine)) } ?? initial
}

private func | <T, U> (left: Parser<T>.Function, right: String -> U) -> Parser<Either<T, U>>.Function {
return left | { (right($0), $0) }
}

private func | <T> (left: Parser<T>.Function, right: String -> T) -> Parser<T>.Function {
return left | { (right($0), $0) }
}

private func flatMap<T, U>(x: [T], f: T -> [U]) -> [U] {
return reduce(lazy(x).map(f), [], +)
private func ?? <C: CollectionType, T>(parser: Parser<C, T>.Function, @autoclosure(escaping) right: () -> T) -> Parser<C, T>.Function {
return { $0 ?? right() } <^> parser|?
}

// MARK: OGDL

private let children: Parser<[Node]>.Function = lazy { group | (element --> { elem in [ elem ] }) }
private let children: Parser<String.CharacterView, [Node]>.Function = delay { group <|> (pure <^> element) }

private let element = lazy { value ++ (optionalSpace ++ children)|? --> { value, children in Node(value: value, children: children ?? []) } }
private let element = delay {
curry(Node.init)
<^> value
<*> (optionalSpace *> children) ?? []
}

// TODO: See Carthage/ogdl-swift#3.
private let block: Int -> Parser<()>.Function = { n in const(nil) }
//private let block: Int -> StringParser = { _ in %"" }

/// Parses a single descendent element.
///
/// This is an element which may be an in-line descendent, and which may further have in-line descendents of its own.
private let descendent = value --> { Node(value: $0) }
private let descendent = value |> map { Node(value: $0) }

/// Parses a sequence of hierarchically descending elements, e.g.:
///
/// x y z # => Node(x, [Node(y, Node(z))])
public let descendents: Parser<Node>.Function = interleave(requiredSpace, descendent) --> {
foldr(dropLast($0), last($0)!) { $0.nodeByAppendingChildren([ $1 ]) }
}
public let descendents = interleave(requiredSpace, descendent)
|> map { foldr($0.dropLast(), initial: $0.last!) { $0.nodeByAppendingChildren([ $1 ]) } }

/// Parses a chain of descendents, optionally ending in a group.
///
/// x y (u, v) # => Node(x, [ Node(y, [ Node(u), Node(v) ]) ])
private let descendentChain: Parser<Node>.Function = (descendents ++ ((optionalSpace ++ group) | const([]))) --> uncurry(Node.nodeByAppendingChildren)
private let descendentChain: Parser<String.CharacterView, Node>.Function =
Node.nodeByAppendingChildren
<^> descendents
<*> (optionalSpace *> group) ?? []

/// Parses a sequence of adjacent sibling elements, e.g.:
///
/// x, y z, w (u, v) # => [ Node(x), Node(y, Node(z)), Node(w, [ Node(u), Node(v) ]) ]
public let adjacent: Parser<[Node]>.Function = lazy { interleave(separator, descendentChain) }
public let adjacent = delay { interleave(separator, descendentChain) }

/// Parses a parenthesized sequence of sibling elements, e.g.:
///
/// (x, y z, w) # => [ Node(x), Node(y, Node(z)), Node(w) ]
private let group = lazy { ignore(%"(") ++ optionalSpace ++ adjacent ++ optionalSpace ++ ignore(%")") }
private let group = delay { char("(") *> optionalSpace *> adjacent <* optionalSpace <* char(")") }

private let subgraph: Int -> Parser<[Node]>.Function = { n in
(descendents ++ lines(n + 1) --> { [ $0.nodeByAppendingChildren($1) ] }) | adjacent
private let subgraph: Int -> Parser<String.CharacterView, [Node]>.Function = { n in
pure <^> (Node.nodeByAppendingChildren <^> descendents <*> lines(n + 1)) <|> adjacent
}

private let line: Int -> Parser<[Node]>.Function = fix { line in
private let line: Int -> Parser<String.CharacterView, [Node]>.Function = fix { line in
{ n in
// TODO: block parsing: ignore(%char_space+ ++ block(n))|?) ++
// See Carthage/ogdl-swift#3.
indentation(n) >>- { n in
subgraph(n) ++ optionalSpace
subgraph(n) <* optionalSpace
}
}
}

private let followingLine: Int -> Parser<[Node]>.Function = { n in (ignore(comment | br)+ ++ line(n)) }
private let lines: Int -> Parser<[Node]>.Function = { n in
(line(n)|? ++ followingLine(n)*) --> { ($0 ?? []) + flatMap($1, id) }
private let followingLine: Int -> Parser<String.CharacterView, [Node]>.Function = { n in some(comment <|> br) *> line(n) }
private let lines: Int -> Parser<String.CharacterView, [Node]>.Function = { n in
concat
<^> line(n) ?? []
<*> (flatten <^> many(followingLine(n)))
}

/// Parses a textual OGDL graph into a list of nodes (and their descendants).
///
/// Example:
///
/// let nodes = parse(graph, "foo (bar, buzz baz)")
public let graph: Parser<[Node]>.Function = ignore(comment | br)* ++ (lines(0) | adjacent) ++ ignore(comment | br)*
public let graph: Parser<String.CharacterView, [Node]>.Function = many(comment <|> br) *> (lines(0) <|> adjacent) <* many(comment <|> br)
Loading