Repository: robrix/Madness
Branch: master
Commit: add3ee4bf05d
Files: 49
Total size: 112.8 KB
Directory structure:
gitextract_t4_kha8o/
├── .gitignore
├── .gitmodules
├── .travis.yml
├── Cartfile
├── Cartfile.resolved
├── Documentation/
│ ├── Collections.playground/
│ │ ├── Contents.swift
│ │ └── contents.xcplayground
│ ├── Colours.playground/
│ │ ├── Contents.swift
│ │ └── contents.xcplayground
│ ├── Lambda Calculus.playground/
│ │ ├── Contents.swift
│ │ └── contents.xcplayground
│ └── Subset of Common Markdown.playground/
│ ├── Contents.swift
│ └── contents.xcplayground
├── LICENSE
├── Madness/
│ ├── Alternation.swift
│ ├── Combinator.swift
│ ├── Concatenation.swift
│ ├── Error.swift
│ ├── Info.plist
│ ├── Madness.h
│ ├── Map.swift
│ ├── Negation.swift
│ ├── Parser.swift
│ ├── Reduction.swift
│ ├── Repetition.swift
│ ├── SourcePos.swift
│ └── String.swift
├── Madness.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── xcshareddata/
│ └── xcschemes/
│ ├── Madness-Mac.xcscheme
│ └── Madness-iOS.xcscheme
├── Madness.xcworkspace/
│ └── contents.xcworkspacedata
├── MadnessTests/
│ ├── AlternationTests.swift
│ ├── CollectionTests.swift
│ ├── CombinatorTests.swift
│ ├── ConcatenationTests.swift
│ ├── ErrorTests.swift
│ ├── Fixtures.swift
│ ├── IgnoreTests.swift
│ ├── Info.plist
│ ├── MapTests.swift
│ ├── NegationTests.swift
│ ├── ParserTests.swift
│ ├── ReductionTests.swift
│ ├── RepetitionTests.swift
│ └── StringTests.swift
├── README.md
└── script/
├── cibuild
└── validate-playground.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
build
xcuserdata
*.mode*
*.pbxuser
*.xcuserdatad
*.xccheckout
*.xcscmblueprint
*.xctimeline
================================================
FILE: .gitmodules
================================================
[submodule "Carthage/Checkouts/Result"]
path = Carthage/Checkouts/Result
url = https://github.com/antitypical/Result.git
================================================
FILE: .travis.yml
================================================
language: objective-c
osx_image: xcode9
branches:
only:
- master
xcode_workspace: Madness.xcworkspace
script:
- script/cibuild
matrix:
include:
- xcode_scheme: Madness-Mac
env:
- XCODE_SDK=macosx
- XCODE_ACTION="build test"
- XCODE_DESTINATION="arch=x86_64"
- xcode_scheme: Madness-Mac
env:
- XCODE_SDK=macosx
- XCODE_ACTION="build"
- XCODE_DESTINATION="arch=x86_64"
- XCODE_PLAYGROUND="Documentation/Collections.playground"
- JOB=Collections.playground
- xcode_scheme: Madness-Mac
env:
- XCODE_SDK=macosx
- XCODE_ACTION="build"
- XCODE_DESTINATION="arch=x86_64"
- XCODE_PLAYGROUND="Documentation/Colours.playground"
- JOB=Colours.playground
- xcode_scheme: Madness-Mac
env:
- XCODE_SDK=macosx
- XCODE_ACTION="build"
- XCODE_DESTINATION="arch=x86_64"
- XCODE_PLAYGROUND="Documentation/Lambda Calculus.playground"
- JOB=Lambda Calculus.playground
- xcode_scheme: Madness-Mac
env:
- XCODE_SDK=macosx
- XCODE_ACTION="build"
- XCODE_DESTINATION="arch=x86_64"
- XCODE_PLAYGROUND="Documentation/Subset of Common Markdown.playground"
- JOB=Subset of Common Markdown.playground
- xcode_scheme: Madness-iOS
env:
- XCODE_SDK=iphonesimulator
- XCODE_ACTION="build-for-testing test-without-building"
- XCODE_DESTINATION="platform=iOS Simulator,name=iPhone X"
notifications:
email: false
================================================
FILE: Cartfile
================================================
github "antitypical/Result" ~> 3.2.4
================================================
FILE: Cartfile.resolved
================================================
github "antitypical/Result" "3.2.4"
================================================
FILE: Documentation/Collections.playground/Contents.swift
================================================
import Madness
import Result
let input = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
typealias Fibonacci = Parser<[Int], [Int]>.Function
func fibonacci(_ x: Int, _ y: Int) -> Fibonacci {
let combined: Fibonacci = %(x + y) >>- { (xy: Int) -> Fibonacci in
{ [ xy ] + $0 } <^> fibonacci(y, xy)
}
return combined <|> pure([])
}
parse(fibonacci(0, 1), input: input).value
================================================
FILE: Documentation/Collections.playground/contents.xcplayground
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='3.0' sdk='macosx' auto-termination-delay='5'>
<sections>
<code source-file-name='section-1.swift'/>
<code source-file-name='section-2.swift'/>
</sections>
<timeline fileName='timeline.xctimeline'/>
</playground>
================================================
FILE: Documentation/Colours.playground/Contents.swift
================================================
import Cocoa
import Darwin
import Madness
func toComponent(_ string: String) -> CGFloat {
return CGFloat(strtol(string, nil, 16)) / 255
}
let digit = %("0"..."9")
let lower = %("a"..."f")
let upper = %("A"..."F")
let hex = digit <|> lower <|> upper
let hex2 = lift(+) <*> hex <*> hex
let component1: Parser<String.CharacterView, CGFloat>.Function = { toComponent($0 + $0) } <^> hex
let component2: Parser<String.CharacterView, CGFloat>.Function = toComponent <^> hex2
let three: Parser<String.CharacterView, [CGFloat]>.Function = component1 * 3
let six: Parser<String.CharacterView, [CGFloat]>.Function = component2 * 3
let colour: Parser<String.CharacterView, NSColor>.Function = map({
NSColor(calibratedRed: $0[0], green: $0[1], blue: $0[2], alpha: 1)
})(%"#" *> (six <|> three))
let reddish = parse(colour, input: "#d52a41").value
let greenish = parse(colour, input: "#5a2").value
let blueish = parse(colour, input: "#5e8ca1").value
================================================
FILE: Documentation/Colours.playground/contents.xcplayground
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' sdk='macosx' auto-termination-delay='4'>
<timeline fileName='timeline.xctimeline'/>
</playground>
================================================
FILE: Documentation/Lambda Calculus.playground/Contents.swift
================================================
import Madness
indirect enum Lambda: CustomStringConvertible {
case variable(String)
case abstraction(String, Lambda)
case application(Lambda, Lambda)
var description: String {
switch self {
case let .variable(symbol):
return symbol
case let .abstraction(symbol, body):
return "λ\(symbol).\(body.description)"
case let .application(x, y):
return "(\(x.description) \(y.description))"
}
}
}
typealias LambdaParser = Parser<String.CharacterView, Lambda>
func lambda(_ input: String.CharacterView, sourcePos: SourcePos<String.CharacterView.Index>) -> LambdaParser.Result {
let symbol: StringParser = %("a"..."z")
let variable: LambdaParser.Function = Lambda.variable <^> symbol
let abstraction: LambdaParser.Function = Lambda.abstraction <^> ( lift(pair) <*> (%"λ" *> symbol) <*> (%"." *> lambda) )
let application: LambdaParser.Function = Lambda.application <^> ( lift(pair) <*> (%"(" *> lambda) <*> (%" " *> lambda) <* %")" )
let parser: LambdaParser.Function = variable <|> abstraction <|> application
return parser(input, sourcePos)
}
parse(lambda, input: "λx.(x x)".characters).value?.description
parse(lambda, input: "(λx.(x x) λx.(x x))".characters).value?.description
================================================
FILE: Documentation/Lambda Calculus.playground/contents.xcplayground
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='3.0' sdk='macosx' auto-termination-delay='5'>
<sections>
<code source-file-name='section-1.swift'/>
<code source-file-name='section-2.swift'/>
</sections>
<timeline fileName='timeline.xctimeline'/>
</playground>
================================================
FILE: Documentation/Subset of Common Markdown.playground/Contents.swift
================================================
import Madness
// MARK: - Lexing rules
let newline = %"\n"
let ws = %" " <|> %"\t"
let lower = %("a"..."z")
let upper = %("A"..."Z")
let digit = %("0"..."9")
let text = lower <|> upper <|> digit <|> ws
let restOfLine = { $0.joined(separator: "") } <^> many(text) <* newline
let texts = { $0.joined(separator: "") } <^> some(text <|> (%"" <* newline))
// MARK: - AST
enum Node: CustomStringConvertible {
case blockquote([Node])
case header(Int, String)
case paragraph(String)
func analysis<T>(ifBlockquote: ([Node]) -> T, ifHeader: (Int, String) -> T, ifParagraph: (String) -> T) -> T {
switch self {
case let .blockquote(nodes):
return ifBlockquote(nodes)
case let .header(level, text):
return ifHeader(level, text)
case let .paragraph(text):
return ifParagraph(text)
}
}
// MARK: Printable
var description: String {
return analysis(
ifBlockquote: { "<blockquote>" + $0.lazy.map{ $0.description }.joined(separator: "") + "</blockquote>" },
ifHeader: { "<h\($0)>\($1)</h\($0)>" },
ifParagraph: { "<p>\($0)</p>" })
}
}
// MARK: - Parsing rules
typealias NodeParser = Parser<String.CharacterView, Node>.Function
typealias ElementParser = (@escaping StringParser) -> NodeParser
func fix<T, U>(_ f: @escaping (@escaping (T) -> U) -> (T) -> U) -> (T) -> U {
return { f(fix(f))($0) }
}
let element: ElementParser = fix { element in
{ prefix in
let octothorpes: IntParser = { $0.count } <^> (%"#" * (1..<7))
let header: NodeParser = prefix *> ( Node.header <^> (lift(pair) <*> octothorpes <*> (%" " *> restOfLine)) )
let paragraph: NodeParser = prefix *> ( Node.paragraph <^> texts )
let blockquote: NodeParser = prefix *> { ( Node.blockquote <^> some(element(prefix *> %"> ")) )($0, $1) }
return header <|> paragraph <|> blockquote
}
}
let parser = many(element(pure("")))
if let parsed = parse(parser, input: "> # hello\n> \n> hello\n> there\n> \n> \n").value {
let description = parsed.reduce(""){ $0 + $1.description }
print(description)
}
if let parsed = parse(parser, input: "This is a \nparagraph\n> # title\n> ### subtitle\n> a").value {
let description = parsed.reduce(""){ $0 + $1.description }
print(description)
}
================================================
FILE: Documentation/Subset of Common Markdown.playground/contents.xcplayground
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='3.0' sdk='macosx'>
<sections>
<code source-file-name='section-1.swift'/>
<code source-file-name='section-2.swift'/>
</sections>
<timeline fileName='timeline.xctimeline'/>
</playground>
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 Rob Rix
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Madness/Alternation.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
/// Parses `parser` 0 or one time.
public postfix func |? <C: Collection, T> (parser: @escaping Parser<C, T>.Function) -> Parser<C, T?>.Function {
return { $0.first } <^> parser * (0...1)
}
/// Parses either `left` or `right` and coalesces their trees.
public func <|> <C: Collection, T> (left: @escaping Parser<C, T>.Function, right: @escaping Parser<C, T>.Function) -> Parser<C, T>.Function {
return alternate(left, right)
}
// MARK: - n-ary alternation
/// Alternates over a sequence of literals, coalescing their parse trees.
public func oneOf<C: Collection, S: Sequence>(_ input: S) -> Parser<C, C.Element>.Function where C.Element: Equatable, S.Element == C.Element {
return satisfy(input.contains)
}
/// Given a set of literals, parses an array of any matches in the order they were found.
///
/// Each literal will only match the first time.
public func anyOf<C: Collection>(_ set: Set<C.Element>) -> Parser<C, [C.Element]>.Function {
return oneOf(set) >>- { match in
var rest = set
rest.remove(match)
return prepend(match) <^> anyOf(rest) <|> pure([match])
}
}
/// Given a set of literals, parses an array of all matches in the order they were found.
///
/// Each literal will be matched as many times as it is found.
public func allOf<C: Collection>(_ input: Set<C.Element>) -> Parser<C, [C.Element]>.Function {
return oneOf(input) >>- { match in
prepend(match) <^> allOf(input) <|> pure([match])
}
}
// MARK: - Private
/// Defines alternation for use in the `<|>` operator definitions above.
private func alternate<C: Collection, T>(_ left: @escaping Parser<C, T>.Function, _ right: @escaping Parser<C, T>.Function) -> Parser<C, T>.Function {
return { input, sourcePos in
return left(input, sourcePos)
.flatMapError { left in
return right(input, sourcePos)
.mapError { right in
return Error.withReason("no alternative matched:", sourcePos)(left, right)
}
}
}
}
/// Curried function that prepends a value to an array.
func prepend<T>(_ value: T) -> ([T]) -> [T] {
return { [value] + $0 }
}
// MARK: - Operators
/// Optional alternation operator.
postfix operator |?
precedencegroup AlternationPrecedence {
associativity: left
higherThan: ChainingPrecedence
lowerThan: MultiplicationPrecedence
}
infix operator <|> : AlternationPrecedence
// MARK: - Imports
import Result
================================================
FILE: Madness/Combinator.swift
================================================
// Copyright © 2015 Rob Rix. All rights reserved.
/// Parses `open`, followed by `parser` and `close`. Returns the value returned by `parser`.
public func between<C: Collection, T, U, V>(_ open: @escaping Parser<C, T>.Function, _ close: @escaping Parser<C, U>.Function) -> (@escaping Parser<C, V>.Function) -> Parser<C, V>.Function {
return { open *> $0 <* close }
}
/// Parses 0 or more `parser` until `end`. Returns the list of values returned by `parser`.
public func manyTill<C: Collection, T, U>(_ parser: @escaping Parser<C, T>.Function, _ end: @escaping Parser<C, U>.Function) -> Parser<C, [T]>.Function {
return many(parser) <* end
}
================================================
FILE: Madness/Concatenation.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
import Result
precedencegroup ConcatenationPrecedence {
associativity: left
higherThan: AlternationPrecedence
lowerThan: MultiplicationPrecedence
}
/// Parses the concatenation of `left` and `right`, pairing their parse trees.
public func <*> <C: Collection, T, U> (left: @escaping Parser<C, (T) -> U>.Function, right: @escaping Parser<C, T>.Function) -> Parser<C, U>.Function {
return left >>- { $0 <^> right }
}
/// Parses the concatenation of `left` and `right`, dropping `right`’s parse tree.
public func <* <C: Collection, T, U> (left: @escaping Parser<C, T>.Function, right: @escaping Parser<C, U>.Function) -> Parser<C, T>.Function {
return left >>- { x in { _ in x } <^> right }
}
/// Parses the concatenation of `left` and `right`, dropping `left`’s parse tree.
public func *> <C: Collection, T, U> (left: @escaping Parser<C, T>.Function, right: @escaping Parser<C, U>.Function) -> Parser<C, U>.Function {
return left >>- { _ in right }
}
infix operator <*> : ConcatenationPrecedence
infix operator *> : ConcatenationPrecedence
infix operator <* : ConcatenationPrecedence
================================================
FILE: Madness/Error.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
import Result
/// A composite error.
public enum Error<I: Comparable>: Swift.Error, CustomStringConvertible {
indirect case branch(String, SourcePos<I>, [Error])
/// Constructs a leaf error, e.g. for terminal parsers.
public static func leaf(_ reason: String, _ sourcePos: SourcePos<I>) -> Error {
return .branch(reason, sourcePos, [])
}
public static func withReason(_ reason: String, _ sourcePos: SourcePos<I>) -> (Error, Error) -> Error {
return { Error(reason: reason, sourcePos: sourcePos, children: [$0, $1]) }
}
public init(reason: String, sourcePos: SourcePos<I>, children: [Error]) {
self = .branch(reason, sourcePos, children)
}
public var reason: String {
switch self {
case let .branch(s, _, _):
return s
}
}
public var sourcePos: SourcePos<I> {
switch self {
case let .branch(_, sourcePos, _):
return sourcePos
}
}
public var children: [Error] {
switch self {
case let .branch(_, _, c):
return c
}
}
public var depth: Int {
return 1 + ((children.sorted { $0.depth < $1.depth }).last?.depth ?? 0)
}
// MARK: Printable
public var description: String {
return describe(0)
}
fileprivate func describe(_ n: Int) -> String {
let description = String(repeating: "\t", count: n) + "\(sourcePos.index): \(reason)"
if children.count > 0 {
return description + "\n" + children.lazy.map { $0.describe(n + 1) }.joined(separator: "\n")
}
return description
}
}
/// MARK: - Annotations
/// Annotate a parser with a name.
public func <?> <C: Collection, T>(parser: @escaping Parser<C, T>.Function, name: String) -> Parser<C, T>.Function {
return describeAs(name)(parser)
}
/// Adds a name to parse errors.
public func describeAs<C: Collection, T>(_ name: String) -> (@escaping Parser<C, T>.Function) -> Parser<C, T>.Function {
return { parser in
{ input, index in
return parser(input, index).mapError {
Error(reason: "\(name): \($0.reason)", sourcePos: $0.sourcePos, children: $0.children)
}
}
}
}
// MARK: - Operators
precedencegroup AnnotationPrecedence {
associativity: left
lowerThan: ChainingPrecedence
}
infix operator <?> : AnnotationPrecedence
================================================
FILE: Madness/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.0.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 Rob Rix. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
================================================
FILE: Madness/Madness.h
================================================
// Copyright (c) 2014 Rob Rix. All rights reserved.
/// Project version number for Madness.
extern double MadnessVersionNumber;
/// Project version string for Madness.
extern const unsigned char MadnessVersionString[];
================================================
FILE: Madness/Map.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
// MARK: - flatMap
/// Returns a parser which requires `parser` to parse, passes its parsed trees to a function `f`, and then requires the result of `f` to parse.
///
/// This can be used to conveniently make a parser which depends on earlier parsed input, for example to parse exactly the same number of characters, or to parse structurally significant indentation.
public func >>- <C: Collection, T, U> (parser: @escaping Parser<C, T>.Function, f: @escaping (T) -> Parser<C, U>.Function) -> Parser<C, U>.Function {
return { input, index in parser(input, index).flatMap { f($0)(input, $1) } }
}
// MARK: - map
/// Returns a parser which applies `f` to transform the output of `parser`.
public func <^> <C: Collection, T, U> (f: @escaping (T) -> U, parser: @escaping Parser<C, T>.Function) -> Parser<C, U>.Function {
return parser >>- { pure(f($0)) }
}
/// Returns a parser which first parses `right`, replacing successful parses with `left`.
public func <^ <C: Collection, T, U> (left: T, right: @escaping Parser<C, U>.Function) -> Parser<C, T>.Function {
return { (_: U) -> T in left } <^> right
}
/// Curried `<^>`. Returns a parser which applies `f` to transform the output of `parser`.
public func map<C: Collection, T, U>(_ f: @escaping (T) -> U) -> (@escaping Parser<C, T>.Function) -> Parser<C, U>.Function {
return { f <^> $0 }
}
// MARK: - pure
/// Returns a parser which always ignores its input and produces a constant value.
///
/// When combining parsers with `>>-`, allows constant values to be injected into the parser chain.
public func pure<C: Collection, T>(_ value: T) -> Parser<C, T>.Function {
return { _, index in .success((value, index)) }
}
// MARK: - lift
public func lift<C: Collection, T, U, V>(_ f: @escaping (T, U) -> V) -> Parser<C, (T) -> (U) -> V>.Function {
return pure({ t in { u in f(t, u) } })
}
public func lift<C: Collection, T, U, V, W>(_ f: @escaping (T, U, V) -> W) -> Parser<C, (T) -> (U) -> (V) -> W>.Function {
return pure({ t in { u in { v in f(t, u, v) } } })
}
// MARK: - pair
public func pair<A, B>(_ a: A, b: B) -> (A, B) {
return (a, b)
}
// MARK: - Operators
/// Flat map operator.
infix operator >>- : ChainingPrecedence
/// Map operator.
infix operator <^> : ConcatenationPrecedence
/// Replace operator.
infix operator <^ : ConcatenationPrecedence
import Result
================================================
FILE: Madness/Negation.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
/// This parser succeeds iff `parser` fails. This parser does not consume any input.
public func not<C: Collection, T> (_ parser: @escaping Parser<C, T>.Function) -> Parser<C, ()>.Function {
return { input, index in
return parser(input, index).analysis(
ifSuccess: { (_, endIndex) in
Result.failure(Error.leaf("failed negative lookahead ending at \(endIndex)", index))
},
ifFailure: { _ in Result.success(((), index)) }
)
}
}
// MARK: - Imports
import Result
================================================
FILE: Madness/Parser.swift
================================================
// Copyright (c) 2014 Rob Rix. All rights reserved.
// Swift has no way to resolve to `Result.Result` inside `Parser.Result`.
public typealias ParserResult<C: Collection, Tree> = Result<(Tree, SourcePos<C.Index>), Error<C.Index>>
/// Convenience for describing the types of parser combinators.
///
/// \param Tree The type of parse tree generated by the parser.
public enum Parser<C: Collection, Tree> {
/// The type of parser combinators.
public typealias Function = (C, SourcePos<C.Index>) -> Result
/// The type produced by parser combinators.
public typealias Result = ParserResult<C, Tree>
}
/// Parses `input` with `parser`, returning the parse trees or `nil` if nothing could be parsed, or if parsing did not consume the entire input.
public func parse<C: Collection, Tree>(_ parser: Parser<C, Tree>.Function, input: C) -> Result<Tree, Error<C.Index>> {
let result = parser(input, SourcePos(index: input.startIndex))
return result.flatMap { tree, sourcePos in
return sourcePos.index == input.endIndex
? .success(tree)
: .failure(.leaf("finished parsing before end of input", sourcePos))
}
}
public func parse<Tree>(_ parser: Parser<String.CharacterView, Tree>.Function, input: String) -> Result<Tree, Error<String.Index>> {
return parse(parser, input: input.characters)
}
// MARK: - Terminals
/// Returns a parser which never parses its input.
public func none<C: Collection, Tree>(_ string: String = "no way forward") -> Parser<C, Tree>.Function {
return { _, sourcePos in .failure(.leaf(string, sourcePos)) }
}
// Returns a parser which parses any single character.
public func any<C: Collection>(_ input: C, sourcePos: SourcePos<C.Index>) -> Parser<C, C.Element>.Result {
return satisfy { _ in true }(input, sourcePos)
}
public func any(_ input: String.CharacterView, sourcePos: SourcePos<String.Index>) -> Parser<String.CharacterView, Character>.Result {
return satisfy { _ in true }(input, sourcePos)
}
/// Returns a parser which parses a `literal` sequence of elements from the input.
///
/// This overload enables e.g. `%"xyz"` to produce `String -> (String, String)`.
public prefix func % <C: Collection> (literal: C) -> Parser<C, C>.Function where C.Element: Equatable {
return { input, sourcePos in
if input[sourcePos.index...].starts(with: literal) {
return .success((literal, sourcePos.advanced(by: literal.count, from: input)))
} else {
return .failure(.leaf("expected \(literal)", sourcePos))
}
}
}
public prefix func %(literal: String) -> Parser<String.CharacterView, String>.Function {
return { input, sourcePos in
if input[sourcePos.index...].starts(with: literal.characters) {
return .success((literal, sourcePos.advanced(by: literal, from: input)))
} else {
return .failure(.leaf("expected \(literal)", sourcePos))
}
}
}
/// Returns a parser which parses a `literal` element from the input.
public prefix func % <C: Collection> (literal: C.Element) -> Parser<C, C.Element>.Function where C.Element: Equatable {
return { input, sourcePos in
if sourcePos.index != input.endIndex && input[sourcePos.index] == literal {
return .success((literal, sourcePos.advanced(by: 1, from: input)))
} else {
return .failure(.leaf("expected \(literal)", sourcePos))
}
}
}
/// Returns a parser which parses any character in `range`.
public prefix func %(range: ClosedRange<Character>) -> Parser<String.CharacterView, String>.Function {
return { (input: String.CharacterView, sourcePos: SourcePos<String.Index>) in
let index = sourcePos.index
if index < input.endIndex && range.contains(input[index]) {
let string = String(input[index])
return .success((string, sourcePos.advanced(by: 1, from: input)))
} else {
return .failure(.leaf("expected an element in range \(range)", sourcePos))
}
}
}
// MARK: - Nonterminals
private func memoize<T>(_ f: @escaping () -> T) -> () -> T {
var memoized: T!
return {
if memoized == nil {
memoized = f()
}
return memoized
}
}
public func delay<C: Collection, T>(_ parser: @escaping () -> Parser<C, T>.Function) -> Parser<C, T>.Function {
let memoized = memoize(parser)
return { memoized()($0, $1) }
}
// Returns a parser that satisfies the given predicate
public func satisfy(_ pred: @escaping (Character) -> Bool) -> Parser<String.CharacterView, Character>.Function {
return tokenPrim(pred) { $0.advanced(by: $1, from: $2) }
}
// Returns a parser that satisfies the given predicate
public func satisfy<C: Collection> (_ pred: @escaping (C.Element) -> Bool) -> Parser<C, C.Element>.Function {
return tokenPrim(pred) { $0.advanced(by: 1, from: $2) }
}
public func tokenPrim<C: Collection> (_ pred: @escaping (C.Element) -> Bool, _ nextPos: @escaping (SourcePos<C.Index>, C.Element, C) -> SourcePos<C.Index>) -> Parser<C, C.Element>.Function {
return { input, sourcePos in
let index = sourcePos.index
if index != input.endIndex {
let parsed = input[index]
if pred(parsed) {
return .success((parsed, nextPos(sourcePos, parsed, input)))
} else {
return .failure(Error.leaf("Failed to parse \(String(describing: parsed)) with predicate at index", sourcePos))
}
} else {
return .failure(Error.leaf("Failed to parse at end of input", sourcePos))
}
}
}
// MARK: - Operators
/// Map operator.
infix operator --> : ChainingPrecedence
/// Literal operator.
prefix operator %
// MARK: - Imports
import Result
================================================
FILE: Madness/Reduction.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
/// Returns a parser which maps parse trees into another type.
public func --> <C: Collection, T, U>(parser: @escaping Parser<C, T>.Function, f: @escaping (C, CountableClosedRange<Line>, CountableClosedRange<Column>, Range<C.Index>, T) -> U) -> Parser<C, U>.Function {
return { input, inputPos in
return parser(input, inputPos).map { output, outputPos in
(f(input, inputPos.line...outputPos.line, outputPos.column...outputPos.column, inputPos.index..<outputPos.index, output), outputPos)
}
}
}
/// Returns a parser which maps parse results.
///
/// This enables e.g. adding identifiers for error handling.
public func --> <C: Collection, T, U> (parser: @escaping Parser<C, T>.Function, transform: @escaping (Parser<C, T>.Result) -> Parser<C, U>.Result) -> Parser<C, U>.Function {
return { transform(parser($0, $1)) }
}
================================================
FILE: Madness/Repetition.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
/// Parser `parser` 1 or more times.
public func some<C: Collection, T> (_ parser: @escaping Parser<C, T>.Function) -> Parser<C, [T]>.Function {
return prepend <^> require(parser) <*> many(parser)
}
/// Parses 1 or more `parser` separated by `separator`.
public func sepBy1<C: Collection, T, U>(_ parser: @escaping Parser<C, T>.Function, _ separator: @escaping Parser<C, U>.Function) -> Parser<C, [T]>.Function {
return prepend <^> parser <*> many(separator *> parser)
}
/// Parses 0 or more `parser` separated by `separator`.
public func sepBy<C: Collection, T, U>(_ parser: @escaping Parser<C, T>.Function, _ separator: @escaping Parser<C, U>.Function) -> Parser<C, [T]>.Function {
return sepBy1(parser, separator) <|> pure([])
}
/// Parses 1 or more `parser` ended by `terminator`.
public func endBy1<C: Collection, T, U>(_ parser: @escaping Parser<C, T>.Function, _ terminator: @escaping Parser<C, U>.Function) -> Parser<C, [T]>.Function {
return some(parser <* terminator)
}
/// Parses 0 or more `parser` ended by `terminator`.
public func endBy<C: Collection, T, U>(_ parser: @escaping Parser<C, T>.Function, _ terminator: @escaping Parser<C, U>.Function) -> Parser<C, [T]>.Function {
return many(parser <* terminator)
}
/// Parses `parser` the number of times specified in `interval`.
///
/// \param interval An interval specifying the number of repetitions to perform. `0...n` means at most `n` repetitions; `m...Int.max` means at least `m` repetitions; and `m...n` means between `m` and `n` repetitions (inclusive).
public func * <C: Collection, T> (parser: @escaping Parser<C, T>.Function, interval: CountableClosedRange<Int>) -> Parser<C, [T]>.Function {
if interval.upperBound <= 0 { return { .success(([], $1)) } }
return (parser >>- { x in { [x] + $0 } <^> (parser * decrement(interval)) })
<|> { interval.lowerBound <= 0 ? .success(([], $1)) : .failure(.leaf("expected at least \(interval.lowerBound) matches", $1)) }
}
/// Parses `parser` exactly `n` times.
///
/// `n` must be > 0 to make any sense.
public func * <C: Collection, T> (parser: @escaping Parser<C, T>.Function, n: Int) -> Parser<C, [T]>.Function {
return ntimes(parser, n)
}
/// Parses `parser` the number of times specified in `interval`.
///
/// \param interval An interval specifying the number of repetitions to perform. `0..<n` means at most `n-1` repetitions; `m..<Int.max` means at least `m` repetitions; and `m..<n` means at least `m` and fewer than `n` repetitions; `n..<n` is an error.
public func * <C: Collection, T> (parser: @escaping Parser<C, T>.Function, interval: Range<Int>) -> Parser<C, [T]>.Function {
if interval.isEmpty { return { .failure(.leaf("cannot parse an empty interval of repetitions", $1)) } }
return parser * (interval.lowerBound...decrement(interval.upperBound))
}
/// Parses `parser` 0 or more times.
public func many<C: Collection, T> (_ p: @escaping Parser<C, T>.Function) -> Parser<C, [T]>.Function {
return prepend <^> require(p) <*> delay { many(p) } <|> pure([])
}
/// Parses `parser` `n` number of times.
public func ntimes<C: Collection, T> (_ p: @escaping Parser<C, T>.Function, _ n: Int) -> Parser<C, [T]>.Function {
guard n > 0 else { return pure([]) }
return prepend <^> p <*> delay { ntimes(p, n - 1) }
}
// MARK: - Private
/// Decrements `x` iff it is not equal to `Int.max`.
private func decrement(_ x: Int) -> Int {
return (x == Int.max ? Int.max : x - 1)
}
private func decrement(_ x: CountableClosedRange<Int>) -> CountableClosedRange<Int> {
return decrement(x.lowerBound)...decrement(x.upperBound)
}
/// Fails iff `parser` does not consume input, otherwise pass through its results
private func require<C: Collection, T> (_ parser: @escaping Parser<C,T>.Function) -> Parser<C, T>.Function {
return { (input, sourcePos) in
return parser(input, sourcePos).flatMap { resultInput, resultPos in
if sourcePos.index == resultPos.index {
return Result.failure(Error.leaf("parser did not consume input when required", sourcePos))
}
return Result.success((resultInput, resultPos))
}
}
}
// MARK: - Imports
import Result
================================================
FILE: Madness/SourcePos.swift
================================================
// Copyright (c) 2014 Josh Vera. All rights reserved.
public typealias Line = Int
public typealias Column = Int
var DefaultTabWidth = 8
public struct SourcePos<Index: Comparable> {
public let line: Line
public let column: Column
public let index: Index
public init(index: Index) {
line = 1
column = 1
self.index = index
}
public init(line: Line, column: Column, index: Index) {
self.line = line
self.column = column
self.index = index
}
}
extension SourcePos: Equatable {
/// Returns whether two SourcePos are equal.
public static func ==(first: SourcePos, other: SourcePos) -> Bool {
return first.line == other.line && first.column == other.column && first.index == other.index
}
}
extension SourcePos {
/// Returns a new SourcePos advanced by the given index.
public func advanced(to index: Index) -> SourcePos {
return SourcePos(line: line, column: column, index: index)
}
/// Returns a new SourcePos advanced by `count`.
public func advanced<C: Collection>(by distance: C.IndexDistance, from input: C) -> SourcePos where C.Index == Index {
return advanced(to: input.index(index, offsetBy: distance))
}
}
extension SourcePos where Index == String.Index {
/// Returns a new SourcePos with its line, column, and index advanced by the given character.
public func advanced(by char: Character, from input: String.CharacterView) -> SourcePos {
let nextIndex = input.index(after: index)
if char == "\n" {
return SourcePos(line: line + 1, column: 0, index: nextIndex)
} else if char == "\t" {
return SourcePos(line: line, column: column + DefaultTabWidth - ((column - 1) % DefaultTabWidth), index: nextIndex)
} else {
return SourcePos(line: line, column: column + 1, index: nextIndex)
}
}
/// Returns a new SourcePos with its line, column, and index advanced by the given string.
func advanced(by string: String, from input: String.CharacterView) -> SourcePos {
return string.characters.reduce(self) { $0.advanced(by: $1, from: input) }
}
}
================================================
FILE: Madness/String.swift
================================================
//
// String.swift
// Madness
//
// Created by Josh Vera on 10/19/15.
// Copyright © 2015 Rob Rix. All rights reserved.
//
import Foundation
public typealias CharacterParser = Parser<String.CharacterView, Character>.Function
public typealias CharacterArrayParser = Parser<String.CharacterView, [Character]>.Function
public typealias StringParser = Parser<String.CharacterView, String>.Function
public typealias DoubleParser = Parser<String.CharacterView, Double>.Function
public typealias IntParser = Parser<String.CharacterView, Int>.Function
private func maybePrepend<T>(_ value: T?) -> ([T]) -> [T] {
return { value != nil ? [value!] + $0 : $0 }
}
private func concat<T>(_ value: [T]) -> ([T]) -> [T] {
return { value + $0 }
}
private func concat2<T>(_ value: [T]) -> ([T]) -> ([T]) -> [T] {
return { value2 in { value + value2 + $0 } }
}
private let someDigits: CharacterArrayParser = some(digit)
// Parses integers as an array of characters
public let int: CharacterArrayParser = {
let minus: Parser<String.CharacterView, Character?>.Function = char("-")|?
return maybePrepend <^> minus <*> someDigits
}()
private let decimal: CharacterArrayParser = prepend <^> %"." <*> someDigits
private let exp: StringParser = %"e+" <|> %"e-" <|> %"e" <|> %"E+" <|> %"E-" <|> %"E"
private let exponent: CharacterArrayParser = { s in { s.characters + $0 } } <^> exp <*> someDigits
// Parses floating point numbers as doubles
public let number: DoubleParser = { characters in Double(String(characters))! } <^>
((concat2 <^> int <*> decimal <*> exponent)
<|> (concat <^> int <*> decimal)
<|> (concat <^> int <*> exponent)
<|> int)
public let digit: CharacterParser = oneOf("0123456789")
public let space: CharacterParser = char(" ")
public let newline: CharacterParser = char("\n")
public let cr = char("\r")
public let crlf: CharacterParser = char("\r\n")
public let endOfLine: CharacterParser = newline <|> crlf
public let tab: CharacterParser = char("\t")
public func oneOf(_ input: String) -> CharacterParser {
return satisfy { input.characters.contains($0) }
}
public func noneOf(_ input: String) -> CharacterParser {
return satisfy { !input.characters.contains($0) }
}
public func char(_ input: Character) -> CharacterParser {
return satisfy { $0 == input }
}
================================================
FILE: Madness.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
849DC2381C0F21D0004C1A1E /* Combinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849DC2371C0F21D0004C1A1E /* Combinator.swift */; };
849DC2391C0F21D0004C1A1E /* Combinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849DC2371C0F21D0004C1A1E /* Combinator.swift */; };
849DC23A1C0F21E1004C1A1E /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E153551BD5B78E00627E39 /* String.swift */; };
849DC23C1C0F224D004C1A1E /* CombinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849DC23B1C0F224D004C1A1E /* CombinatorTests.swift */; };
849DC23D1C0F224D004C1A1E /* CombinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849DC23B1C0F224D004C1A1E /* CombinatorTests.swift */; };
B8219A941BF1DF05000006F1 /* Negation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8219A931BF1DF05000006F1 /* Negation.swift */; };
B8219A951BF1DF0A000006F1 /* Negation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8219A931BF1DF05000006F1 /* Negation.swift */; };
B8219A981BF1ED07000006F1 /* NegationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8219A971BF1ED07000006F1 /* NegationTests.swift */; };
B88CCA091BF2C17700979677 /* NegationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8219A971BF1ED07000006F1 /* NegationTests.swift */; };
B8E0AB871BF098DD002B5C8B /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8E0AB861BF098DD002B5C8B /* StringTests.swift */; };
B8E0AB881BF098DD002B5C8B /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8E0AB861BF098DD002B5C8B /* StringTests.swift */; };
BECD3BD21F8D918E006FF13E /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BECD3BD11F8D918E006FF13E /* Result.framework */; };
BECD3BD51F8D91A8006FF13E /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BECD3BD41F8D91A8006FF13E /* Result.framework */; };
D1A6B7F91BE01B8F00B4858C /* SourcePos.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A6B7F81BE01B8F00B4858C /* SourcePos.swift */; };
D1A6B7FA1BE01B8F00B4858C /* SourcePos.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A6B7F81BE01B8F00B4858C /* SourcePos.swift */; };
D1E153561BD5B78E00627E39 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E153551BD5B78E00627E39 /* String.swift */; };
D421A2A91A9A8E33009AC3B1 /* IgnoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D421A2A81A9A8E33009AC3B1 /* IgnoreTests.swift */; };
D421A2AA1A9A8E33009AC3B1 /* IgnoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D421A2A81A9A8E33009AC3B1 /* IgnoreTests.swift */; };
D421A2AC1A9A9540009AC3B1 /* ReductionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D421A2AB1A9A9540009AC3B1 /* ReductionTests.swift */; };
D421A2AD1A9A9540009AC3B1 /* ReductionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D421A2AB1A9A9540009AC3B1 /* ReductionTests.swift */; };
D47B10761A9A9A1C006701A8 /* Reduction.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47B10751A9A9A1C006701A8 /* Reduction.swift */; };
D47B10771A9A9A1C006701A8 /* Reduction.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47B10751A9A9A1C006701A8 /* Reduction.swift */; };
D490927A1A98F11A00275C79 /* CollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49092791A98F11A00275C79 /* CollectionTests.swift */; };
D490927B1A98F11A00275C79 /* CollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49092791A98F11A00275C79 /* CollectionTests.swift */; };
D4BC5E021A98C8B4008C6851 /* Madness.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4BC5DF71A98C8B4008C6851 /* Madness.framework */; };
D4BC5E101A98C978008C6851 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4FC47CD1A37E48800D23A6F /* Parser.swift */; };
D4BC5E121A98C97C008C6851 /* ParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4FC47C31A37E47C00D23A6F /* ParserTests.swift */; };
D4BC5E131A98C97C008C6851 /* MapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C8B02D1A69B1A900943303 /* MapTests.swift */; };
D4C0FB011AC5EDA500936032 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C0FAFE1AC5ECCE00936032 /* Fixtures.swift */; };
D4C0FB021AC5EDA600936032 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C0FAFE1AC5ECCE00936032 /* Fixtures.swift */; };
D4C2EDA71A98D38E00054FAA /* Concatenation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDA61A98D38E00054FAA /* Concatenation.swift */; };
D4C2EDAA1A98D4D400054FAA /* ConcatenationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDA81A98D49500054FAA /* ConcatenationTests.swift */; };
D4C2EDAB1A98D4D600054FAA /* ConcatenationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDA81A98D49500054FAA /* ConcatenationTests.swift */; };
D4C2EDAC1A98D4DE00054FAA /* Concatenation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDA61A98D38E00054FAA /* Concatenation.swift */; };
D4C2EDAE1A98D52B00054FAA /* Alternation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDAD1A98D52B00054FAA /* Alternation.swift */; };
D4C2EDAF1A98D53400054FAA /* Alternation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDAD1A98D52B00054FAA /* Alternation.swift */; };
D4C2EDB11A98D5DB00054FAA /* AlternationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDB01A98D5DB00054FAA /* AlternationTests.swift */; };
D4C2EDB21A98D5DB00054FAA /* AlternationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDB01A98D5DB00054FAA /* AlternationTests.swift */; };
D4C2EDB61A98D65300054FAA /* Repetition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDB31A98D63600054FAA /* Repetition.swift */; };
D4C2EDB71A98D65400054FAA /* Repetition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDB31A98D63600054FAA /* Repetition.swift */; };
D4C2EDB91A98D82200054FAA /* RepetitionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDB81A98D82200054FAA /* RepetitionTests.swift */; };
D4C2EDBA1A98D82200054FAA /* RepetitionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDB81A98D82200054FAA /* RepetitionTests.swift */; };
D4C2EDBC1A98D8F800054FAA /* Map.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDBB1A98D8F800054FAA /* Map.swift */; };
D4C2EDBD1A98D8F800054FAA /* Map.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C2EDBB1A98D8F800054FAA /* Map.swift */; };
D4C2EDFC1A98DEE800054FAA /* Madness.h in Headers */ = {isa = PBXBuildFile; fileRef = D4FC47B61A37E47C00D23A6F /* Madness.h */; settings = {ATTRIBUTES = (Public, ); }; };
D4C8B02E1A69B1A900943303 /* MapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C8B02D1A69B1A900943303 /* MapTests.swift */; };
D4D328491A9AFE2700216D7E /* ErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D328481A9AFE2700216D7E /* ErrorTests.swift */; };
D4D9F28A1A9C42A7002BEFF2 /* ErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D328481A9AFE2700216D7E /* ErrorTests.swift */; };
D4DE2EE61ABCB2D000D3D70A /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D3284B1A9AFE6000216D7E /* Error.swift */; };
D4DE2EE71ABCB2D100D3D70A /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D3284B1A9AFE6000216D7E /* Error.swift */; };
D4FC47B71A37E47C00D23A6F /* Madness.h in Headers */ = {isa = PBXBuildFile; fileRef = D4FC47B61A37E47C00D23A6F /* Madness.h */; settings = {ATTRIBUTES = (Public, ); }; };
D4FC47BD1A37E47C00D23A6F /* Madness.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4FC47B11A37E47C00D23A6F /* Madness.framework */; };
D4FC47C41A37E47C00D23A6F /* ParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4FC47C31A37E47C00D23A6F /* ParserTests.swift */; };
D4FC47CE1A37E48800D23A6F /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4FC47CD1A37E48800D23A6F /* Parser.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
D4BC5E031A98C8B4008C6851 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D4FC47A81A37E47C00D23A6F /* Project object */;
proxyType = 1;
remoteGlobalIDString = D4BC5DF61A98C8B4008C6851;
remoteInfo = Madness;
};
D4FC47BE1A37E47C00D23A6F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D4FC47A81A37E47C00D23A6F /* Project object */;
proxyType = 1;
remoteGlobalIDString = D4FC47B01A37E47C00D23A6F;
remoteInfo = Madness;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
849DC2371C0F21D0004C1A1E /* Combinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Combinator.swift; sourceTree = "<group>"; };
849DC23B1C0F224D004C1A1E /* CombinatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombinatorTests.swift; sourceTree = "<group>"; };
B8219A931BF1DF05000006F1 /* Negation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Negation.swift; sourceTree = "<group>"; };
B8219A971BF1ED07000006F1 /* NegationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NegationTests.swift; sourceTree = "<group>"; };
B8E0AB861BF098DD002B5C8B /* StringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = "<group>"; };
BECD3BD11F8D918E006FF13E /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BECD3BD41F8D91A8006FF13E /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D1A6B7F81BE01B8F00B4858C /* SourcePos.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourcePos.swift; sourceTree = "<group>"; };
D1E153551BD5B78E00627E39 /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
D421A2A81A9A8E33009AC3B1 /* IgnoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IgnoreTests.swift; sourceTree = "<group>"; };
D421A2AB1A9A9540009AC3B1 /* ReductionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ReductionTests.swift; path = MadnessTests/ReductionTests.swift; sourceTree = SOURCE_ROOT; };
D47B10751A9A9A1C006701A8 /* Reduction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reduction.swift; sourceTree = "<group>"; };
D49092791A98F11A00275C79 /* CollectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionTests.swift; sourceTree = "<group>"; };
D4BC5DF71A98C8B4008C6851 /* Madness.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Madness.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D4BC5E011A98C8B4008C6851 /* Madness-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Madness-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
D4C0FAFE1AC5ECCE00936032 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
D4C2EDA61A98D38E00054FAA /* Concatenation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Concatenation.swift; sourceTree = "<group>"; };
D4C2EDA81A98D49500054FAA /* ConcatenationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcatenationTests.swift; sourceTree = "<group>"; };
D4C2EDAD1A98D52B00054FAA /* Alternation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Alternation.swift; sourceTree = "<group>"; };
D4C2EDB01A98D5DB00054FAA /* AlternationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlternationTests.swift; sourceTree = "<group>"; };
D4C2EDB31A98D63600054FAA /* Repetition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Repetition.swift; sourceTree = "<group>"; };
D4C2EDB81A98D82200054FAA /* RepetitionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepetitionTests.swift; sourceTree = "<group>"; };
D4C2EDBB1A98D8F800054FAA /* Map.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Map.swift; sourceTree = "<group>"; };
D4C8B02D1A69B1A900943303 /* MapTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapTests.swift; sourceTree = "<group>"; };
D4D328481A9AFE2700216D7E /* ErrorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorTests.swift; sourceTree = "<group>"; };
D4D3284B1A9AFE6000216D7E /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
D4FC47B11A37E47C00D23A6F /* Madness.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Madness.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D4FC47B51A37E47C00D23A6F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D4FC47B61A37E47C00D23A6F /* Madness.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Madness.h; sourceTree = "<group>"; };
D4FC47BC1A37E47C00D23A6F /* Madness-MacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Madness-MacTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
D4FC47C21A37E47C00D23A6F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D4FC47C31A37E47C00D23A6F /* ParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParserTests.swift; sourceTree = "<group>"; };
D4FC47CD1A37E48800D23A6F /* Parser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D4BC5DF31A98C8B4008C6851 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
BECD3BD51F8D91A8006FF13E /* Result.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D4BC5DFE1A98C8B4008C6851 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D4BC5E021A98C8B4008C6851 /* Madness.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D4FC47AD1A37E47C00D23A6F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
BECD3BD21F8D918E006FF13E /* Result.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D4FC47B91A37E47C00D23A6F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D4FC47BD1A37E47C00D23A6F /* Madness.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
BECD3BD31F8D9199006FF13E /* Frameworks */ = {
isa = PBXGroup;
children = (
BECD3BD41F8D91A8006FF13E /* Result.framework */,
BECD3BD11F8D918E006FF13E /* Result.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
D4FC47A71A37E47C00D23A6F = {
isa = PBXGroup;
children = (
D4FC47B31A37E47C00D23A6F /* Madness */,
D4FC47C01A37E47C00D23A6F /* MadnessTests */,
BECD3BD31F8D9199006FF13E /* Frameworks */,
D4FC47B21A37E47C00D23A6F /* Products */,
);
sourceTree = "<group>";
usesTabs = 1;
};
D4FC47B21A37E47C00D23A6F /* Products */ = {
isa = PBXGroup;
children = (
D4FC47B11A37E47C00D23A6F /* Madness.framework */,
D4FC47BC1A37E47C00D23A6F /* Madness-MacTests.xctest */,
D4BC5DF71A98C8B4008C6851 /* Madness.framework */,
D4BC5E011A98C8B4008C6851 /* Madness-iOSTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
D4FC47B31A37E47C00D23A6F /* Madness */ = {
isa = PBXGroup;
children = (
D4FC47B61A37E47C00D23A6F /* Madness.h */,
D4FC47CD1A37E48800D23A6F /* Parser.swift */,
D1A6B7F81BE01B8F00B4858C /* SourcePos.swift */,
D4C2EDAD1A98D52B00054FAA /* Alternation.swift */,
D4C2EDA61A98D38E00054FAA /* Concatenation.swift */,
D4D3284B1A9AFE6000216D7E /* Error.swift */,
D4C2EDBB1A98D8F800054FAA /* Map.swift */,
B8219A931BF1DF05000006F1 /* Negation.swift */,
D47B10751A9A9A1C006701A8 /* Reduction.swift */,
D4C2EDB31A98D63600054FAA /* Repetition.swift */,
849DC2371C0F21D0004C1A1E /* Combinator.swift */,
D4FC47B41A37E47C00D23A6F /* Supporting Files */,
D1E153551BD5B78E00627E39 /* String.swift */,
);
path = Madness;
sourceTree = "<group>";
};
D4FC47B41A37E47C00D23A6F /* Supporting Files */ = {
isa = PBXGroup;
children = (
D4FC47B51A37E47C00D23A6F /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
D4FC47C01A37E47C00D23A6F /* MadnessTests */ = {
isa = PBXGroup;
children = (
D4FC47C31A37E47C00D23A6F /* ParserTests.swift */,
D4C2EDB01A98D5DB00054FAA /* AlternationTests.swift */,
D49092791A98F11A00275C79 /* CollectionTests.swift */,
D4C2EDA81A98D49500054FAA /* ConcatenationTests.swift */,
849DC23B1C0F224D004C1A1E /* CombinatorTests.swift */,
D4D328481A9AFE2700216D7E /* ErrorTests.swift */,
D4C8B02D1A69B1A900943303 /* MapTests.swift */,
B8219A971BF1ED07000006F1 /* NegationTests.swift */,
D421A2A81A9A8E33009AC3B1 /* IgnoreTests.swift */,
D421A2AB1A9A9540009AC3B1 /* ReductionTests.swift */,
D4C2EDB81A98D82200054FAA /* RepetitionTests.swift */,
B8E0AB861BF098DD002B5C8B /* StringTests.swift */,
D4C0FAFE1AC5ECCE00936032 /* Fixtures.swift */,
D4FC47C11A37E47C00D23A6F /* Supporting Files */,
);
path = MadnessTests;
sourceTree = "<group>";
};
D4FC47C11A37E47C00D23A6F /* Supporting Files */ = {
isa = PBXGroup;
children = (
D4FC47C21A37E47C00D23A6F /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
D4BC5DF41A98C8B4008C6851 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
D4C2EDFC1A98DEE800054FAA /* Madness.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D4FC47AE1A37E47C00D23A6F /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
D4FC47B71A37E47C00D23A6F /* Madness.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
D4BC5DF61A98C8B4008C6851 /* Madness-iOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = D4BC5E0A1A98C8B4008C6851 /* Build configuration list for PBXNativeTarget "Madness-iOS" */;
buildPhases = (
D4BC5DF21A98C8B4008C6851 /* Sources */,
D4BC5DF31A98C8B4008C6851 /* Frameworks */,
D4BC5DF41A98C8B4008C6851 /* Headers */,
D4BC5DF51A98C8B4008C6851 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "Madness-iOS";
productName = Madness;
productReference = D4BC5DF71A98C8B4008C6851 /* Madness.framework */;
productType = "com.apple.product-type.framework";
};
D4BC5E001A98C8B4008C6851 /* Madness-iOSTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = D4BC5E0D1A98C8B4008C6851 /* Build configuration list for PBXNativeTarget "Madness-iOSTests" */;
buildPhases = (
D4BC5DFD1A98C8B4008C6851 /* Sources */,
D4BC5DFE1A98C8B4008C6851 /* Frameworks */,
D4BC5DFF1A98C8B4008C6851 /* Resources */,
);
buildRules = (
);
dependencies = (
D4BC5E041A98C8B4008C6851 /* PBXTargetDependency */,
);
name = "Madness-iOSTests";
productName = MadnessTests;
productReference = D4BC5E011A98C8B4008C6851 /* Madness-iOSTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
D4FC47B01A37E47C00D23A6F /* Madness-Mac */ = {
isa = PBXNativeTarget;
buildConfigurationList = D4FC47C71A37E47C00D23A6F /* Build configuration list for PBXNativeTarget "Madness-Mac" */;
buildPhases = (
D4FC47AC1A37E47C00D23A6F /* Sources */,
D4FC47AD1A37E47C00D23A6F /* Frameworks */,
D4FC47AE1A37E47C00D23A6F /* Headers */,
D4FC47AF1A37E47C00D23A6F /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "Madness-Mac";
productName = Madness;
productReference = D4FC47B11A37E47C00D23A6F /* Madness.framework */;
productType = "com.apple.product-type.framework";
};
D4FC47BB1A37E47C00D23A6F /* Madness-MacTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = D4FC47CA1A37E47C00D23A6F /* Build configuration list for PBXNativeTarget "Madness-MacTests" */;
buildPhases = (
D4FC47B81A37E47C00D23A6F /* Sources */,
D4FC47B91A37E47C00D23A6F /* Frameworks */,
D4FC47BA1A37E47C00D23A6F /* Resources */,
);
buildRules = (
);
dependencies = (
D4FC47BF1A37E47C00D23A6F /* PBXTargetDependency */,
);
name = "Madness-MacTests";
productName = MadnessTests;
productReference = D4FC47BC1A37E47C00D23A6F /* Madness-MacTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D4FC47A81A37E47C00D23A6F /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0900;
ORGANIZATIONNAME = "Rob Rix";
TargetAttributes = {
D4BC5DF61A98C8B4008C6851 = {
CreatedOnToolsVersion = 6.3;
};
D4BC5E001A98C8B4008C6851 = {
CreatedOnToolsVersion = 6.3;
};
D4FC47B01A37E47C00D23A6F = {
CreatedOnToolsVersion = 6.1.1;
LastSwiftMigration = 0900;
};
D4FC47BB1A37E47C00D23A6F = {
CreatedOnToolsVersion = 6.1.1;
LastSwiftMigration = 0900;
};
};
};
buildConfigurationList = D4FC47AB1A37E47C00D23A6F /* Build configuration list for PBXProject "Madness" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = D4FC47A71A37E47C00D23A6F;
productRefGroup = D4FC47B21A37E47C00D23A6F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D4FC47B01A37E47C00D23A6F /* Madness-Mac */,
D4FC47BB1A37E47C00D23A6F /* Madness-MacTests */,
D4BC5DF61A98C8B4008C6851 /* Madness-iOS */,
D4BC5E001A98C8B4008C6851 /* Madness-iOSTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
D4BC5DF51A98C8B4008C6851 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
D4BC5DFF1A98C8B4008C6851 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
D4FC47AF1A37E47C00D23A6F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
D4FC47BA1A37E47C00D23A6F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
D4BC5DF21A98C8B4008C6851 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
849DC23A1C0F21E1004C1A1E /* String.swift in Sources */,
D4DE2EE71ABCB2D100D3D70A /* Error.swift in Sources */,
849DC2391C0F21D0004C1A1E /* Combinator.swift in Sources */,
D4C2EDAF1A98D53400054FAA /* Alternation.swift in Sources */,
D4BC5E101A98C978008C6851 /* Parser.swift in Sources */,
D4C2EDBD1A98D8F800054FAA /* Map.swift in Sources */,
D4C2EDAC1A98D4DE00054FAA /* Concatenation.swift in Sources */,
D1A6B7FA1BE01B8F00B4858C /* SourcePos.swift in Sources */,
D47B10771A9A9A1C006701A8 /* Reduction.swift in Sources */,
B8219A951BF1DF0A000006F1 /* Negation.swift in Sources */,
D4C2EDB61A98D65300054FAA /* Repetition.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D4BC5DFD1A98C8B4008C6851 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D4C2EDAB1A98D4D600054FAA /* ConcatenationTests.swift in Sources */,
D4C2EDBA1A98D82200054FAA /* RepetitionTests.swift in Sources */,
849DC23D1C0F224D004C1A1E /* CombinatorTests.swift in Sources */,
D490927B1A98F11A00275C79 /* CollectionTests.swift in Sources */,
D4C0FB011AC5EDA500936032 /* Fixtures.swift in Sources */,
B8E0AB881BF098DD002B5C8B /* StringTests.swift in Sources */,
D4BC5E131A98C97C008C6851 /* MapTests.swift in Sources */,
B88CCA091BF2C17700979677 /* NegationTests.swift in Sources */,
D4BC5E121A98C97C008C6851 /* ParserTests.swift in Sources */,
D4C2EDB21A98D5DB00054FAA /* AlternationTests.swift in Sources */,
D421A2AA1A9A8E33009AC3B1 /* IgnoreTests.swift in Sources */,
D4D9F28A1A9C42A7002BEFF2 /* ErrorTests.swift in Sources */,
D421A2AD1A9A9540009AC3B1 /* ReductionTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D4FC47AC1A37E47C00D23A6F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D4DE2EE61ABCB2D000D3D70A /* Error.swift in Sources */,
D4C2EDAE1A98D52B00054FAA /* Alternation.swift in Sources */,
D4FC47CE1A37E48800D23A6F /* Parser.swift in Sources */,
B8219A941BF1DF05000006F1 /* Negation.swift in Sources */,
D4C2EDBC1A98D8F800054FAA /* Map.swift in Sources */,
D4C2EDA71A98D38E00054FAA /* Concatenation.swift in Sources */,
D1A6B7F91BE01B8F00B4858C /* SourcePos.swift in Sources */,
849DC2381C0F21D0004C1A1E /* Combinator.swift in Sources */,
D47B10761A9A9A1C006701A8 /* Reduction.swift in Sources */,
D1E153561BD5B78E00627E39 /* String.swift in Sources */,
D4C2EDB71A98D65400054FAA /* Repetition.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D4FC47B81A37E47C00D23A6F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D4C2EDAA1A98D4D400054FAA /* ConcatenationTests.swift in Sources */,
D4C8B02E1A69B1A900943303 /* MapTests.swift in Sources */,
849DC23C1C0F224D004C1A1E /* CombinatorTests.swift in Sources */,
D490927A1A98F11A00275C79 /* CollectionTests.swift in Sources */,
D4C0FB021AC5EDA600936032 /* Fixtures.swift in Sources */,
B8E0AB871BF098DD002B5C8B /* StringTests.swift in Sources */,
D4C2EDB91A98D82200054FAA /* RepetitionTests.swift in Sources */,
B8219A981BF1ED07000006F1 /* NegationTests.swift in Sources */,
D4FC47C41A37E47C00D23A6F /* ParserTests.swift in Sources */,
D4D328491A9AFE2700216D7E /* ErrorTests.swift in Sources */,
D4C2EDB11A98D5DB00054FAA /* AlternationTests.swift in Sources */,
D421A2A91A9A8E33009AC3B1 /* IgnoreTests.swift in Sources */,
D421A2AC1A9A9540009AC3B1 /* ReductionTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
D4BC5E041A98C8B4008C6851 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D4BC5DF61A98C8B4008C6851 /* Madness-iOS */;
targetProxy = D4BC5E031A98C8B4008C6851 /* PBXContainerItemProxy */;
};
D4FC47BF1A37E47C00D23A6F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D4FC47B01A37E47C00D23A6F /* Madness-Mac */;
targetProxy = D4FC47BE1A37E47C00D23A6F /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
D4BC5E0B1A98C8B4008C6851 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = Madness/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = Madness;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
D4BC5E0C1A98C8B4008C6851 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
COPY_PHASE_STRIP = NO;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = Madness/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = Madness;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
D4BC5E0E1A98C8B4008C6851 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEBUG_INFORMATION_FORMAT = dwarf;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = MadnessTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
D4BC5E0F1A98C8B4008C6851 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = MadnessTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_VERSION = 3.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
D4FC47C51A37E47C00D23A6F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
D4FC47C61A37E47C00D23A6F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
D4FC47C81A37E47C00D23A6F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Madness/Info.plist;
INSTALL_PATH = "@rpath";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = Madness;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
};
name = Debug;
};
D4FC47C91A37E47C00D23A6F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Madness/Info.plist;
INSTALL_PATH = "@rpath";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = Madness;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.0;
};
name = Release;
};
D4FC47CB1A37E47C00D23A6F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = MadnessTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
};
name = Debug;
};
D4FC47CC1A37E47C00D23A6F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
INFOPLIST_FILE = MadnessTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
D4BC5E0A1A98C8B4008C6851 /* Build configuration list for PBXNativeTarget "Madness-iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D4BC5E0B1A98C8B4008C6851 /* Debug */,
D4BC5E0C1A98C8B4008C6851 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D4BC5E0D1A98C8B4008C6851 /* Build configuration list for PBXNativeTarget "Madness-iOSTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D4BC5E0E1A98C8B4008C6851 /* Debug */,
D4BC5E0F1A98C8B4008C6851 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D4FC47AB1A37E47C00D23A6F /* Build configuration list for PBXProject "Madness" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D4FC47C51A37E47C00D23A6F /* Debug */,
D4FC47C61A37E47C00D23A6F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D4FC47C71A37E47C00D23A6F /* Build configuration list for PBXNativeTarget "Madness-Mac" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D4FC47C81A37E47C00D23A6F /* Debug */,
D4FC47C91A37E47C00D23A6F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D4FC47CA1A37E47C00D23A6F /* Build configuration list for PBXNativeTarget "Madness-MacTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D4FC47CB1A37E47C00D23A6F /* Debug */,
D4FC47CC1A37E47C00D23A6F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D4FC47A81A37E47C00D23A6F /* Project object */;
}
================================================
FILE: Madness.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Madness.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: Madness.xcodeproj/xcshareddata/xcschemes/Madness-Mac.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4FC47B01A37E47C00D23A6F"
BuildableName = "Madness.framework"
BlueprintName = "Madness-Mac"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4FC47BB1A37E47C00D23A6F"
BuildableName = "Madness-MacTests.xctest"
BlueprintName = "Madness-MacTests"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4FC47BB1A37E47C00D23A6F"
BuildableName = "Madness-MacTests.xctest"
BlueprintName = "Madness-MacTests"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4FC47B01A37E47C00D23A6F"
BuildableName = "Madness.framework"
BlueprintName = "Madness-Mac"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4FC47B01A37E47C00D23A6F"
BuildableName = "Madness.framework"
BlueprintName = "Madness-Mac"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4FC47B01A37E47C00D23A6F"
BuildableName = "Madness.framework"
BlueprintName = "Madness-Mac"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: Madness.xcodeproj/xcshareddata/xcschemes/Madness-iOS.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4BC5DF61A98C8B4008C6851"
BuildableName = "Madness.framework"
BlueprintName = "Madness-iOS"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4BC5E001A98C8B4008C6851"
BuildableName = "Madness-iOSTests.xctest"
BlueprintName = "Madness-iOSTests"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4BC5E001A98C8B4008C6851"
BuildableName = "Madness-iOSTests.xctest"
BlueprintName = "Madness-iOSTests"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4BC5DF61A98C8B4008C6851"
BuildableName = "Madness.framework"
BlueprintName = "Madness-iOS"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4BC5DF61A98C8B4008C6851"
BuildableName = "Madness.framework"
BlueprintName = "Madness-iOS"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4BC5DF61A98C8B4008C6851"
BuildableName = "Madness.framework"
BlueprintName = "Madness-iOS"
ReferencedContainer = "container:Madness.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: Madness.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<Group
location = "container:Documentation"
name = "Documentation">
<FileRef
location = "group:Collections.playground">
</FileRef>
<FileRef
location = "group:Colours.playground">
</FileRef>
<FileRef
location = "group:Lambda Calculus.playground">
</FileRef>
<FileRef
location = "group:Subset of Common Markdown.playground">
</FileRef>
</Group>
<FileRef
location = "group:Carthage/Checkouts/Result/Result.xcodeproj">
</FileRef>
<FileRef
location = "group:Madness.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: MadnessTests/AlternationTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
final class AlternationTests: XCTestCase {
// MARK: Alternation
func testAlternationParsesEitherAlternative() {
assertAdvancedBy(alternation, input: "xy".characters, lineOffset: 0, columnOffset: 1, offset: 1)
assertAdvancedBy(alternation, input: "yx".characters, lineOffset: 0, columnOffset: 1, offset: 1)
}
func testAlternationOfASingleTypeCoalescesTheParsedValue() {
assertTree(alternation, "xy".characters, ==, "x")
}
// MARK: Optional
func testOptionalProducesWhenPresent() {
assertTree(optional, "y".characters, ==, "y")
assertTree(prefixed, "xy".characters, ==, "xy")
assertTree(suffixed, "yzsandwiched".characters, ==, "yz")
}
func testOptionalProducesWhenAbsent() {
assertTree(optional, "".characters, ==, "")
assertTree(prefixed, "x".characters, ==, "x")
assertTree(suffixed, "z".characters, ==, "z")
assertTree(sandwiched, "xz".characters, ==, "xz")
}
// MARK: One-of
func testOneOfParsesFirstMatch() {
assertTree(one, "xyz".characters, ==, "x")
assertTree(one, "yzx".characters, ==, "y")
assertTree(one, "zxy".characters, ==, "z")
}
// MARK: Any-of
func testAnyOfParsesAnArrayOfMatchesPreservingOrder() {
assertTree(any, "xy".characters, ==, ["x", "y"])
assertTree(any, "yx".characters, ==, ["y", "x"])
assertTree(any, "zxy".characters, ==, ["z", "x", "y"])
}
func testAnyOfRejectsWhenNoneMatch() {
assertUnmatched(anyOf(Set("x")), Set("y".characters))
}
func testAnyOfOnlyParsesFirstMatch() {
assertTree(any, "xyy".characters, ==, ["x", "y"])
}
// MARK: All-of
func testAllOfParsesAnArrayOfMatchesPreservingOrder() {
assertTree(all, "xy".characters, ==, ["x", "y"])
assertTree(all, "yx".characters, ==, ["y", "x"])
assertTree(all, "zxy".characters, ==, ["z", "x", "y"])
}
func testAllOfRejectsWhenNoneMatch() {
assertUnmatched(allOf(Set("x")), Set(["y"]))
}
}
// MARK: - Fixtures
private let alternation = %"x" <|> %"y"
private let optional = map({ $0 ?? "" })((%"y")|?)
private let prefixed = { x in { y in x + y } } <^> %"x" <*> optional
private let suffixed = { x in { y in x + y } } <^> optional <*> %"z"
private let sandwiched = { x in { y in x + y } } <^> prefixed <*> %"z"
private let arrayOfChars: Set<Character> = ["x", "y", "z"]
private let chars: String = "xyz"
private let one = oneOf(chars)
private let any: Parser<String.CharacterView, [Character]>.Function = anyOf(arrayOfChars)
private let all: Parser<String.CharacterView, [Character]>.Function = allOf(arrayOfChars)
// MARK: - Imports
import Madness
import Result
import XCTest
================================================
FILE: MadnessTests/CollectionTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
final class CollectionTests: XCTestCase {
func testParsingCollections() {
let input = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
typealias Fibonacci = Parser<[Int], [Int]>.Function
func fibonacci(_ x: Int, _ y: Int) -> Fibonacci {
let combined: Fibonacci = %(x + y) >>- { (xy: Int) -> Fibonacci in
{ [ xy ] + $0 } <^> fibonacci(y, xy)
}
return combined <|> pure([])
}
XCTAssertEqual(parse(fibonacci(0, 1), input: input).value!, input)
}
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: MadnessTests/CombinatorTests.swift
================================================
// Copyright © 2015 Rob Rix. All rights reserved.
final class CombinatorTests: XCTestCase {
// MARK: - between
let braces: (@escaping StringParser) -> StringParser = between(%"{", %"}")
func testBetweenCombinatorParsesSandwichedString(){
assertTree(braces(%"a"), "{a}".characters, ==, "a")
}
func testBetweenCombinatorAcceptsEmptyString(){
assertTree(braces(%""), "{}".characters, ==, "")
}
// MARK: - manyTill
let digits = manyTill(digit, %",")
func testManyTillCombinatorParsesElementsUntilEndParser(){
assertTree(digits, "123,".characters, ==, ["1", "2", "3"])
}
func testManyTillCombinatorAcceptsEmptyString(){
assertTree(digits, ",".characters, ==, [])
}
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: MadnessTests/ConcatenationTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
final class ConcatenationTests: XCTestCase {
let concatenation = lift(pair) <*> %"x" <*> %"y"
func testConcatenationRejectsPartialParses() {
assertUnmatched(concatenation, "x".characters)
}
func testConcatenationParsesBothOperands() {
assertAdvancedBy(concatenation, input: "xyz".characters, lineOffset: 0, columnOffset: 2, offset: 2)
}
func testConcatenationProducesPairsOfTerms() {
let input = "xy".characters
let parsed = concatenation(input, SourcePos(index: input.startIndex))
XCTAssertEqual(parsed.value?.0.0, "x")
XCTAssertEqual(parsed.value?.0.1, "y")
}
}
func matches<C: Collection, T>(_ parser: Parser<C, T>.Function, input: C) -> Bool {
return parser(input, SourcePos(index: input.startIndex)).value != nil
}
func doesNotMatch<C: Collection, T>(_ parser: Parser<C, T>.Function, input: C) -> Bool {
return parser(input, SourcePos(index: input.startIndex)).value == nil
}
func assertUnmatched<C: Collection, T>(_ parser: Parser<C, T>.Function, _ input: C, message: String = "", file: StaticString = #file, line: UInt = #line) {
XCTAssertNil(parser(input, SourcePos(index: input.startIndex)).value, "should not have matched \(input). " + message, file: file, line: line)
}
func assertMatched<C: Collection, T>(_ parser: Parser<C, T>.Function, input: C, message: String = "", file: StaticString = #file, line: UInt = #line) {
XCTAssertNotNil(parser(input, SourcePos(index: input.startIndex)).value, "should have matched \(input). " + message, file: file, line: line)
}
func assertTree<C: Collection, T>(_ parser: Parser<C, T>.Function, _ input: C, _ match: @escaping (T, T) -> Bool, _ tree: T, message: String = "", file: StaticString = #file, line: UInt = #line) {
let parsed: Parser<C, T>.Result = parser(input, SourcePos(index: input.startIndex))
let value = parsed.value?.0
XCTAssert(value.map { match($0, tree) } ?? false, "should have parsed \(input) as \(tree). " + message, file: file, line: line)
}
func assertAdvancedBy<C: Collection, T>(_ parser: Parser<C, T>.Function, input: C, offset: C.IndexDistance, message: String = "", file: StaticString = #file, line: UInt = #line) {
let pos = SourcePos(index: input.startIndex)
let newSourcePos: SourcePos<C.Index>? = SourcePos(line: pos.line, column: pos.column, index: input.index(pos.index, offsetBy: offset))
let value = parser(input, pos).value
XCTAssertNotNil(value, "should have parsed \(input) and advanced by \(offset). " + message, file: file, line: line)
XCTAssertEqual(value?.1, newSourcePos, "should have parsed \(input) and advanced by \(offset). " + message, file: file, line: line)
}
func assertAdvancedBy<C: Collection, T>(_ parser: Parser<C, T>.Function, input: C, lineOffset: Line, columnOffset: Column, offset: C.IndexDistance, message: String = "", file: StaticString = #file, line: UInt = #line) {
let pos = SourcePos(index: input.startIndex)
let newSourcePos: SourcePos<C.Index>? = SourcePos(line: pos.line + lineOffset, column: pos.column + columnOffset, index: input.index(pos.index, offsetBy: offset))
let value = parser(input, pos).value
XCTAssertNotNil(value, "should have parsed \(String(describing: input)) and advanced by \(offset). " + message, file: file, line: line)
XCTAssertEqual(value?.1, newSourcePos, "should have parsed \(String(describing: input)) and advanced by \(offset). " + message, file: file, line: line)
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: MadnessTests/ErrorTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
final class ErrorTests: XCTestCase {
func testLiftedParsersDoNotReportErrorsWhenTheyMatch() {
let parser = %"x"
let input = "x".characters
let sourcePos = SourcePos(index: input.startIndex)
XCTAssertNotNil(parser(input, sourcePos).value)
XCTAssertNil(parser(input, sourcePos).error)
}
func testLiftedParsersReportErrorsWhenTheyDoNotMatch() {
let parser = %"x"
let input = "y"
let sourcePos = SourcePos(index: input.startIndex)
XCTAssertNil(parser(input.characters, sourcePos).value)
XCTAssertNotNil(parser(input.characters, sourcePos).error)
}
func testParseError() {
XCTAssertEqual(parse(lambda, input: "λx.").error?.depth, 5)
}
func testParseNaming() {
XCTAssertNotNil(parse(describeAs("lambda")(lambda), input: "λx.").error)
}
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: MadnessTests/Fixtures.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
extension String {
public static func lift<A>(_ parser: @escaping Parser<String.CharacterView, A>.Function) -> Parser<String, A>.Function {
return {
parser($0.characters, $1)
}
}
}
/// Returns the least fixed point of the function returned by `f`.
///
/// This is useful for e.g. making recursive closures without using the two-step assignment dance.
///
/// \param f - A function which takes a parameter function, and returns a result function. The result function may recur by calling the parameter function.
///
/// \return A recursive function.
func fix<T, U>(_ f: @escaping (@escaping (T) -> U) -> (T) -> U) -> (T) -> U {
return { f(fix(f))($0) }
}
typealias LambdaParser = Parser<String, Lambda>.Function
func lambda(_ input: String, sourcePos: SourcePos<String.Index>) -> Parser<String, Lambda>.Result {
let symbol: Parser<String, String>.Function = String.lift(%("a"..."z"))
let variable: LambdaParser = Lambda.variable <^> symbol
let abstraction: LambdaParser = { x in { y in Lambda.abstraction(x, y) } } <^> (%"λ" *> symbol) <*> (%"." *> lambda)
let application: LambdaParser = { x in { y in Lambda.application(x, y) } } <^> (%"(" *> lambda) <*> (%" " *> lambda) <* %")"
let parser: LambdaParser = variable <|> abstraction <|> application
return parser(input, sourcePos)
}
enum Lambda: CustomStringConvertible {
case variable(String)
indirect case abstraction(String, Lambda)
indirect case application(Lambda, Lambda)
var description: String {
switch self {
case let .variable(symbol):
return symbol
case let .abstraction(symbol, body):
return "λ\(symbol).\(body.description)"
case let .application(x, y):
return "(\(x.description) \(y.description))"
}
}
}
import Madness
================================================
FILE: MadnessTests/IgnoreTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
final class IgnoreTests: XCTestCase {
let ignored = %"x"
func testIgnoredInputDoesNotGetConcatenatedAtLeft() {
assertTree(ignored *> %"y", "xy".characters, ==, "y")
}
func testIgnoredInputDoesNotGetConcatenatedAtRight() {
assertTree(%"y" <* ignored, "yx".characters, ==, "y")
}
func testRepeatedIgnoredEmptyParsesAreDropped() {
assertTree(many(ignored) *> %"y", "y".characters, ==, "y")
}
func testRepeatedIgnoredParsesAreDropped() {
assertTree(many(ignored) *> %"y", "xxy".characters, ==, "y")
}
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: MadnessTests/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
================================================
FILE: MadnessTests/MapTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
private struct Tree<T: Equatable>: Equatable, CustomStringConvertible {
init(_ value: T, _ children: [Tree] = []) {
self.values = [ value ]
self.children = children
}
let values: [T]
let children: [Tree]
// MARK: Printable
var description: String {
let space = " "
let valueString = values.map({ String(describing: $0) }).joined(separator: space)
return children.count > 0 ?
"(\(valueString) \(children.map({ String(describing: $0) }).joined(separator: space)))"
: "(\(valueString))"
}
}
private func == <T> (left: Tree<T>, right: Tree<T>) -> Bool {
return left.values == right.values && left.children == right.children
}
private func == <T: Equatable, U: Equatable> (l: (T, U), r: (T, U)) -> Bool {
return l.0 == r.0 && l.1 == r.1
}
final class MapTests: XCTestCase {
// MARK: flatMap
func testFlatMap() {
let item: Parser<String, String>.Function = %"-" *> String.lift(%("a"..."z")) <* %"\n"
let tree: (Int) -> Parser<String, Tree<String>>.Function = fix { tree in
{ n in
let line: Parser<String, String>.Function = (%"\t" * n) *> item
return line >>- { itemContent in
map({ children in Tree(itemContent, children) })(many(tree(n + 1)))
}
}
}
let fixtures: [String: Tree<String>] = [
"-a\n": Tree("a"),
"-a\n\t-b\n": Tree("a", [ Tree("b") ]),
"-a\n\t-b\n\t-c\n": Tree("a", [ Tree("b"), Tree("c") ]),
"-a\n\t-b\n\t\t-c\n\t-d\n": Tree("a", [ Tree("b", [ Tree("c") ]), Tree("d") ]),
]
for (input, actual) in fixtures {
if let parsed = parse(tree(0), input: input).value {
XCTAssertEqual(parsed, actual)
} else {
XCTFail("expected to parse \(input) as \(actual) but failed to parse")
}
}
let failures: [String] = [
"-a\n-a\n",
"-a\n\t\t-b\n",
"-a\n\t-b\n-c\n"
]
for input in failures {
XCTAssert(parse(tree(0), input: input).value == nil)
}
}
// MARK: map
func testMapTransformsParserOutput() {
assertTree(String.init <^> %123, [123], ==, "123")
}
func testMapHasHigherPrecedenceThanFlatMap() {
let addTwo = { $0 + 2 }
let triple = { $0 * 3 }
let parser: Parser<[Int], Int>.Function = addTwo <^> %2 >>- { i in triple <^> pure(i) }
assertTree(parser, [2], ==, 12)
}
func testReplaceConsumesItsInput() {
assertTree(lift(pair) <*> ("abc" <^ %123) <*> %0, [123, 0], ==, ("abc", 0))
}
func testCurriedMap() {
assertTree(map({ String($0) })(%123), [123], ==, "123")
}
// MARK: pure
func testPureIgnoresItsInput() {
assertTree(pure("a"), "b".characters, ==, "a")
}
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: MadnessTests/NegationTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
class NegationTests: XCTestCase {
let notA: CharacterParser = not(%"a") *> any
func testNegativeLookaheadRejectsMatches() {
assertUnmatched(notA, "a".characters)
}
func testNegativeLookaheadAcceptsNonMatches() {
assertTree(notA, "b".characters, ==, "b")
}
let upToBang: CharacterArrayParser = many(not(%"!") *> any) <* many(any)
func testNegativeLooaheadAccumulation() {
assertTree(upToBang, "xy!z".characters, ==, ["x", "y"])
}
func testNegativeLooaheadAccumulationWithoutMatch() {
assertTree(upToBang, "xyz".characters, ==, ["x", "y", "z"])
}
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: MadnessTests/ParserTests.swift
================================================
// Copyright (c) 2014 Rob Rix. All rights reserved.
import Madness
import Result
import XCTest
final class ParserTests: XCTestCase {
// MARK: - Operations
func testParseRejectsPartialParses() {
XCTAssertNil(parse(%("x".characters), input: "xy".characters).value)
}
func testParseProducesParseTreesForFullParses() {
XCTAssertEqual(parse(%"x", input: "x").value, "x")
}
// MARK: - Terminals
// MARK: Literals
func testLiteralParsersParseAPrefixOfTheInput() {
let parser = %"foo"
assertAdvancedBy(parser, input: "foot".characters, lineOffset: 0, columnOffset: 3, offset: 3)
assertUnmatched(parser, "fo".characters)
}
func testLiteralParsersProduceTheirArgument() {
assertTree(%"foo", "foot".characters, ==, "foo")
}
// MARK: Ranges
let digits = %("0"..."9")
func testRangeParsersParseAnyCharacterInTheirRange() {
assertTree(digits, "0".characters, ==, "0")
assertTree(digits, "5".characters, ==, "5")
assertTree(digits, "9".characters, ==, "9")
}
func testRangeParsersRejectCharactersOutsideTheRange() {
assertUnmatched(digits, "a".characters)
}
// MARK: None
func testNoneDoesNotConsumeItsInput() {
assertTree(none() <|> %"a", "a", ==, "a")
}
func testNoneIsIdentityForAlternation() {
let parser = [%"a", %"b", %"c"].reduce(none(), <|>)
assertTree(parser, "a".characters, ==, "a")
assertTree(parser, "b".characters, ==, "b")
assertTree(parser, "c".characters, ==, "c")
}
// MARK: Any
func testAnyRejectsTheEmptyString() {
assertUnmatched(any, "".characters)
}
func testAnyParsesAnySingleCharacter() {
assertTree(any, "🔥".characters, ==, "🔥")
}
// MARK: satisfy
func testSatisfyIncrementsLinesOverNewlineCharacters() {
let parser = any *> %"foo"
assertAdvancedBy(parser, input: "\nfoot".characters, lineOffset: 1, columnOffset: 2, offset: 4)
}
}
================================================
FILE: MadnessTests/ReductionTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
final class ReductionTests: XCTestCase {
let reduction = %"x" --> { $4.uppercased() }
func testMapsParseTreesWithAFunction() {
assertTree(reduction, "x".characters, ==, "X")
}
func testRejectsInputRejectedByItsParser() {
assertUnmatched(reduction, "y".characters)
}
enum Value { case null }
let constReduction = %"null" --> { _, _, _, _, _ in Value.null }
func testMapsConstFunctionOverInput() {
assertTree(constReduction, "null".characters, ==, Value.null)
}
let reductionWithIndex = %"x" --> { "\($4.uppercased()):\($0.distance(from: $0.startIndex, to: $3.lowerBound))..<\($0.distance(from: $0.startIndex, to: $3.upperBound))" }
func testMapsParseTreesWithAFunctionWhichTakesTheSourceIndex() {
assertTree(reductionWithIndex, "x".characters, ==, "X:0..<1")
}
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: MadnessTests/RepetitionTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
final class RepetitionTests: XCTestCase {
let zeroOrMore: Parser<String.CharacterView, [String]>.Function = many(%"x")
func testZeroOrMoreRepetitionAcceptsTheEmptyString() {
assertMatched(zeroOrMore, input: "".characters)
}
func testZeroOrMoreRepetitionAcceptsUnmatchedStrings() {
assertMatched(zeroOrMore, input: "y".characters)
}
func testZeroOrMoreRepetitionDoesNotAdvanceWithUnmatchedStrings() {
assertAdvancedBy(zeroOrMore, input: "y".characters, offset: 0)
}
func testZeroOrMoreRepetitionParsesUnmatchedStringsAsEmptyArrays() {
assertTree(zeroOrMore, "y".characters, ==, [])
}
func testZeroOrMoreRepetitionParsesAMatchedString() {
assertTree(zeroOrMore, "x".characters, ==, ["x"])
}
func testZeroOrMoreRepetitionParsesMatchedStrings() {
assertTree(zeroOrMore, "xx".characters, ==, ["x", "x"])
}
let oneOrMore = some(%"x")
func testOneOrMoreRepetitionRejectsTheEmptyString() {
assertUnmatched(oneOrMore, "".characters)
}
func testOneOrMoreRepetitionParsesASingleMatchedString() {
assertTree(oneOrMore, "x".characters, ==, ["x"])
}
func testOneOrMoreRepetitonParsesMultipleMatchedStrings() {
assertTree(oneOrMore, "xxy".characters, ==, ["x", "x"])
}
let exactlyN = %"x" * 3
func testExactlyNRepetitionParsesNTrees() {
assertTree(exactlyN, "xxx".characters, ==, ["x", "x", "x"])
}
func testExactlyNRepetitionParsesRejectsFewerMatches() {
assertUnmatched(exactlyN, "xx".characters)
}
func testExactlyNRepetitionParsesStopsAtN() {
assertAdvancedBy(exactlyN, input: "xxxx".characters, lineOffset: 0, columnOffset: 3, offset: 3)
}
let zeroToN = %"x" * (0..<2)
func testZeroToNRepetitionParsesZeroTrees() {
assertTree(zeroToN, "y".characters, ==, [])
}
func testZeroToNRepetitionParsesUpToButNotIncludingNTrees() {
assertTree(zeroToN, "xxx".characters, ==, ["x"])
assertAdvancedBy(zeroToN, input: "xxx".characters, lineOffset: 0, columnOffset: 1, offset: 1)
}
let atLeastN = %"x" * (2..<Int.max)
func testAtLeastNRepetitionRejectsZeroTrees() {
assertUnmatched(atLeastN, "y".characters)
}
func testAtLeastNRepetitionParsesNTrees() {
assertTree(atLeastN, "xx".characters, ==, ["x", "x"])
}
func testAtLeastNRepetitionParsesMoreThanNTrees() {
assertTree(atLeastN, "xxxx".characters, ==, ["x", "x", "x", "x"])
}
let mToN = %"x" * (2..<3)
func testMToNRepetitionRejectsLessThanM() {
assertUnmatched(mToN, "x".characters)
}
func testMToNRepetitionMatchesUpToButNotIncludingN() {
assertAdvancedBy(mToN, input: "xxxx".characters, lineOffset: 0, columnOffset: 2, offset: 2)
}
let nToN = %"x" * (2..<2)
func testOpenNToNRepetitionRejectsN() {
assertUnmatched(nToN, "xx".characters)
}
let zeroToNClosed = %"x" * (0...2)
func testZeroToNClosedRepetitionParsesZeroTrees() {
assertTree(zeroToNClosed, "y".characters, ==, [])
}
func testZeroToNClosedRepetitionParsesUpToNTrees() {
assertTree(zeroToNClosed, "xxx".characters, ==, ["x", "x"])
assertAdvancedBy(zeroToNClosed, input: "xxx".characters, lineOffset: 0, columnOffset: 2, offset: 2)
}
let atLeastNClosed = %"x" * (2...Int.max)
func testAtLeastNClosedRepetitionRejectsZeroTrees() {
assertUnmatched(atLeastNClosed, "y".characters)
}
func testAtLeastNClosedRepetitionParsesNTrees() {
assertTree(atLeastNClosed, "xx".characters, ==, ["x", "x"])
}
func testAtLeastNClosedRepetitionParsesMoreThanNTrees() {
assertTree(atLeastNClosed, "xxxx".characters, ==, ["x", "x", "x", "x"])
}
let mToNClosed = %"x" * (2...3)
func testMToNClosedRepetitionRejectsLessThanM() {
assertUnmatched(mToNClosed, "x".characters)
}
func testMToNClosedRepetitionMatchesUpToN() {
assertAdvancedBy(mToNClosed, input: "xxxx".characters, lineOffset: 0, columnOffset: 3, offset: 3)
}
let closedNToN = %"x" * (2...2)
func testClosedNToNRepetitionMatchesUpToN() {
assertAdvancedBy(closedNToN, input: "xxx".characters, lineOffset: 0, columnOffset: 2, offset: 2)
}
// MARK: Repetition shorthand
let zeroOrMoreSimple = many(%"x")
func testZeroOrMoreSimpleRepetitionAcceptsTheEmptyString() {
assertMatched(zeroOrMoreSimple, input: "".characters)
}
func testZeroOrMoreSimpleRepetitionAcceptsUnmatchedStrings() {
assertMatched(zeroOrMoreSimple, input: "y".characters)
}
func testZeroOrMoreSimpleRepetitionDoesNotAdvanceWithUnmatchedStrings() {
assertAdvancedBy(zeroOrMoreSimple, input: "y".characters, offset: 0)
}
func testZeroOrMoreSimpleRepetitionParsesUnmatchedStringsAsEmptyArrays() {
assertTree(zeroOrMoreSimple, "y".characters, ==, [])
}
func testZeroOrMoreSimpleRepetitionParsesAMatchedString() {
assertTree(zeroOrMoreSimple, "x".characters, ==, ["x"])
}
func testZeroOrMoreSimpleRepetitionParsesMatchedStrings() {
assertTree(zeroOrMoreSimple, "xx".characters, ==, ["x", "x"])
}
let oneOrMoreSimple = some(%"x")
func testOneOrMoreSimpleRepetitionRejectsTheEmptyString() {
assertUnmatched(oneOrMoreSimple, "".characters)
}
func testOneOrMoreSimpleRepetitionParsesASingleMatchedString() {
assertTree(oneOrMoreSimple, "x".characters, ==, ["x"])
}
func testOneOrMoreSimpleRepetitonParsesMultipleMatchedStrings() {
assertTree(oneOrMoreSimple, "xxy".characters, ==, ["x", "x"])
}
let zeroOrMoreLookAhead = many(not(%"x"))
func testZeroOrMoreSkipsLookAhead() {
assertTree(zeroOrMoreLookAhead, "yyy".characters, ==, [])
}
let oneOrMoreLookAhead = some(not(%"x"))
func testOneOrMoreFailsLookAhead() {
assertUnmatched(oneOrMoreLookAhead, "yyy".characters)
}
// MARK: - endBy1
let numbers = endBy1(digit, %".")
func testOneOrMoreRepetitionWithEndRejectsTheEmptyString() {
assertUnmatched(numbers, "".characters)
}
func testOneOrMoreRepetitionWithEndParsesASingleMatchedString() {
assertTree(numbers, "0.".characters, ==, ["0"])
}
func testOneOrMoreRepetitionWithEndParsesMultipleMatchedStrings() {
assertTree(numbers, "0.1.2.".characters, ==, ["0", "1", "2"])
}
// MARK: - endBy
let numbers2 = endBy(digit, %".")
func testZeroOrMoreRepetitionWithEndAcceptsTheEmptyString() {
assertMatched(numbers2, input: "".characters)
}
func testZeroOrMoreRepetitionWithEndParsesASingleMatchedString() {
assertTree(numbers2, "0.".characters, ==, ["0"])
}
func testZeroOrMoreRepetitionWithEndParsesMultipleMatchedStrings() {
assertTree(numbers2, "0.1.2.".characters, ==, ["0", "1", "2"])
}
}
private func == (left: [()], right: [()]) -> Bool {
return left.count == right.count
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: MadnessTests/StringTests.swift
================================================
// Copyright (c) 2015 Rob Rix. All rights reserved.
final class StringTests: XCTestCase {
func testSimpleIntegers() {
assertNumber("1")
assertNumber("45")
assertNumber("-13")
}
func testSimpleFloats() {
assertNumber("1.0")
assertNumber("45.3")
assertNumber("-2.53")
}
func testIntegerUnsignedExponents() {
assertNumber("2E1")
assertNumber("1e2")
assertNumber("0e3")
assertNumber("-1e4")
assertNumber("-2E5")
assertNumber("1e21")
}
func testIntegerSignedExponents() {
assertNumber("8e+1")
assertNumber("7e-2")
assertNumber("6E+3")
assertNumber("5E-4")
assertNumber("-4e+5")
assertNumber("-3e-6")
assertNumber("-2E+7")
assertNumber("-1E-8")
}
func testFloatUnsignedExponents() {
assertNumber("1.2e1")
assertNumber("4.567E2")
assertNumber("1.0e4")
assertNumber("-6.21e3")
assertNumber("-1.5E2")
}
func testFloatSignedExponents() {
assertNumber("1.4e+5")
assertNumber("2.5e-6")
assertNumber("3.6E+7")
assertNumber("4.7E-8")
assertNumber("-5.8E-9")
}
}
func assertNumber(_ input: String, message: String = "", file: StaticString = #file, line: UInt = #line) {
return XCTAssertEqual(parse(number, input: input).value, Double(input)!, message, file: file, line: line)
}
// MARK: - Imports
import Madness
import XCTest
================================================
FILE: README.md
================================================
# Recursive Descent into Madness
Madness is a Swift µframework for parsing strings in simple context-free grammars. Combine parsers from simple Swift expressions and parse away:
```swift
let digit = %("0"..."9") <|> %("a"..."f") <|> %("A"..."F")
let hex = digit+ |> map { strtol(join("", $0), nil, 16) }
parse(%"0x" *> hex, "0xdeadbeef") // => 3,735,928,559
```
Your parsers can produce your own model objects directly, making Madness ideal for experimenting with grammars, for example in a playground.

See `Madness.playground` for some examples of parsing with Madness.
## Use
- **Lexing**
Madness can be used to write lexers, lexeme parsers, and scannerless parsers. @bencochran has built a [lexer and parser for the LLVM tutorial language, Kaleidoscope](https://github.com/bencochran/KaleidoscopeLang).
- **Any**
```swift
any
```
parses any single character.
- **Strings**
```swift
%"hello"
```
parses the string “hello”.
- **Ranges**
```swift
%("a"..."z")
```
parses any lowercase letter from “a” to “z” inclusive.
- **Concatenation**
```swift
x <*> y <*> z
```
parses `x` followed by `y` and produces parses as `(X, Y)`.
- **Alternation**
```swift
x <|> y
```
parses `x`, and if it fails, `y`, and produces parses as `Either<X, Y>`. If `x` and `y` are of the same type, then it produces parses as `X`.
```swift
oneOf([x1, x2, x3])
```
tries a sequence of parsers until the first success, producing parses as `X`.
```swift
anyOf(["x", "y", "z"])
```
tries to parse one each of a set of literals in sequence, collecting each successful parse into an array until none match.
```swift
allOf(["x", "y", "z"])
```
greedier than `anyOf`, parsing every match from a set of literals in sequence, including duplicates.
- **Repetition**
```swift
x*
```
parses `x` 0 or more times, producing parses as `[X]`.
```swift
x+
```
parses `x` one or more times.
```swift
x * 3
```
parses `x` exactly three times.
```swift
x * (3..<6)
```
parses `x` three to five times. Use `Int.max` for the upper bound to parse three or more times.
- **Mapping**
```swift
x |> map { $0 }
{ $0 } <^> x
x --> { _, _, y in y }
```
parses `x` and maps its parse trees using the passed function. Use mapping to build your model objects. `-->` passes the input and parsed range as well as the parsed data for e.g. error reporting or AST construction.
- **Ignoring**
Some text is just decoration. `x *> y` parses `x` and then `y` just like `<*>`, but drops the result of `x`. `x <* y` does the same, but drops the result of `y`.
API documentation is in the source.
## This way Madness lies
### ∞ loop de loops
Madness employs simple—naïve, even—recursive descent parsing. Among other things, that means that it can’t parse any arbitrary grammar that you could construct with it. In particular, it can’t parse left-recursive grammars:
```swift
let number = %("0"..."9")
let addition = expression <*> %"+" <*> expression
let expression = addition <|> number
```
`expression` is left-recursive: its first term is `addition`, whose first term is `expression`. This will cause infinite loops every time `expression` is invoked; try to avoid it.
### I love ambiguity more than [@numist](https://twitter.com/numist/status/423722622031908864)
Alternations try their left operand before their operand, and are short-circuiting. This means that they disambiguate (arbitrarily) to the left, which can be handy; but this can have unintended consequences. For example, this parser:
```swift
%"x" <|> %"xx"
```
will not parse “xx” completely.
## Integration
1. Add this repository as a submodule and check out its dependencies, and/or [add it to your Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile) if you’re using [carthage](https://github.com/Carthage/Carthage/) to manage your dependencies.
2. Drag `Madness.xcodeproj` into your project or workspace, and do the same with its dependencies (i.e. the other `.xcodeproj` files included in `Madness.xcworkspace`). NB: `Madness.xcworkspace` is for standalone development of Madness, while `Madness.xcodeproj` is for targets using Madness as a dependency.
3. Link your target against `Madness.framework` and each of the dependency frameworks.
4. Application targets should ensure that the framework gets copied into their application bundle. (Framework targets should instead require the application linking them to include Madness and its dependencies.)
================================================
FILE: script/cibuild
================================================
#!/bin/bash
BUILD_DIRECTORY="build"
CONFIGURATION=Release
if [[ -z $TRAVIS_XCODE_WORKSPACE ]]; then
echo "Error: \$TRAVIS_XCODE_WORKSPACE is not set."
exit 1
fi
if [[ -z $TRAVIS_XCODE_SCHEME ]]; then
echo "Error: \$TRAVIS_XCODE_SCHEME is not set!"
exit 1
fi
if [[ -z $XCODE_ACTION ]]; then
echo "Error: \$XCODE_ACTION is not set!"
exit 1
fi
if [[ -z $XCODE_SDK ]]; then
echo "Error: \$XCODE_SDK is not set!"
exit 1
fi
if [[ -z $XCODE_DESTINATION ]]; then
echo "Error: \$XCODE_DESTINATION is not set!"
exit 1
fi
set -o pipefail
xcodebuild $XCODE_ACTION \
-workspace "$TRAVIS_XCODE_WORKSPACE" \
-scheme "$TRAVIS_XCODE_SCHEME" \
-sdk "$XCODE_SDK" \
-destination "$XCODE_DESTINATION" \
-derivedDataPath "${BUILD_DIRECTORY}" \
-configuration $CONFIGURATION \
ENABLE_TESTABILITY=YES \
GCC_GENERATE_DEBUGGING_SYMBOLS=NO \
RUN_CLANG_STATIC_ANALYZER=NO | xcpretty
result=$?
if [ "$result" -ne 0 ]; then
exit $result
fi
# Compile code in playgrounds
if [[ -n $XCODE_PLAYGROUND ]]; then
echo "Validating playground..."
. script/validate-playground.sh
fi
================================================
FILE: script/validate-playground.sh
================================================
#!/bin/bash
# Bash script to lint the content of playgrounds
# Heavily based on RxSwift's
# https://github.com/ReactiveX/RxSwift/blob/master/scripts/validate-playgrounds.sh
if [ -z "$BUILD_DIRECTORY" ]; then
echo "\$BUILD_DIRECTORY is not set. Are you trying to run \`validate-playgrounds.sh\` without building Logician first?\n"
echo "To validate the playground, run \`script/build\`."
exit 1
fi
if [ -z "$XCODE_PLAYGROUND" ]; then
echo "\$XCODE_PLAYGROUND is not set."
exit 1
fi
PAGES_PATH=${BUILD_DIRECTORY}/Build/Products/${CONFIGURATION}/all-playground-pages.swift
cat ${XCODE_PLAYGROUND}/Sources/*.swift ${XCODE_PLAYGROUND}.playground/Pages/**/*.swift > ${PAGES_PATH}
swift -v -target "x86_64-apple-macosx10.10" -D NOT_IN_PLAYGROUND -F ${BUILD_DIRECTORY}/Build/Products/${CONFIGURATION} ${PAGES_PATH} > /dev/null
result=$?
# Cleanup
rm -Rf $BUILD_DIRECTORY
exit $result
gitextract_t4_kha8o/
├── .gitignore
├── .gitmodules
├── .travis.yml
├── Cartfile
├── Cartfile.resolved
├── Documentation/
│ ├── Collections.playground/
│ │ ├── Contents.swift
│ │ └── contents.xcplayground
│ ├── Colours.playground/
│ │ ├── Contents.swift
│ │ └── contents.xcplayground
│ ├── Lambda Calculus.playground/
│ │ ├── Contents.swift
│ │ └── contents.xcplayground
│ └── Subset of Common Markdown.playground/
│ ├── Contents.swift
│ └── contents.xcplayground
├── LICENSE
├── Madness/
│ ├── Alternation.swift
│ ├── Combinator.swift
│ ├── Concatenation.swift
│ ├── Error.swift
│ ├── Info.plist
│ ├── Madness.h
│ ├── Map.swift
│ ├── Negation.swift
│ ├── Parser.swift
│ ├── Reduction.swift
│ ├── Repetition.swift
│ ├── SourcePos.swift
│ └── String.swift
├── Madness.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── xcshareddata/
│ └── xcschemes/
│ ├── Madness-Mac.xcscheme
│ └── Madness-iOS.xcscheme
├── Madness.xcworkspace/
│ └── contents.xcworkspacedata
├── MadnessTests/
│ ├── AlternationTests.swift
│ ├── CollectionTests.swift
│ ├── CombinatorTests.swift
│ ├── ConcatenationTests.swift
│ ├── ErrorTests.swift
│ ├── Fixtures.swift
│ ├── IgnoreTests.swift
│ ├── Info.plist
│ ├── MapTests.swift
│ ├── NegationTests.swift
│ ├── ParserTests.swift
│ ├── ReductionTests.swift
│ ├── RepetitionTests.swift
│ └── StringTests.swift
├── README.md
└── script/
├── cibuild
└── validate-playground.sh
Condensed preview — 49 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (127K chars).
[
{
"path": ".gitignore",
"chars": 102,
"preview": ".DS_Store\nbuild\nxcuserdata\n*.mode*\n*.pbxuser\n*.xcuserdatad\n*.xccheckout\n*.xcscmblueprint\n*.xctimeline\n"
},
{
"path": ".gitmodules",
"chars": 123,
"preview": "[submodule \"Carthage/Checkouts/Result\"]\n\tpath = Carthage/Checkouts/Result\n\turl = https://github.com/antitypical/Result.g"
},
{
"path": ".travis.yml",
"chars": 1555,
"preview": "language: objective-c\nosx_image: xcode9\nbranches:\n only:\n - master\nxcode_workspace: Madness.xcworkspace\nscript:\n - "
},
{
"path": "Cartfile",
"chars": 37,
"preview": "github \"antitypical/Result\" ~> 3.2.4\n"
},
{
"path": "Cartfile.resolved",
"chars": 36,
"preview": "github \"antitypical/Result\" \"3.2.4\"\n"
},
{
"path": "Documentation/Collections.playground/Contents.swift",
"chars": 374,
"preview": "import Madness\nimport Result\n\nlet input = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]\n\ntypealias Fibonacci = Parser<[Int], "
},
{
"path": "Documentation/Collections.playground/contents.xcplayground",
"chars": 316,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<playground version='3.0' sdk='macosx' auto-termination-delay='5"
},
{
"path": "Documentation/Colours.playground/Contents.swift",
"chars": 944,
"preview": "import Cocoa\nimport Darwin\nimport Madness\n\nfunc toComponent(_ string: String) -> CGFloat {\n return CGFloat(strtol(strin"
},
{
"path": "Documentation/Colours.playground/contents.xcplayground",
"chars": 184,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<playground version='5.0' sdk='macosx' auto-termination-delay='4"
},
{
"path": "Documentation/Lambda Calculus.playground/Contents.swift",
"chars": 1216,
"preview": "import Madness\n\nindirect enum Lambda: CustomStringConvertible {\n\tcase variable(String)\n\tcase abstraction(String, Lambda)"
},
{
"path": "Documentation/Lambda Calculus.playground/contents.xcplayground",
"chars": 316,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<playground version='3.0' sdk='macosx' auto-termination-delay='5"
},
{
"path": "Documentation/Subset of Common Markdown.playground/Contents.swift",
"chars": 2208,
"preview": "import Madness\n\n// MARK: - Lexing rules\n\nlet newline = %\"\\n\"\nlet ws = %\" \" <|> %\"\\t\"\nlet lower = %(\"a\"...\"z\")\nlet upper "
},
{
"path": "Documentation/Subset of Common Markdown.playground/contents.xcplayground",
"chars": 289,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<playground version='3.0' sdk='macosx'>\n <sections>\n <"
},
{
"path": "LICENSE",
"chars": 1073,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Rob Rix\n\nPermission is hereby granted, free of charge, to any person obtaining"
},
{
"path": "Madness/Alternation.swift",
"chars": 2406,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\n/// Parses `parser` 0 or one time.\npublic postfix func |? <C: Coll"
},
{
"path": "Madness/Combinator.swift",
"chars": 647,
"preview": "// Copyright © 2015 Rob Rix. All rights reserved.\n\n/// Parses `open`, followed by `parser` and `close`. Returns the val"
},
{
"path": "Madness/Concatenation.swift",
"chars": 1149,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nimport Result\n\nprecedencegroup ConcatenationPrecedence {\n\tassociat"
},
{
"path": "Madness/Error.swift",
"chars": 2214,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nimport Result\n\n/// A composite error.\npublic enum Error<I: Compara"
},
{
"path": "Madness/Info.plist",
"chars": 910,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "Madness/Madness.h",
"chars": 223,
"preview": "// Copyright (c) 2014 Rob Rix. All rights reserved.\n\n/// Project version number for Madness.\nextern double MadnessVersi"
},
{
"path": "Madness/Map.swift",
"chars": 2402,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\n// MARK: - flatMap\n\n/// Returns a parser which requires `parser` t"
},
{
"path": "Madness/Negation.swift",
"chars": 534,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\n/// This parser succeeds iff `parser` fails. This parser does not "
},
{
"path": "Madness/Parser.swift",
"chars": 5410,
"preview": "// Copyright (c) 2014 Rob Rix. All rights reserved.\n\n// Swift has no way to resolve to `Result.Result` inside `Parser.R"
},
{
"path": "Madness/Reduction.swift",
"chars": 885,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\n/// Returns a parser which maps parse trees into another type.\npub"
},
{
"path": "Madness/Repetition.swift",
"chars": 4157,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\n/// Parser `parser` 1 or more times.\npublic func some<C: Collectio"
},
{
"path": "Madness/SourcePos.swift",
"chars": 2013,
"preview": "// Copyright (c) 2014 Josh Vera. All rights reserved.\n\npublic typealias Line = Int\npublic typealias Column = Int\n\nvar D"
},
{
"path": "Madness/String.swift",
"chars": 2295,
"preview": "//\n// String.swift\n// Madness\n//\n// Created by Josh Vera on 10/19/15.\n// Copyright © 2015 Rob Rix. All rights reserv"
},
{
"path": "Madness.xcodeproj/project.pbxproj",
"chars": 39998,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "Madness.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 152,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:Madness.xcodepr"
},
{
"path": "Madness.xcodeproj/xcshareddata/xcschemes/Madness-Mac.xcscheme",
"chars": 4298,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0900\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "Madness.xcodeproj/xcshareddata/xcschemes/Madness-iOS.xcscheme",
"chars": 4298,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0900\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "Madness.xcworkspace/contents.xcworkspacedata",
"chars": 693,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <Group\n location = \"container:Documentatio"
},
{
"path": "MadnessTests/AlternationTests.swift",
"chars": 2611,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nfinal class AlternationTests: XCTestCase {\n\n\t// MARK: Alternation\n"
},
{
"path": "MadnessTests/CollectionTests.swift",
"chars": 572,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nfinal class CollectionTests: XCTestCase {\n\tfunc testParsingCollect"
},
{
"path": "MadnessTests/CombinatorTests.swift",
"chars": 753,
"preview": "// Copyright © 2015 Rob Rix. All rights reserved.\n\nfinal class CombinatorTests: XCTestCase {\n\t\n\t// MARK: - between\n\t\n\tl"
},
{
"path": "MadnessTests/ConcatenationTests.swift",
"chars": 3472,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nfinal class ConcatenationTests: XCTestCase {\n\tlet concatenation = "
},
{
"path": "MadnessTests/ErrorTests.swift",
"chars": 872,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nfinal class ErrorTests: XCTestCase {\n\tfunc testLiftedParsersDoNotR"
},
{
"path": "MadnessTests/Fixtures.swift",
"chars": 1786,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nextension String {\n\tpublic static func lift<A>(_ parser: @escaping"
},
{
"path": "MadnessTests/IgnoreTests.swift",
"chars": 625,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nfinal class IgnoreTests: XCTestCase {\n\tlet ignored = %\"x\"\n\n\tfunc t"
},
{
"path": "MadnessTests/Info.plist",
"chars": 733,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "MadnessTests/MapTests.swift",
"chars": 2629,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nprivate struct Tree<T: Equatable>: Equatable, CustomStringConverti"
},
{
"path": "MadnessTests/NegationTests.swift",
"chars": 678,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nclass NegationTests: XCTestCase {\n\tlet notA: CharacterParser = not"
},
{
"path": "MadnessTests/ParserTests.swift",
"chars": 1838,
"preview": "// Copyright (c) 2014 Rob Rix. All rights reserved.\n\nimport Madness\nimport Result\nimport XCTest\n\nfinal class ParserTest"
},
{
"path": "MadnessTests/ReductionTests.swift",
"chars": 896,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nfinal class ReductionTests: XCTestCase {\n\tlet reduction = %\"x\" -->"
},
{
"path": "MadnessTests/RepetitionTests.swift",
"chars": 6558,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nfinal class RepetitionTests: XCTestCase {\n\tlet zeroOrMore: Parser<"
},
{
"path": "MadnessTests/StringTests.swift",
"chars": 1294,
"preview": "// Copyright (c) 2015 Rob Rix. All rights reserved.\n\nfinal class StringTests: XCTestCase {\n\tfunc testSimpleIntegers() {"
},
{
"path": "README.md",
"chars": 4718,
"preview": "# Recursive Descent into Madness\n\nMadness is a Swift µframework for parsing strings in simple context-free grammars. Com"
},
{
"path": "script/cibuild",
"chars": 1141,
"preview": "#!/bin/bash\n\nBUILD_DIRECTORY=\"build\"\nCONFIGURATION=Release\n\nif [[ -z $TRAVIS_XCODE_WORKSPACE ]]; then\n echo \"Error: \\"
},
{
"path": "script/validate-playground.sh",
"chars": 904,
"preview": "#!/bin/bash\n\n# Bash script to lint the content of playgrounds\n# Heavily based on RxSwift's\n# https://github.com/Reactive"
}
]
About this extraction
This page contains the full source code of the robrix/Madness GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 49 files (112.8 KB), approximately 36.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.