├── .circleci └── config.yml ├── .dockerignore ├── .gitignore ├── .swift-version ├── .travis.yml ├── Dockerfile ├── LICENSE ├── Makefile ├── Package.resolved ├── Package.swift ├── ParserPrinter.playground ├── Pages │ ├── Stock Ticker.xcplaygroundpage │ │ └── Contents.swift │ └── URL Router.xcplaygroundpage │ │ └── Contents.swift └── contents.xcplayground ├── ParserPrinter.xcodeproj ├── GeneratePartialIsosTests_Info.plist ├── GeneratePartialIsos_Info.plist ├── Monoid_Info.plist ├── PartialIsoTests_Info.plist ├── PartialIso_Info.plist ├── SnapshotTesting_Info.plist ├── SwiftSyntax_Info.plist ├── SyntaxTests_Info.plist ├── Syntax_Info.plist ├── URLRequestRouterTests_Info.plist ├── URLRequestRouter_Info.plist ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ └── xcschemes │ ├── ParserPrinter-Package.xcscheme │ └── generate-partial-isos.xcscheme ├── ParserPrinter.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── README.md ├── Sources ├── GeneratePartialIsos │ └── GeneratePartialIsos.swift ├── PartialIso │ ├── ExpressibleByStringLiteral.swift │ ├── Flatten.swift │ └── PartialIso.swift ├── Syntax │ ├── Numeric.swift │ ├── String.swift │ └── Syntax.swift ├── URLRequestRouter │ ├── RequestData.swift │ └── URLRequestRouter.swift └── generate-partial-isos │ └── main.swift └── Tests ├── GeneratePartialIsosTests ├── Fixture.swift ├── GeneratePartialIsosTests.swift ├── XCTestManifests.swift └── __Snapshots__ │ └── GeneratePartialIsosTests │ └── test.1.swift ├── LinuxMain.swift ├── PartialIsoTests ├── PartialIsoTests.swift └── XCTestManifests.swift ├── SyntaxTests ├── SyntaxTests.swift └── XCTestManifests.swift └── URLRequestRouterTests ├── URLRequestRouterTests.swift └── XCTestManifests.swift /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | build: 5 | macos: 6 | xcode: "10.1.0" 7 | 8 | steps: 9 | - checkout 10 | 11 | - restore_cache: 12 | keys: 13 | - pre-build-cache-{{ .Branch }} 14 | - pre-derivedData-cache-{{ .Branch }} 15 | 16 | - run: 17 | name: Mac info 18 | command: system_profiler SPSoftwareDataType 19 | 20 | - run: 21 | name: Run Swift tests 22 | command: make test-swift 23 | environment: 24 | SNAPSHOT_ARTIFACTS: /tmp/__SnapshotArtifacts__ 25 | 26 | - run: 27 | name: Run macOS tests 28 | command: make test-macos 29 | environment: 30 | SNAPSHOT_ARTIFACTS: /tmp/__SnapshotArtifacts__ 31 | 32 | - run: 33 | name: Run playground tests 34 | command: make test-playgrounds 35 | 36 | - store_artifacts: 37 | path: /tmp/__SnapshotArtifacts__ 38 | 39 | - save_cache: 40 | key: pre-build-cache-{{ .Branch }} 41 | paths: 42 | - ".build" 43 | 44 | - save_cache: 45 | key: pre-derivedData-cache-{{ .Branch }} 46 | paths: 47 | - ".derivedData" 48 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .build/ 3 | !.build/checkouts/ 4 | !.build/repositories/ 5 | !.build/workspace-state.json 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | .derivedData/ 44 | 45 | # CocoaPods 46 | # 47 | # We recommend against adding the Pods directory to your .gitignore. However 48 | # you should judge for yourself, the pros and cons are mentioned at: 49 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 50 | # 51 | # Pods/ 52 | 53 | # Carthage 54 | # 55 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 56 | # Carthage/Checkouts 57 | 58 | Carthage/Build 59 | 60 | # fastlane 61 | # 62 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 63 | # screenshots whenever they are needed. 64 | # For more information about the recommended setup visit: 65 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 66 | 67 | fastlane/report.xml 68 | fastlane/Preview.html 69 | fastlane/screenshots/**/*.png 70 | fastlane/test_output 71 | .DS_Store -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.2.1 -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | env: 4 | language: generic 5 | sudo: required 6 | dist: trusty 7 | install: 8 | - if [ $TRAVIS_OS_NAME = linux ]; then 9 | eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"; 10 | fi 11 | cache: 12 | directories: 13 | - .build 14 | matrix: 15 | include: 16 | - script: 17 | - make test-swift 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM swift:4.2 2 | 3 | WORKDIR /package 4 | 5 | COPY . ./ 6 | 7 | RUN swift package resolve 8 | RUN swift package clean 9 | CMD swift test --parallel 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Brandon Williams 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | XCPRETTY := $(if $(shell command -v xcpretty 2> /dev/null),xcpretty,cat) 2 | 3 | generate-xcodeproj: 4 | swift package generate-xcodeproj 5 | 6 | xcodeproj: generate-xcodeproj 7 | xed . 8 | 9 | test-linux: 10 | docker build --tag parser-printer . \ 11 | && docker run --rm parser-printer 12 | 13 | test-swift: 14 | swift test 15 | 16 | test-macos: generate-xcodeproj 17 | set -o pipefail && \ 18 | xcodebuild test \ 19 | -scheme ParserPrinter-Package \ 20 | -destination platform="macOS" \ 21 | -derivedDataPath ./.derivedData \ 22 | | $(XCPRETTY) 23 | 24 | test-ios: generate-xcodeproj 25 | set -o pipefail && \ 26 | xcodebuild test \ 27 | -scheme ParserPrinter-Package \ 28 | -destination platform="iOS Simulator,name=iPhone XR,OS=12.0" \ 29 | -derivedDataPath ./.derivedData \ 30 | | $(XCPRETTY) 31 | 32 | test-playgrounds: test-macos 33 | # this isn't right... 34 | find . \ 35 | -path '*.playground/Pages/*.xcplaygroundpage/*' \ 36 | -name '*.swift' \ 37 | -exec swift -F .derivedData/Build/Products/Debug/ -suppress-warnings {} + 38 | 39 | test-all: test-linux test-macos test-ios test-playgrounds 40 | 41 | clean: 42 | rm -rf .build/ 43 | rm -rf .derivedData 44 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "Monoid", 6 | "repositoryURL": "https://github.com/pointfreeco/swift-algebras", 7 | "state": { 8 | "branch": "monoid", 9 | "revision": "542267d903c8f745994555b890a2c3c54acfb256", 10 | "version": null 11 | } 12 | }, 13 | { 14 | "package": "SnapshotTesting", 15 | "repositoryURL": "https://github.com/pointfreeco/swift-snapshot-testing.git", 16 | "state": { 17 | "branch": "0ea1b40", 18 | "revision": "0ea1b40921766767856790fae046f57ce489b922", 19 | "version": null 20 | } 21 | } 22 | ] 23 | }, 24 | "version": 1 25 | } 26 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.2 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "ParserPrinter", 7 | products: [ 8 | .library(name: "PartialIso", targets: ["PartialIso"]), 9 | .library(name: "Syntax", targets: ["Syntax"]), 10 | .library(name: "URLRequestRouter", targets: ["URLRequestRouter"]), 11 | ], 12 | dependencies: [ 13 | .package(url: "https://github.com/pointfreeco/swift-algebras", .branch("monoid")), 14 | .package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", .revision("0ea1b40")), 15 | ], 16 | targets: [ 17 | .target( 18 | name: "PartialIso", 19 | dependencies: []), 20 | .testTarget( 21 | name: "PartialIsoTests", 22 | dependencies: ["PartialIso"]), 23 | .target( 24 | name: "Syntax", 25 | dependencies: ["Monoid", "PartialIso"]), 26 | .testTarget( 27 | name: "SyntaxTests", 28 | dependencies: ["Syntax"]), 29 | .target( 30 | name: "URLRequestRouter", 31 | dependencies: ["Monoid", "PartialIso", "Syntax"]), 32 | .testTarget( 33 | name: "URLRequestRouterTests", 34 | dependencies: ["URLRequestRouter"]), 35 | ] 36 | ) 37 | -------------------------------------------------------------------------------- /ParserPrinter.playground/Pages/Stock Ticker.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Monoid 3 | import PartialIso 4 | import Syntax 5 | 6 | // Inspired by https://github.com/Flight-School/RegularExpressionDecoder 7 | // Let's build a parser for stock prices that are stored in plain text. 8 | 9 | // This is the data structure that we want to parse into and print from. For 10 | // example, the string "AAPL 170.69▲0.51" would parse into the value 11 | // 12 | // Stock{symbol: AAPL, price: 170.69, sign: .gain, .change: 0.51} 13 | // 14 | // and then that value would print back into the string "AAPL 170.69▲0.51". 15 | struct Stock { 16 | let symbol: String 17 | let price: Double 18 | let sign: Sign 19 | let change: Double 20 | 21 | enum Sign: String, CaseIterable { 22 | case gain = "▲" 23 | case unchanged = "=" 24 | case loss = "▼" 25 | } 26 | } 27 | 28 | // Some domain specific syntaxes for dealing with stocker symbol and sign. 29 | let symbol = Syntax.string(until: { $0 == " " }) 30 | let sign: Syntax = (Syntax.string(length: 1)).map(.rawRepresentable) 31 | 32 | // A syntax for a single ticker line 33 | let stockSyntax = ( 34 | symbol <%> .optWs <%> .double <%> sign <%> .double 35 | ) 36 | .flatten( 37 | Stock.init(symbol:price:sign:change:), 38 | { ($0.symbol, $0.price, $0.sign, $0.change) } 39 | ) 40 | 41 | // Try running the syntax on a few sample stock strings. 42 | stockSyntax.run("AAPL 170.69▲0.51") 43 | stockSyntax.run("GOOG 1122.57▲2.41") 44 | stockSyntax.run("AMZN 1621.48▼18.52") 45 | stockSyntax.run("MSFT 106.57=0.00") 46 | 47 | // Try printing a strock string from a Stock value. 48 | stockSyntax.print(Stock(symbol: "FB", price: 100, sign: .loss, change: 90)) 49 | 50 | // A syntax for a full ticker by combining multiple stock syntaxes separated by newlines. 51 | let tickerSyntax = Syntax.many(stockSyntax, separatedBy: .lit("\n")) 52 | 53 | // Parse an entire ticker stream. 54 | tickerSyntax.parse(""" 55 | AAPL 170.69▲0.51 56 | GOOG 1122.57▲2.41 57 | AMZN 1621.48▼18.52 58 | MSFT 106.57=0.00 59 | """) 60 | 61 | // Parse and then print the ticker stream to make sure we get the same thing back. 62 | print( 63 | tickerSyntax.print( 64 | tickerSyntax.parse(""" 65 | AAPL 170.69▲0.51 66 | GOOG 1122.57▲2.41 67 | AMZN 1621.48▼18.52 68 | MSFT 106.57=0.00 69 | """)! 70 | )! 71 | ) 72 | 73 | -------------------------------------------------------------------------------- /ParserPrinter.playground/Pages/URL Router.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PartialIso 3 | import Syntax 4 | import URLRequestRouter 5 | 6 | struct User: Codable { 7 | let email: String 8 | let password: String 9 | } 10 | 11 | enum Route { 12 | case home 13 | case episodes(limit: Int?, offset: Int?) 14 | case episode(Int) 15 | case search(String?) 16 | case signUp(User) 17 | } 18 | 19 | let router = Router( 20 | .match(.home, to: .get), 21 | .match( 22 | Route.episodes(limit:offset:), 23 | to: .get "episodes" ("limit", .optional(.int)) <&> ("offset", .optional(.int)) 24 | ), 25 | .match(Route.episode, to: .get "episodes" .int), 26 | .match(Route.search, to: .get "search" ("q", .optional(.string))), 27 | .match(Route.signUp, to: .post(.json) "sign-up") 28 | ) 29 | 30 | router.match(urlString: "/?ga=1") 31 | router.match(urlString: "/episodes/1?ga=1") 32 | router.match(urlString: "/episodes?limit=10") 33 | router.match(urlString: "/search?ga=1") 34 | router.match(urlString: "/search?q=point-free&ga=1") 35 | router.match(urlString: "/search") 36 | router.match(urlString: "/search?q=") 37 | 38 | var req = URLRequest(url: URL(string: "/sign-up")!) 39 | req.httpMethod = "post" 40 | req.httpBody = Data(""" 41 | {"email":"support@pointfree.co","password":"blob8108"} 42 | """.utf8) 43 | 44 | router.match(request: req) 45 | 46 | router.request(for: Route.search("blob")) 47 | router.request(for: Route.search("")) 48 | router.request(for: Route.search(nil)) 49 | router.request(for: Route.episode(42)) 50 | router.request(for: Route.episodes(limit: 10, offset: 10)) 51 | -------------------------------------------------------------------------------- /ParserPrinter.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/GeneratePartialIsosTests_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | BNDL 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/GeneratePartialIsos_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/Monoid_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/PartialIsoTests_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | BNDL 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/PartialIso_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/SnapshotTesting_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/SwiftSyntax_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/SyntaxTests_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | BNDL 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/Syntax_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/URLRequestRouterTests_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | BNDL 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/URLRequestRouter_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = "1"; 4 | objectVersion = "46"; 5 | objects = { 6 | "Monoid::Monoid" = { 7 | isa = "PBXNativeTarget"; 8 | buildConfigurationList = "OBJ_66"; 9 | buildPhases = ( 10 | "OBJ_69", 11 | "OBJ_87" 12 | ); 13 | dependencies = ( 14 | ); 15 | name = "Monoid"; 16 | productName = "Monoid"; 17 | productReference = "Monoid::Monoid::Product"; 18 | productType = "com.apple.product-type.framework"; 19 | }; 20 | "Monoid::Monoid::Product" = { 21 | isa = "PBXFileReference"; 22 | path = "Monoid.framework"; 23 | sourceTree = "BUILT_PRODUCTS_DIR"; 24 | }; 25 | "Monoid::SwiftPMPackageDescription" = { 26 | isa = "PBXNativeTarget"; 27 | buildConfigurationList = "OBJ_89"; 28 | buildPhases = ( 29 | "OBJ_92" 30 | ); 31 | dependencies = ( 32 | ); 33 | name = "MonoidPackageDescription"; 34 | productName = "MonoidPackageDescription"; 35 | productType = "com.apple.product-type.framework"; 36 | }; 37 | "OBJ_1" = { 38 | isa = "PBXProject"; 39 | attributes = { 40 | LastSwiftMigration = "9999"; 41 | LastUpgradeCheck = "9999"; 42 | }; 43 | buildConfigurationList = "OBJ_2"; 44 | compatibilityVersion = "Xcode 3.2"; 45 | developmentRegion = "en"; 46 | hasScannedForEncodings = "0"; 47 | knownRegions = ( 48 | "en" 49 | ); 50 | mainGroup = "OBJ_5"; 51 | productRefGroup = "OBJ_52"; 52 | projectDirPath = "."; 53 | targets = ( 54 | "Monoid::Monoid", 55 | "Monoid::SwiftPMPackageDescription", 56 | "ParserPrinter::SwiftPMPackageDescription", 57 | "ParserPrinter::ParserPrinterPackageTests::ProductTarget", 58 | "ParserPrinter::PartialIso", 59 | "ParserPrinter::PartialIsoTests", 60 | "ParserPrinter::Syntax", 61 | "ParserPrinter::SyntaxTests", 62 | "ParserPrinter::URLRequestRouter", 63 | "ParserPrinter::URLRequestRouterTests" 64 | ); 65 | }; 66 | "OBJ_10" = { 67 | isa = "PBXFileReference"; 68 | path = "Flatten.swift"; 69 | sourceTree = ""; 70 | }; 71 | "OBJ_101" = { 72 | isa = "XCConfigurationList"; 73 | buildConfigurations = ( 74 | "OBJ_102", 75 | "OBJ_103" 76 | ); 77 | defaultConfigurationIsVisible = "0"; 78 | defaultConfigurationName = "Release"; 79 | }; 80 | "OBJ_102" = { 81 | isa = "XCBuildConfiguration"; 82 | buildSettings = { 83 | }; 84 | name = "Debug"; 85 | }; 86 | "OBJ_103" = { 87 | isa = "XCBuildConfiguration"; 88 | buildSettings = { 89 | }; 90 | name = "Release"; 91 | }; 92 | "OBJ_104" = { 93 | isa = "PBXTargetDependency"; 94 | target = "ParserPrinter::URLRequestRouterTests"; 95 | }; 96 | "OBJ_106" = { 97 | isa = "PBXTargetDependency"; 98 | target = "ParserPrinter::PartialIsoTests"; 99 | }; 100 | "OBJ_108" = { 101 | isa = "PBXTargetDependency"; 102 | target = "ParserPrinter::SyntaxTests"; 103 | }; 104 | "OBJ_11" = { 105 | isa = "PBXFileReference"; 106 | path = "PartialIso.swift"; 107 | sourceTree = ""; 108 | }; 109 | "OBJ_111" = { 110 | isa = "XCConfigurationList"; 111 | buildConfigurations = ( 112 | "OBJ_112", 113 | "OBJ_113" 114 | ); 115 | defaultConfigurationIsVisible = "0"; 116 | defaultConfigurationName = "Release"; 117 | }; 118 | "OBJ_112" = { 119 | isa = "XCBuildConfiguration"; 120 | buildSettings = { 121 | ENABLE_TESTABILITY = "YES"; 122 | FRAMEWORK_SEARCH_PATHS = ( 123 | "$(inherited)", 124 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 125 | ); 126 | HEADER_SEARCH_PATHS = ( 127 | "$(inherited)" 128 | ); 129 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/PartialIso_Info.plist"; 130 | LD_RUNPATH_SEARCH_PATHS = ( 131 | "$(inherited)", 132 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" 133 | ); 134 | OTHER_CFLAGS = ( 135 | "$(inherited)" 136 | ); 137 | OTHER_LDFLAGS = ( 138 | "$(inherited)" 139 | ); 140 | OTHER_SWIFT_FLAGS = ( 141 | "$(inherited)" 142 | ); 143 | PRODUCT_BUNDLE_IDENTIFIER = "PartialIso"; 144 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 145 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 146 | SKIP_INSTALL = "YES"; 147 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 148 | "$(inherited)" 149 | ); 150 | SWIFT_VERSION = "4.2"; 151 | TARGET_NAME = "PartialIso"; 152 | }; 153 | name = "Debug"; 154 | }; 155 | "OBJ_113" = { 156 | isa = "XCBuildConfiguration"; 157 | buildSettings = { 158 | ENABLE_TESTABILITY = "YES"; 159 | FRAMEWORK_SEARCH_PATHS = ( 160 | "$(inherited)", 161 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 162 | ); 163 | HEADER_SEARCH_PATHS = ( 164 | "$(inherited)" 165 | ); 166 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/PartialIso_Info.plist"; 167 | LD_RUNPATH_SEARCH_PATHS = ( 168 | "$(inherited)", 169 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" 170 | ); 171 | OTHER_CFLAGS = ( 172 | "$(inherited)" 173 | ); 174 | OTHER_LDFLAGS = ( 175 | "$(inherited)" 176 | ); 177 | OTHER_SWIFT_FLAGS = ( 178 | "$(inherited)" 179 | ); 180 | PRODUCT_BUNDLE_IDENTIFIER = "PartialIso"; 181 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 182 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 183 | SKIP_INSTALL = "YES"; 184 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 185 | "$(inherited)" 186 | ); 187 | SWIFT_VERSION = "4.2"; 188 | TARGET_NAME = "PartialIso"; 189 | }; 190 | name = "Release"; 191 | }; 192 | "OBJ_114" = { 193 | isa = "PBXSourcesBuildPhase"; 194 | files = ( 195 | "OBJ_115", 196 | "OBJ_116", 197 | "OBJ_117" 198 | ); 199 | }; 200 | "OBJ_115" = { 201 | isa = "PBXBuildFile"; 202 | fileRef = "OBJ_9"; 203 | }; 204 | "OBJ_116" = { 205 | isa = "PBXBuildFile"; 206 | fileRef = "OBJ_10"; 207 | }; 208 | "OBJ_117" = { 209 | isa = "PBXBuildFile"; 210 | fileRef = "OBJ_11"; 211 | }; 212 | "OBJ_118" = { 213 | isa = "PBXFrameworksBuildPhase"; 214 | files = ( 215 | ); 216 | }; 217 | "OBJ_119" = { 218 | isa = "XCConfigurationList"; 219 | buildConfigurations = ( 220 | "OBJ_120", 221 | "OBJ_121" 222 | ); 223 | defaultConfigurationIsVisible = "0"; 224 | defaultConfigurationName = "Release"; 225 | }; 226 | "OBJ_12" = { 227 | isa = "PBXGroup"; 228 | children = ( 229 | "OBJ_13", 230 | "OBJ_14", 231 | "OBJ_15" 232 | ); 233 | name = "Syntax"; 234 | path = "Sources/Syntax"; 235 | sourceTree = "SOURCE_ROOT"; 236 | }; 237 | "OBJ_120" = { 238 | isa = "XCBuildConfiguration"; 239 | buildSettings = { 240 | CLANG_ENABLE_MODULES = "YES"; 241 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; 242 | FRAMEWORK_SEARCH_PATHS = ( 243 | "$(inherited)", 244 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 245 | ); 246 | HEADER_SEARCH_PATHS = ( 247 | "$(inherited)" 248 | ); 249 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/PartialIsoTests_Info.plist"; 250 | LD_RUNPATH_SEARCH_PATHS = ( 251 | "$(inherited)", 252 | "@loader_path/../Frameworks", 253 | "@loader_path/Frameworks" 254 | ); 255 | OTHER_CFLAGS = ( 256 | "$(inherited)" 257 | ); 258 | OTHER_LDFLAGS = ( 259 | "$(inherited)" 260 | ); 261 | OTHER_SWIFT_FLAGS = ( 262 | "$(inherited)" 263 | ); 264 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 265 | "$(inherited)" 266 | ); 267 | SWIFT_VERSION = "4.2"; 268 | TARGET_NAME = "PartialIsoTests"; 269 | }; 270 | name = "Debug"; 271 | }; 272 | "OBJ_121" = { 273 | isa = "XCBuildConfiguration"; 274 | buildSettings = { 275 | CLANG_ENABLE_MODULES = "YES"; 276 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; 277 | FRAMEWORK_SEARCH_PATHS = ( 278 | "$(inherited)", 279 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 280 | ); 281 | HEADER_SEARCH_PATHS = ( 282 | "$(inherited)" 283 | ); 284 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/PartialIsoTests_Info.plist"; 285 | LD_RUNPATH_SEARCH_PATHS = ( 286 | "$(inherited)", 287 | "@loader_path/../Frameworks", 288 | "@loader_path/Frameworks" 289 | ); 290 | OTHER_CFLAGS = ( 291 | "$(inherited)" 292 | ); 293 | OTHER_LDFLAGS = ( 294 | "$(inherited)" 295 | ); 296 | OTHER_SWIFT_FLAGS = ( 297 | "$(inherited)" 298 | ); 299 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 300 | "$(inherited)" 301 | ); 302 | SWIFT_VERSION = "4.2"; 303 | TARGET_NAME = "PartialIsoTests"; 304 | }; 305 | name = "Release"; 306 | }; 307 | "OBJ_122" = { 308 | isa = "PBXSourcesBuildPhase"; 309 | files = ( 310 | "OBJ_123", 311 | "OBJ_124" 312 | ); 313 | }; 314 | "OBJ_123" = { 315 | isa = "PBXBuildFile"; 316 | fileRef = "OBJ_21"; 317 | }; 318 | "OBJ_124" = { 319 | isa = "PBXBuildFile"; 320 | fileRef = "OBJ_22"; 321 | }; 322 | "OBJ_125" = { 323 | isa = "PBXFrameworksBuildPhase"; 324 | files = ( 325 | "OBJ_126" 326 | ); 327 | }; 328 | "OBJ_126" = { 329 | isa = "PBXBuildFile"; 330 | fileRef = "ParserPrinter::PartialIso::Product"; 331 | }; 332 | "OBJ_127" = { 333 | isa = "PBXTargetDependency"; 334 | target = "ParserPrinter::PartialIso"; 335 | }; 336 | "OBJ_129" = { 337 | isa = "XCConfigurationList"; 338 | buildConfigurations = ( 339 | "OBJ_130", 340 | "OBJ_131" 341 | ); 342 | defaultConfigurationIsVisible = "0"; 343 | defaultConfigurationName = "Release"; 344 | }; 345 | "OBJ_13" = { 346 | isa = "PBXFileReference"; 347 | path = "Numeric.swift"; 348 | sourceTree = ""; 349 | }; 350 | "OBJ_130" = { 351 | isa = "XCBuildConfiguration"; 352 | buildSettings = { 353 | ENABLE_TESTABILITY = "YES"; 354 | FRAMEWORK_SEARCH_PATHS = ( 355 | "$(inherited)", 356 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 357 | ); 358 | HEADER_SEARCH_PATHS = ( 359 | "$(inherited)" 360 | ); 361 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/Syntax_Info.plist"; 362 | LD_RUNPATH_SEARCH_PATHS = ( 363 | "$(inherited)", 364 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" 365 | ); 366 | OTHER_CFLAGS = ( 367 | "$(inherited)" 368 | ); 369 | OTHER_LDFLAGS = ( 370 | "$(inherited)" 371 | ); 372 | OTHER_SWIFT_FLAGS = ( 373 | "$(inherited)" 374 | ); 375 | PRODUCT_BUNDLE_IDENTIFIER = "Syntax"; 376 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 377 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 378 | SKIP_INSTALL = "YES"; 379 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 380 | "$(inherited)" 381 | ); 382 | SWIFT_VERSION = "4.2"; 383 | TARGET_NAME = "Syntax"; 384 | }; 385 | name = "Debug"; 386 | }; 387 | "OBJ_131" = { 388 | isa = "XCBuildConfiguration"; 389 | buildSettings = { 390 | ENABLE_TESTABILITY = "YES"; 391 | FRAMEWORK_SEARCH_PATHS = ( 392 | "$(inherited)", 393 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 394 | ); 395 | HEADER_SEARCH_PATHS = ( 396 | "$(inherited)" 397 | ); 398 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/Syntax_Info.plist"; 399 | LD_RUNPATH_SEARCH_PATHS = ( 400 | "$(inherited)", 401 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" 402 | ); 403 | OTHER_CFLAGS = ( 404 | "$(inherited)" 405 | ); 406 | OTHER_LDFLAGS = ( 407 | "$(inherited)" 408 | ); 409 | OTHER_SWIFT_FLAGS = ( 410 | "$(inherited)" 411 | ); 412 | PRODUCT_BUNDLE_IDENTIFIER = "Syntax"; 413 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 414 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 415 | SKIP_INSTALL = "YES"; 416 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 417 | "$(inherited)" 418 | ); 419 | SWIFT_VERSION = "4.2"; 420 | TARGET_NAME = "Syntax"; 421 | }; 422 | name = "Release"; 423 | }; 424 | "OBJ_132" = { 425 | isa = "PBXSourcesBuildPhase"; 426 | files = ( 427 | "OBJ_133", 428 | "OBJ_134", 429 | "OBJ_135" 430 | ); 431 | }; 432 | "OBJ_133" = { 433 | isa = "PBXBuildFile"; 434 | fileRef = "OBJ_13"; 435 | }; 436 | "OBJ_134" = { 437 | isa = "PBXBuildFile"; 438 | fileRef = "OBJ_14"; 439 | }; 440 | "OBJ_135" = { 441 | isa = "PBXBuildFile"; 442 | fileRef = "OBJ_15"; 443 | }; 444 | "OBJ_136" = { 445 | isa = "PBXFrameworksBuildPhase"; 446 | files = ( 447 | "OBJ_137", 448 | "OBJ_138" 449 | ); 450 | }; 451 | "OBJ_137" = { 452 | isa = "PBXBuildFile"; 453 | fileRef = "Monoid::Monoid::Product"; 454 | }; 455 | "OBJ_138" = { 456 | isa = "PBXBuildFile"; 457 | fileRef = "ParserPrinter::PartialIso::Product"; 458 | }; 459 | "OBJ_139" = { 460 | isa = "PBXTargetDependency"; 461 | target = "Monoid::Monoid"; 462 | }; 463 | "OBJ_14" = { 464 | isa = "PBXFileReference"; 465 | path = "String.swift"; 466 | sourceTree = ""; 467 | }; 468 | "OBJ_140" = { 469 | isa = "PBXTargetDependency"; 470 | target = "ParserPrinter::PartialIso"; 471 | }; 472 | "OBJ_141" = { 473 | isa = "XCConfigurationList"; 474 | buildConfigurations = ( 475 | "OBJ_142", 476 | "OBJ_143" 477 | ); 478 | defaultConfigurationIsVisible = "0"; 479 | defaultConfigurationName = "Release"; 480 | }; 481 | "OBJ_142" = { 482 | isa = "XCBuildConfiguration"; 483 | buildSettings = { 484 | CLANG_ENABLE_MODULES = "YES"; 485 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; 486 | FRAMEWORK_SEARCH_PATHS = ( 487 | "$(inherited)", 488 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 489 | ); 490 | HEADER_SEARCH_PATHS = ( 491 | "$(inherited)" 492 | ); 493 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/SyntaxTests_Info.plist"; 494 | LD_RUNPATH_SEARCH_PATHS = ( 495 | "$(inherited)", 496 | "@loader_path/../Frameworks", 497 | "@loader_path/Frameworks" 498 | ); 499 | OTHER_CFLAGS = ( 500 | "$(inherited)" 501 | ); 502 | OTHER_LDFLAGS = ( 503 | "$(inherited)" 504 | ); 505 | OTHER_SWIFT_FLAGS = ( 506 | "$(inherited)" 507 | ); 508 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 509 | "$(inherited)" 510 | ); 511 | SWIFT_VERSION = "4.2"; 512 | TARGET_NAME = "SyntaxTests"; 513 | }; 514 | name = "Debug"; 515 | }; 516 | "OBJ_143" = { 517 | isa = "XCBuildConfiguration"; 518 | buildSettings = { 519 | CLANG_ENABLE_MODULES = "YES"; 520 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; 521 | FRAMEWORK_SEARCH_PATHS = ( 522 | "$(inherited)", 523 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 524 | ); 525 | HEADER_SEARCH_PATHS = ( 526 | "$(inherited)" 527 | ); 528 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/SyntaxTests_Info.plist"; 529 | LD_RUNPATH_SEARCH_PATHS = ( 530 | "$(inherited)", 531 | "@loader_path/../Frameworks", 532 | "@loader_path/Frameworks" 533 | ); 534 | OTHER_CFLAGS = ( 535 | "$(inherited)" 536 | ); 537 | OTHER_LDFLAGS = ( 538 | "$(inherited)" 539 | ); 540 | OTHER_SWIFT_FLAGS = ( 541 | "$(inherited)" 542 | ); 543 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 544 | "$(inherited)" 545 | ); 546 | SWIFT_VERSION = "4.2"; 547 | TARGET_NAME = "SyntaxTests"; 548 | }; 549 | name = "Release"; 550 | }; 551 | "OBJ_144" = { 552 | isa = "PBXSourcesBuildPhase"; 553 | files = ( 554 | "OBJ_145", 555 | "OBJ_146" 556 | ); 557 | }; 558 | "OBJ_145" = { 559 | isa = "PBXBuildFile"; 560 | fileRef = "OBJ_24"; 561 | }; 562 | "OBJ_146" = { 563 | isa = "PBXBuildFile"; 564 | fileRef = "OBJ_25"; 565 | }; 566 | "OBJ_147" = { 567 | isa = "PBXFrameworksBuildPhase"; 568 | files = ( 569 | "OBJ_148", 570 | "OBJ_149", 571 | "OBJ_150" 572 | ); 573 | }; 574 | "OBJ_148" = { 575 | isa = "PBXBuildFile"; 576 | fileRef = "ParserPrinter::Syntax::Product"; 577 | }; 578 | "OBJ_149" = { 579 | isa = "PBXBuildFile"; 580 | fileRef = "Monoid::Monoid::Product"; 581 | }; 582 | "OBJ_15" = { 583 | isa = "PBXFileReference"; 584 | path = "Syntax.swift"; 585 | sourceTree = ""; 586 | }; 587 | "OBJ_150" = { 588 | isa = "PBXBuildFile"; 589 | fileRef = "ParserPrinter::PartialIso::Product"; 590 | }; 591 | "OBJ_151" = { 592 | isa = "PBXTargetDependency"; 593 | target = "ParserPrinter::Syntax"; 594 | }; 595 | "OBJ_152" = { 596 | isa = "PBXTargetDependency"; 597 | target = "Monoid::Monoid"; 598 | }; 599 | "OBJ_153" = { 600 | isa = "PBXTargetDependency"; 601 | target = "ParserPrinter::PartialIso"; 602 | }; 603 | "OBJ_155" = { 604 | isa = "XCConfigurationList"; 605 | buildConfigurations = ( 606 | "OBJ_156", 607 | "OBJ_157" 608 | ); 609 | defaultConfigurationIsVisible = "0"; 610 | defaultConfigurationName = "Release"; 611 | }; 612 | "OBJ_156" = { 613 | isa = "XCBuildConfiguration"; 614 | buildSettings = { 615 | ENABLE_TESTABILITY = "YES"; 616 | FRAMEWORK_SEARCH_PATHS = ( 617 | "$(inherited)", 618 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 619 | ); 620 | HEADER_SEARCH_PATHS = ( 621 | "$(inherited)" 622 | ); 623 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/URLRequestRouter_Info.plist"; 624 | LD_RUNPATH_SEARCH_PATHS = ( 625 | "$(inherited)", 626 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" 627 | ); 628 | OTHER_CFLAGS = ( 629 | "$(inherited)" 630 | ); 631 | OTHER_LDFLAGS = ( 632 | "$(inherited)" 633 | ); 634 | OTHER_SWIFT_FLAGS = ( 635 | "$(inherited)" 636 | ); 637 | PRODUCT_BUNDLE_IDENTIFIER = "URLRequestRouter"; 638 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 639 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 640 | SKIP_INSTALL = "YES"; 641 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 642 | "$(inherited)" 643 | ); 644 | SWIFT_VERSION = "4.2"; 645 | TARGET_NAME = "URLRequestRouter"; 646 | }; 647 | name = "Debug"; 648 | }; 649 | "OBJ_157" = { 650 | isa = "XCBuildConfiguration"; 651 | buildSettings = { 652 | ENABLE_TESTABILITY = "YES"; 653 | FRAMEWORK_SEARCH_PATHS = ( 654 | "$(inherited)", 655 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 656 | ); 657 | HEADER_SEARCH_PATHS = ( 658 | "$(inherited)" 659 | ); 660 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/URLRequestRouter_Info.plist"; 661 | LD_RUNPATH_SEARCH_PATHS = ( 662 | "$(inherited)", 663 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" 664 | ); 665 | OTHER_CFLAGS = ( 666 | "$(inherited)" 667 | ); 668 | OTHER_LDFLAGS = ( 669 | "$(inherited)" 670 | ); 671 | OTHER_SWIFT_FLAGS = ( 672 | "$(inherited)" 673 | ); 674 | PRODUCT_BUNDLE_IDENTIFIER = "URLRequestRouter"; 675 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 676 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 677 | SKIP_INSTALL = "YES"; 678 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 679 | "$(inherited)" 680 | ); 681 | SWIFT_VERSION = "4.2"; 682 | TARGET_NAME = "URLRequestRouter"; 683 | }; 684 | name = "Release"; 685 | }; 686 | "OBJ_158" = { 687 | isa = "PBXSourcesBuildPhase"; 688 | files = ( 689 | "OBJ_159", 690 | "OBJ_160" 691 | ); 692 | }; 693 | "OBJ_159" = { 694 | isa = "PBXBuildFile"; 695 | fileRef = "OBJ_17"; 696 | }; 697 | "OBJ_16" = { 698 | isa = "PBXGroup"; 699 | children = ( 700 | "OBJ_17", 701 | "OBJ_18" 702 | ); 703 | name = "URLRequestRouter"; 704 | path = "Sources/URLRequestRouter"; 705 | sourceTree = "SOURCE_ROOT"; 706 | }; 707 | "OBJ_160" = { 708 | isa = "PBXBuildFile"; 709 | fileRef = "OBJ_18"; 710 | }; 711 | "OBJ_161" = { 712 | isa = "PBXFrameworksBuildPhase"; 713 | files = ( 714 | "OBJ_162", 715 | "OBJ_163", 716 | "OBJ_164" 717 | ); 718 | }; 719 | "OBJ_162" = { 720 | isa = "PBXBuildFile"; 721 | fileRef = "ParserPrinter::Syntax::Product"; 722 | }; 723 | "OBJ_163" = { 724 | isa = "PBXBuildFile"; 725 | fileRef = "Monoid::Monoid::Product"; 726 | }; 727 | "OBJ_164" = { 728 | isa = "PBXBuildFile"; 729 | fileRef = "ParserPrinter::PartialIso::Product"; 730 | }; 731 | "OBJ_165" = { 732 | isa = "PBXTargetDependency"; 733 | target = "ParserPrinter::Syntax"; 734 | }; 735 | "OBJ_166" = { 736 | isa = "PBXTargetDependency"; 737 | target = "Monoid::Monoid"; 738 | }; 739 | "OBJ_167" = { 740 | isa = "PBXTargetDependency"; 741 | target = "ParserPrinter::PartialIso"; 742 | }; 743 | "OBJ_168" = { 744 | isa = "XCConfigurationList"; 745 | buildConfigurations = ( 746 | "OBJ_169", 747 | "OBJ_170" 748 | ); 749 | defaultConfigurationIsVisible = "0"; 750 | defaultConfigurationName = "Release"; 751 | }; 752 | "OBJ_169" = { 753 | isa = "XCBuildConfiguration"; 754 | buildSettings = { 755 | CLANG_ENABLE_MODULES = "YES"; 756 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; 757 | FRAMEWORK_SEARCH_PATHS = ( 758 | "$(inherited)", 759 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 760 | ); 761 | HEADER_SEARCH_PATHS = ( 762 | "$(inherited)" 763 | ); 764 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/URLRequestRouterTests_Info.plist"; 765 | LD_RUNPATH_SEARCH_PATHS = ( 766 | "$(inherited)", 767 | "@loader_path/../Frameworks", 768 | "@loader_path/Frameworks" 769 | ); 770 | OTHER_CFLAGS = ( 771 | "$(inherited)" 772 | ); 773 | OTHER_LDFLAGS = ( 774 | "$(inherited)" 775 | ); 776 | OTHER_SWIFT_FLAGS = ( 777 | "$(inherited)" 778 | ); 779 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 780 | "$(inherited)" 781 | ); 782 | SWIFT_VERSION = "4.2"; 783 | TARGET_NAME = "URLRequestRouterTests"; 784 | }; 785 | name = "Debug"; 786 | }; 787 | "OBJ_17" = { 788 | isa = "PBXFileReference"; 789 | path = "RequestData.swift"; 790 | sourceTree = ""; 791 | }; 792 | "OBJ_170" = { 793 | isa = "XCBuildConfiguration"; 794 | buildSettings = { 795 | CLANG_ENABLE_MODULES = "YES"; 796 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; 797 | FRAMEWORK_SEARCH_PATHS = ( 798 | "$(inherited)", 799 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 800 | ); 801 | HEADER_SEARCH_PATHS = ( 802 | "$(inherited)" 803 | ); 804 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/URLRequestRouterTests_Info.plist"; 805 | LD_RUNPATH_SEARCH_PATHS = ( 806 | "$(inherited)", 807 | "@loader_path/../Frameworks", 808 | "@loader_path/Frameworks" 809 | ); 810 | OTHER_CFLAGS = ( 811 | "$(inherited)" 812 | ); 813 | OTHER_LDFLAGS = ( 814 | "$(inherited)" 815 | ); 816 | OTHER_SWIFT_FLAGS = ( 817 | "$(inherited)" 818 | ); 819 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 820 | "$(inherited)" 821 | ); 822 | SWIFT_VERSION = "4.2"; 823 | TARGET_NAME = "URLRequestRouterTests"; 824 | }; 825 | name = "Release"; 826 | }; 827 | "OBJ_171" = { 828 | isa = "PBXSourcesBuildPhase"; 829 | files = ( 830 | "OBJ_172", 831 | "OBJ_173" 832 | ); 833 | }; 834 | "OBJ_172" = { 835 | isa = "PBXBuildFile"; 836 | fileRef = "OBJ_27"; 837 | }; 838 | "OBJ_173" = { 839 | isa = "PBXBuildFile"; 840 | fileRef = "OBJ_28"; 841 | }; 842 | "OBJ_174" = { 843 | isa = "PBXFrameworksBuildPhase"; 844 | files = ( 845 | "OBJ_175", 846 | "OBJ_176", 847 | "OBJ_177", 848 | "OBJ_178" 849 | ); 850 | }; 851 | "OBJ_175" = { 852 | isa = "PBXBuildFile"; 853 | fileRef = "ParserPrinter::URLRequestRouter::Product"; 854 | }; 855 | "OBJ_176" = { 856 | isa = "PBXBuildFile"; 857 | fileRef = "ParserPrinter::Syntax::Product"; 858 | }; 859 | "OBJ_177" = { 860 | isa = "PBXBuildFile"; 861 | fileRef = "Monoid::Monoid::Product"; 862 | }; 863 | "OBJ_178" = { 864 | isa = "PBXBuildFile"; 865 | fileRef = "ParserPrinter::PartialIso::Product"; 866 | }; 867 | "OBJ_179" = { 868 | isa = "PBXTargetDependency"; 869 | target = "ParserPrinter::URLRequestRouter"; 870 | }; 871 | "OBJ_18" = { 872 | isa = "PBXFileReference"; 873 | path = "URLRequestRouter.swift"; 874 | sourceTree = ""; 875 | }; 876 | "OBJ_180" = { 877 | isa = "PBXTargetDependency"; 878 | target = "ParserPrinter::Syntax"; 879 | }; 880 | "OBJ_181" = { 881 | isa = "PBXTargetDependency"; 882 | target = "Monoid::Monoid"; 883 | }; 884 | "OBJ_182" = { 885 | isa = "PBXTargetDependency"; 886 | target = "ParserPrinter::PartialIso"; 887 | }; 888 | "OBJ_19" = { 889 | isa = "PBXGroup"; 890 | children = ( 891 | "OBJ_20", 892 | "OBJ_23", 893 | "OBJ_26" 894 | ); 895 | name = "Tests"; 896 | path = ""; 897 | sourceTree = "SOURCE_ROOT"; 898 | }; 899 | "OBJ_2" = { 900 | isa = "XCConfigurationList"; 901 | buildConfigurations = ( 902 | "OBJ_3", 903 | "OBJ_4" 904 | ); 905 | defaultConfigurationIsVisible = "0"; 906 | defaultConfigurationName = "Release"; 907 | }; 908 | "OBJ_20" = { 909 | isa = "PBXGroup"; 910 | children = ( 911 | "OBJ_21", 912 | "OBJ_22" 913 | ); 914 | name = "PartialIsoTests"; 915 | path = "Tests/PartialIsoTests"; 916 | sourceTree = "SOURCE_ROOT"; 917 | }; 918 | "OBJ_21" = { 919 | isa = "PBXFileReference"; 920 | path = "PartialIsoTests.swift"; 921 | sourceTree = ""; 922 | }; 923 | "OBJ_22" = { 924 | isa = "PBXFileReference"; 925 | path = "XCTestManifests.swift"; 926 | sourceTree = ""; 927 | }; 928 | "OBJ_23" = { 929 | isa = "PBXGroup"; 930 | children = ( 931 | "OBJ_24", 932 | "OBJ_25" 933 | ); 934 | name = "SyntaxTests"; 935 | path = "Tests/SyntaxTests"; 936 | sourceTree = "SOURCE_ROOT"; 937 | }; 938 | "OBJ_24" = { 939 | isa = "PBXFileReference"; 940 | path = "SyntaxTests.swift"; 941 | sourceTree = ""; 942 | }; 943 | "OBJ_25" = { 944 | isa = "PBXFileReference"; 945 | path = "XCTestManifests.swift"; 946 | sourceTree = ""; 947 | }; 948 | "OBJ_26" = { 949 | isa = "PBXGroup"; 950 | children = ( 951 | "OBJ_27", 952 | "OBJ_28" 953 | ); 954 | name = "URLRequestRouterTests"; 955 | path = "Tests/URLRequestRouterTests"; 956 | sourceTree = "SOURCE_ROOT"; 957 | }; 958 | "OBJ_27" = { 959 | isa = "PBXFileReference"; 960 | path = "URLRequestRouterTests.swift"; 961 | sourceTree = ""; 962 | }; 963 | "OBJ_28" = { 964 | isa = "PBXFileReference"; 965 | path = "XCTestManifests.swift"; 966 | sourceTree = ""; 967 | }; 968 | "OBJ_29" = { 969 | isa = "PBXGroup"; 970 | children = ( 971 | "OBJ_30" 972 | ); 973 | name = "Dependencies"; 974 | path = ""; 975 | sourceTree = ""; 976 | }; 977 | "OBJ_3" = { 978 | isa = "XCBuildConfiguration"; 979 | buildSettings = { 980 | CLANG_ENABLE_OBJC_ARC = "YES"; 981 | COMBINE_HIDPI_IMAGES = "YES"; 982 | COPY_PHASE_STRIP = "NO"; 983 | DEBUG_INFORMATION_FORMAT = "dwarf"; 984 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 985 | ENABLE_NS_ASSERTIONS = "YES"; 986 | GCC_OPTIMIZATION_LEVEL = "0"; 987 | GCC_PREPROCESSOR_DEFINITIONS = ( 988 | "$(inherited)", 989 | "SWIFT_PACKAGE=1", 990 | "DEBUG=1" 991 | ); 992 | MACOSX_DEPLOYMENT_TARGET = "10.10"; 993 | ONLY_ACTIVE_ARCH = "YES"; 994 | OTHER_SWIFT_FLAGS = ( 995 | "$(inherited)", 996 | "-DXcode" 997 | ); 998 | PRODUCT_NAME = "$(TARGET_NAME)"; 999 | SDKROOT = "macosx"; 1000 | SUPPORTED_PLATFORMS = ( 1001 | "macosx", 1002 | "iphoneos", 1003 | "iphonesimulator", 1004 | "appletvos", 1005 | "appletvsimulator", 1006 | "watchos", 1007 | "watchsimulator" 1008 | ); 1009 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 1010 | "$(inherited)", 1011 | "SWIFT_PACKAGE", 1012 | "DEBUG" 1013 | ); 1014 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 1015 | USE_HEADERMAP = "NO"; 1016 | }; 1017 | name = "Debug"; 1018 | }; 1019 | "OBJ_30" = { 1020 | isa = "PBXGroup"; 1021 | children = ( 1022 | "OBJ_31", 1023 | "OBJ_51" 1024 | ); 1025 | name = "Monoid"; 1026 | path = ""; 1027 | sourceTree = "SOURCE_ROOT"; 1028 | }; 1029 | "OBJ_31" = { 1030 | isa = "PBXGroup"; 1031 | children = ( 1032 | "OBJ_32", 1033 | "OBJ_37" 1034 | ); 1035 | name = "Monoid"; 1036 | path = ".build/checkouts/swift-algebras/Sources/Monoid"; 1037 | sourceTree = "SOURCE_ROOT"; 1038 | }; 1039 | "OBJ_32" = { 1040 | isa = "PBXGroup"; 1041 | children = ( 1042 | "OBJ_33", 1043 | "OBJ_34", 1044 | "OBJ_35", 1045 | "OBJ_36" 1046 | ); 1047 | name = "Algebras"; 1048 | path = "Algebras"; 1049 | sourceTree = ""; 1050 | }; 1051 | "OBJ_33" = { 1052 | isa = "PBXFileReference"; 1053 | path = "Folds.swift"; 1054 | sourceTree = ""; 1055 | }; 1056 | "OBJ_34" = { 1057 | isa = "PBXFileReference"; 1058 | path = "Monoid.swift"; 1059 | sourceTree = ""; 1060 | }; 1061 | "OBJ_35" = { 1062 | isa = "PBXFileReference"; 1063 | path = "Semigroup.swift"; 1064 | sourceTree = ""; 1065 | }; 1066 | "OBJ_36" = { 1067 | isa = "PBXFileReference"; 1068 | path = "TODO.swift"; 1069 | sourceTree = ""; 1070 | }; 1071 | "OBJ_37" = { 1072 | isa = "PBXGroup"; 1073 | children = ( 1074 | "OBJ_38", 1075 | "OBJ_39", 1076 | "OBJ_40", 1077 | "OBJ_41", 1078 | "OBJ_42", 1079 | "OBJ_43", 1080 | "OBJ_44", 1081 | "OBJ_45", 1082 | "OBJ_46", 1083 | "OBJ_47", 1084 | "OBJ_48", 1085 | "OBJ_49", 1086 | "OBJ_50" 1087 | ); 1088 | name = "Instances"; 1089 | path = "Instances"; 1090 | sourceTree = ""; 1091 | }; 1092 | "OBJ_38" = { 1093 | isa = "PBXFileReference"; 1094 | path = "Average.swift"; 1095 | sourceTree = ""; 1096 | }; 1097 | "OBJ_39" = { 1098 | isa = "PBXFileReference"; 1099 | path = "Bool.swift"; 1100 | sourceTree = ""; 1101 | }; 1102 | "OBJ_4" = { 1103 | isa = "XCBuildConfiguration"; 1104 | buildSettings = { 1105 | CLANG_ENABLE_OBJC_ARC = "YES"; 1106 | COMBINE_HIDPI_IMAGES = "YES"; 1107 | COPY_PHASE_STRIP = "YES"; 1108 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 1109 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 1110 | GCC_OPTIMIZATION_LEVEL = "s"; 1111 | GCC_PREPROCESSOR_DEFINITIONS = ( 1112 | "$(inherited)", 1113 | "SWIFT_PACKAGE=1" 1114 | ); 1115 | MACOSX_DEPLOYMENT_TARGET = "10.10"; 1116 | OTHER_SWIFT_FLAGS = ( 1117 | "$(inherited)", 1118 | "-DXcode" 1119 | ); 1120 | PRODUCT_NAME = "$(TARGET_NAME)"; 1121 | SDKROOT = "macosx"; 1122 | SUPPORTED_PLATFORMS = ( 1123 | "macosx", 1124 | "iphoneos", 1125 | "iphonesimulator", 1126 | "appletvos", 1127 | "appletvsimulator", 1128 | "watchos", 1129 | "watchsimulator" 1130 | ); 1131 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 1132 | "$(inherited)", 1133 | "SWIFT_PACKAGE" 1134 | ); 1135 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 1136 | USE_HEADERMAP = "NO"; 1137 | }; 1138 | name = "Release"; 1139 | }; 1140 | "OBJ_40" = { 1141 | isa = "PBXFileReference"; 1142 | path = "Comparable.swift"; 1143 | sourceTree = ""; 1144 | }; 1145 | "OBJ_41" = { 1146 | isa = "PBXFileReference"; 1147 | path = "Dictionary.swift"; 1148 | sourceTree = ""; 1149 | }; 1150 | "OBJ_42" = { 1151 | isa = "PBXFileReference"; 1152 | path = "Endo.swift"; 1153 | sourceTree = ""; 1154 | }; 1155 | "OBJ_43" = { 1156 | isa = "PBXFileReference"; 1157 | path = "Numeric.swift"; 1158 | sourceTree = ""; 1159 | }; 1160 | "OBJ_44" = { 1161 | isa = "PBXFileReference"; 1162 | path = "Optional.swift"; 1163 | sourceTree = ""; 1164 | }; 1165 | "OBJ_45" = { 1166 | isa = "PBXFileReference"; 1167 | path = "Pointwise.swift"; 1168 | sourceTree = ""; 1169 | }; 1170 | "OBJ_46" = { 1171 | isa = "PBXFileReference"; 1172 | path = "RangeReplaceableCollection.swift"; 1173 | sourceTree = ""; 1174 | }; 1175 | "OBJ_47" = { 1176 | isa = "PBXFileReference"; 1177 | path = "Set.swift"; 1178 | sourceTree = ""; 1179 | }; 1180 | "OBJ_48" = { 1181 | isa = "PBXFileReference"; 1182 | path = "Tuple.swift"; 1183 | sourceTree = ""; 1184 | }; 1185 | "OBJ_49" = { 1186 | isa = "PBXFileReference"; 1187 | path = "Variance.swift"; 1188 | sourceTree = ""; 1189 | }; 1190 | "OBJ_5" = { 1191 | isa = "PBXGroup"; 1192 | children = ( 1193 | "OBJ_6", 1194 | "OBJ_7", 1195 | "OBJ_19", 1196 | "OBJ_29", 1197 | "OBJ_52", 1198 | "OBJ_60", 1199 | "OBJ_61", 1200 | "OBJ_62", 1201 | "OBJ_63", 1202 | "OBJ_64" 1203 | ); 1204 | path = ""; 1205 | sourceTree = ""; 1206 | }; 1207 | "OBJ_50" = { 1208 | isa = "PBXFileReference"; 1209 | path = "Void.swift"; 1210 | sourceTree = ""; 1211 | }; 1212 | "OBJ_51" = { 1213 | isa = "PBXFileReference"; 1214 | explicitFileType = "sourcecode.swift"; 1215 | name = "Package.swift"; 1216 | path = "/Users/stephen/Developer/pointfreeco/swift-parser-printer/.build/checkouts/swift-algebras/Package.swift"; 1217 | sourceTree = ""; 1218 | }; 1219 | "OBJ_52" = { 1220 | isa = "PBXGroup"; 1221 | children = ( 1222 | "ParserPrinter::URLRequestRouter::Product", 1223 | "Monoid::Monoid::Product", 1224 | "ParserPrinter::SyntaxTests::Product", 1225 | "ParserPrinter::Syntax::Product", 1226 | "ParserPrinter::PartialIsoTests::Product", 1227 | "ParserPrinter::URLRequestRouterTests::Product", 1228 | "ParserPrinter::PartialIso::Product" 1229 | ); 1230 | name = "Products"; 1231 | path = ""; 1232 | sourceTree = "BUILT_PRODUCTS_DIR"; 1233 | }; 1234 | "OBJ_6" = { 1235 | isa = "PBXFileReference"; 1236 | explicitFileType = "sourcecode.swift"; 1237 | path = "Package.swift"; 1238 | sourceTree = ""; 1239 | }; 1240 | "OBJ_60" = { 1241 | isa = "PBXFileReference"; 1242 | path = "ParserPrinter.xcworkspace"; 1243 | sourceTree = "SOURCE_ROOT"; 1244 | }; 1245 | "OBJ_61" = { 1246 | isa = "PBXFileReference"; 1247 | path = "LICENSE"; 1248 | sourceTree = ""; 1249 | }; 1250 | "OBJ_62" = { 1251 | isa = "PBXFileReference"; 1252 | path = "Dockerfile"; 1253 | sourceTree = ""; 1254 | }; 1255 | "OBJ_63" = { 1256 | isa = "PBXFileReference"; 1257 | path = "Makefile"; 1258 | sourceTree = ""; 1259 | }; 1260 | "OBJ_64" = { 1261 | isa = "PBXFileReference"; 1262 | path = "README.md"; 1263 | sourceTree = ""; 1264 | }; 1265 | "OBJ_66" = { 1266 | isa = "XCConfigurationList"; 1267 | buildConfigurations = ( 1268 | "OBJ_67", 1269 | "OBJ_68" 1270 | ); 1271 | defaultConfigurationIsVisible = "0"; 1272 | defaultConfigurationName = "Release"; 1273 | }; 1274 | "OBJ_67" = { 1275 | isa = "XCBuildConfiguration"; 1276 | buildSettings = { 1277 | ENABLE_TESTABILITY = "YES"; 1278 | FRAMEWORK_SEARCH_PATHS = ( 1279 | "$(inherited)", 1280 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 1281 | ); 1282 | HEADER_SEARCH_PATHS = ( 1283 | "$(inherited)" 1284 | ); 1285 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/Monoid_Info.plist"; 1286 | LD_RUNPATH_SEARCH_PATHS = ( 1287 | "$(inherited)", 1288 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" 1289 | ); 1290 | OTHER_CFLAGS = ( 1291 | "$(inherited)" 1292 | ); 1293 | OTHER_LDFLAGS = ( 1294 | "$(inherited)" 1295 | ); 1296 | OTHER_SWIFT_FLAGS = ( 1297 | "$(inherited)" 1298 | ); 1299 | PRODUCT_BUNDLE_IDENTIFIER = "Monoid"; 1300 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 1301 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 1302 | SKIP_INSTALL = "YES"; 1303 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 1304 | "$(inherited)" 1305 | ); 1306 | SWIFT_VERSION = "4.2"; 1307 | TARGET_NAME = "Monoid"; 1308 | }; 1309 | name = "Debug"; 1310 | }; 1311 | "OBJ_68" = { 1312 | isa = "XCBuildConfiguration"; 1313 | buildSettings = { 1314 | ENABLE_TESTABILITY = "YES"; 1315 | FRAMEWORK_SEARCH_PATHS = ( 1316 | "$(inherited)", 1317 | "$(PLATFORM_DIR)/Developer/Library/Frameworks" 1318 | ); 1319 | HEADER_SEARCH_PATHS = ( 1320 | "$(inherited)" 1321 | ); 1322 | INFOPLIST_FILE = "ParserPrinter.xcodeproj/Monoid_Info.plist"; 1323 | LD_RUNPATH_SEARCH_PATHS = ( 1324 | "$(inherited)", 1325 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" 1326 | ); 1327 | OTHER_CFLAGS = ( 1328 | "$(inherited)" 1329 | ); 1330 | OTHER_LDFLAGS = ( 1331 | "$(inherited)" 1332 | ); 1333 | OTHER_SWIFT_FLAGS = ( 1334 | "$(inherited)" 1335 | ); 1336 | PRODUCT_BUNDLE_IDENTIFIER = "Monoid"; 1337 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 1338 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 1339 | SKIP_INSTALL = "YES"; 1340 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( 1341 | "$(inherited)" 1342 | ); 1343 | SWIFT_VERSION = "4.2"; 1344 | TARGET_NAME = "Monoid"; 1345 | }; 1346 | name = "Release"; 1347 | }; 1348 | "OBJ_69" = { 1349 | isa = "PBXSourcesBuildPhase"; 1350 | files = ( 1351 | "OBJ_70", 1352 | "OBJ_71", 1353 | "OBJ_72", 1354 | "OBJ_73", 1355 | "OBJ_74", 1356 | "OBJ_75", 1357 | "OBJ_76", 1358 | "OBJ_77", 1359 | "OBJ_78", 1360 | "OBJ_79", 1361 | "OBJ_80", 1362 | "OBJ_81", 1363 | "OBJ_82", 1364 | "OBJ_83", 1365 | "OBJ_84", 1366 | "OBJ_85", 1367 | "OBJ_86" 1368 | ); 1369 | }; 1370 | "OBJ_7" = { 1371 | isa = "PBXGroup"; 1372 | children = ( 1373 | "OBJ_8", 1374 | "OBJ_12", 1375 | "OBJ_16" 1376 | ); 1377 | name = "Sources"; 1378 | path = ""; 1379 | sourceTree = "SOURCE_ROOT"; 1380 | }; 1381 | "OBJ_70" = { 1382 | isa = "PBXBuildFile"; 1383 | fileRef = "OBJ_33"; 1384 | }; 1385 | "OBJ_71" = { 1386 | isa = "PBXBuildFile"; 1387 | fileRef = "OBJ_34"; 1388 | }; 1389 | "OBJ_72" = { 1390 | isa = "PBXBuildFile"; 1391 | fileRef = "OBJ_35"; 1392 | }; 1393 | "OBJ_73" = { 1394 | isa = "PBXBuildFile"; 1395 | fileRef = "OBJ_36"; 1396 | }; 1397 | "OBJ_74" = { 1398 | isa = "PBXBuildFile"; 1399 | fileRef = "OBJ_38"; 1400 | }; 1401 | "OBJ_75" = { 1402 | isa = "PBXBuildFile"; 1403 | fileRef = "OBJ_39"; 1404 | }; 1405 | "OBJ_76" = { 1406 | isa = "PBXBuildFile"; 1407 | fileRef = "OBJ_40"; 1408 | }; 1409 | "OBJ_77" = { 1410 | isa = "PBXBuildFile"; 1411 | fileRef = "OBJ_41"; 1412 | }; 1413 | "OBJ_78" = { 1414 | isa = "PBXBuildFile"; 1415 | fileRef = "OBJ_42"; 1416 | }; 1417 | "OBJ_79" = { 1418 | isa = "PBXBuildFile"; 1419 | fileRef = "OBJ_43"; 1420 | }; 1421 | "OBJ_8" = { 1422 | isa = "PBXGroup"; 1423 | children = ( 1424 | "OBJ_9", 1425 | "OBJ_10", 1426 | "OBJ_11" 1427 | ); 1428 | name = "PartialIso"; 1429 | path = "Sources/PartialIso"; 1430 | sourceTree = "SOURCE_ROOT"; 1431 | }; 1432 | "OBJ_80" = { 1433 | isa = "PBXBuildFile"; 1434 | fileRef = "OBJ_44"; 1435 | }; 1436 | "OBJ_81" = { 1437 | isa = "PBXBuildFile"; 1438 | fileRef = "OBJ_45"; 1439 | }; 1440 | "OBJ_82" = { 1441 | isa = "PBXBuildFile"; 1442 | fileRef = "OBJ_46"; 1443 | }; 1444 | "OBJ_83" = { 1445 | isa = "PBXBuildFile"; 1446 | fileRef = "OBJ_47"; 1447 | }; 1448 | "OBJ_84" = { 1449 | isa = "PBXBuildFile"; 1450 | fileRef = "OBJ_48"; 1451 | }; 1452 | "OBJ_85" = { 1453 | isa = "PBXBuildFile"; 1454 | fileRef = "OBJ_49"; 1455 | }; 1456 | "OBJ_86" = { 1457 | isa = "PBXBuildFile"; 1458 | fileRef = "OBJ_50"; 1459 | }; 1460 | "OBJ_87" = { 1461 | isa = "PBXFrameworksBuildPhase"; 1462 | files = ( 1463 | ); 1464 | }; 1465 | "OBJ_89" = { 1466 | isa = "XCConfigurationList"; 1467 | buildConfigurations = ( 1468 | "OBJ_90", 1469 | "OBJ_91" 1470 | ); 1471 | defaultConfigurationIsVisible = "0"; 1472 | defaultConfigurationName = "Release"; 1473 | }; 1474 | "OBJ_9" = { 1475 | isa = "PBXFileReference"; 1476 | path = "ExpressibleByStringLiteral.swift"; 1477 | sourceTree = ""; 1478 | }; 1479 | "OBJ_90" = { 1480 | isa = "XCBuildConfiguration"; 1481 | buildSettings = { 1482 | LD = "/usr/bin/true"; 1483 | OTHER_SWIFT_FLAGS = ( 1484 | "-swift-version", 1485 | "4.2", 1486 | "-I", 1487 | "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2", 1488 | "-target", 1489 | "x86_64-apple-macosx10.10", 1490 | "-sdk", 1491 | "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk", 1492 | "-package-description-version", 1493 | "4.2" 1494 | ); 1495 | SWIFT_VERSION = "4.2"; 1496 | }; 1497 | name = "Debug"; 1498 | }; 1499 | "OBJ_91" = { 1500 | isa = "XCBuildConfiguration"; 1501 | buildSettings = { 1502 | LD = "/usr/bin/true"; 1503 | OTHER_SWIFT_FLAGS = ( 1504 | "-swift-version", 1505 | "4.2", 1506 | "-I", 1507 | "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2", 1508 | "-target", 1509 | "x86_64-apple-macosx10.10", 1510 | "-sdk", 1511 | "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk", 1512 | "-package-description-version", 1513 | "4.2" 1514 | ); 1515 | SWIFT_VERSION = "4.2"; 1516 | }; 1517 | name = "Release"; 1518 | }; 1519 | "OBJ_92" = { 1520 | isa = "PBXSourcesBuildPhase"; 1521 | files = ( 1522 | "OBJ_93" 1523 | ); 1524 | }; 1525 | "OBJ_93" = { 1526 | isa = "PBXBuildFile"; 1527 | fileRef = "OBJ_51"; 1528 | }; 1529 | "OBJ_95" = { 1530 | isa = "XCConfigurationList"; 1531 | buildConfigurations = ( 1532 | "OBJ_96", 1533 | "OBJ_97" 1534 | ); 1535 | defaultConfigurationIsVisible = "0"; 1536 | defaultConfigurationName = "Release"; 1537 | }; 1538 | "OBJ_96" = { 1539 | isa = "XCBuildConfiguration"; 1540 | buildSettings = { 1541 | LD = "/usr/bin/true"; 1542 | OTHER_SWIFT_FLAGS = ( 1543 | "-swift-version", 1544 | "4.2", 1545 | "-I", 1546 | "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2", 1547 | "-target", 1548 | "x86_64-apple-macosx10.10", 1549 | "-sdk", 1550 | "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk", 1551 | "-package-description-version", 1552 | "4.2" 1553 | ); 1554 | SWIFT_VERSION = "4.2"; 1555 | }; 1556 | name = "Debug"; 1557 | }; 1558 | "OBJ_97" = { 1559 | isa = "XCBuildConfiguration"; 1560 | buildSettings = { 1561 | LD = "/usr/bin/true"; 1562 | OTHER_SWIFT_FLAGS = ( 1563 | "-swift-version", 1564 | "4.2", 1565 | "-I", 1566 | "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2", 1567 | "-target", 1568 | "x86_64-apple-macosx10.10", 1569 | "-sdk", 1570 | "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk", 1571 | "-package-description-version", 1572 | "4.2" 1573 | ); 1574 | SWIFT_VERSION = "4.2"; 1575 | }; 1576 | name = "Release"; 1577 | }; 1578 | "OBJ_98" = { 1579 | isa = "PBXSourcesBuildPhase"; 1580 | files = ( 1581 | "OBJ_99" 1582 | ); 1583 | }; 1584 | "OBJ_99" = { 1585 | isa = "PBXBuildFile"; 1586 | fileRef = "OBJ_6"; 1587 | }; 1588 | "ParserPrinter::ParserPrinterPackageTests::ProductTarget" = { 1589 | isa = "PBXAggregateTarget"; 1590 | buildConfigurationList = "OBJ_101"; 1591 | buildPhases = ( 1592 | ); 1593 | dependencies = ( 1594 | "OBJ_104", 1595 | "OBJ_106", 1596 | "OBJ_108" 1597 | ); 1598 | name = "ParserPrinterPackageTests"; 1599 | productName = "ParserPrinterPackageTests"; 1600 | }; 1601 | "ParserPrinter::PartialIso" = { 1602 | isa = "PBXNativeTarget"; 1603 | buildConfigurationList = "OBJ_111"; 1604 | buildPhases = ( 1605 | "OBJ_114", 1606 | "OBJ_118" 1607 | ); 1608 | dependencies = ( 1609 | ); 1610 | name = "PartialIso"; 1611 | productName = "PartialIso"; 1612 | productReference = "ParserPrinter::PartialIso::Product"; 1613 | productType = "com.apple.product-type.framework"; 1614 | }; 1615 | "ParserPrinter::PartialIso::Product" = { 1616 | isa = "PBXFileReference"; 1617 | path = "PartialIso.framework"; 1618 | sourceTree = "BUILT_PRODUCTS_DIR"; 1619 | }; 1620 | "ParserPrinter::PartialIsoTests" = { 1621 | isa = "PBXNativeTarget"; 1622 | buildConfigurationList = "OBJ_119"; 1623 | buildPhases = ( 1624 | "OBJ_122", 1625 | "OBJ_125" 1626 | ); 1627 | dependencies = ( 1628 | "OBJ_127" 1629 | ); 1630 | name = "PartialIsoTests"; 1631 | productName = "PartialIsoTests"; 1632 | productReference = "ParserPrinter::PartialIsoTests::Product"; 1633 | productType = "com.apple.product-type.bundle.unit-test"; 1634 | }; 1635 | "ParserPrinter::PartialIsoTests::Product" = { 1636 | isa = "PBXFileReference"; 1637 | path = "PartialIsoTests.xctest"; 1638 | sourceTree = "BUILT_PRODUCTS_DIR"; 1639 | }; 1640 | "ParserPrinter::SwiftPMPackageDescription" = { 1641 | isa = "PBXNativeTarget"; 1642 | buildConfigurationList = "OBJ_95"; 1643 | buildPhases = ( 1644 | "OBJ_98" 1645 | ); 1646 | dependencies = ( 1647 | ); 1648 | name = "ParserPrinterPackageDescription"; 1649 | productName = "ParserPrinterPackageDescription"; 1650 | productType = "com.apple.product-type.framework"; 1651 | }; 1652 | "ParserPrinter::Syntax" = { 1653 | isa = "PBXNativeTarget"; 1654 | buildConfigurationList = "OBJ_129"; 1655 | buildPhases = ( 1656 | "OBJ_132", 1657 | "OBJ_136" 1658 | ); 1659 | dependencies = ( 1660 | "OBJ_139", 1661 | "OBJ_140" 1662 | ); 1663 | name = "Syntax"; 1664 | productName = "Syntax"; 1665 | productReference = "ParserPrinter::Syntax::Product"; 1666 | productType = "com.apple.product-type.framework"; 1667 | }; 1668 | "ParserPrinter::Syntax::Product" = { 1669 | isa = "PBXFileReference"; 1670 | path = "Syntax.framework"; 1671 | sourceTree = "BUILT_PRODUCTS_DIR"; 1672 | }; 1673 | "ParserPrinter::SyntaxTests" = { 1674 | isa = "PBXNativeTarget"; 1675 | buildConfigurationList = "OBJ_141"; 1676 | buildPhases = ( 1677 | "OBJ_144", 1678 | "OBJ_147" 1679 | ); 1680 | dependencies = ( 1681 | "OBJ_151", 1682 | "OBJ_152", 1683 | "OBJ_153" 1684 | ); 1685 | name = "SyntaxTests"; 1686 | productName = "SyntaxTests"; 1687 | productReference = "ParserPrinter::SyntaxTests::Product"; 1688 | productType = "com.apple.product-type.bundle.unit-test"; 1689 | }; 1690 | "ParserPrinter::SyntaxTests::Product" = { 1691 | isa = "PBXFileReference"; 1692 | path = "SyntaxTests.xctest"; 1693 | sourceTree = "BUILT_PRODUCTS_DIR"; 1694 | }; 1695 | "ParserPrinter::URLRequestRouter" = { 1696 | isa = "PBXNativeTarget"; 1697 | buildConfigurationList = "OBJ_155"; 1698 | buildPhases = ( 1699 | "OBJ_158", 1700 | "OBJ_161" 1701 | ); 1702 | dependencies = ( 1703 | "OBJ_165", 1704 | "OBJ_166", 1705 | "OBJ_167" 1706 | ); 1707 | name = "URLRequestRouter"; 1708 | productName = "URLRequestRouter"; 1709 | productReference = "ParserPrinter::URLRequestRouter::Product"; 1710 | productType = "com.apple.product-type.framework"; 1711 | }; 1712 | "ParserPrinter::URLRequestRouter::Product" = { 1713 | isa = "PBXFileReference"; 1714 | path = "URLRequestRouter.framework"; 1715 | sourceTree = "BUILT_PRODUCTS_DIR"; 1716 | }; 1717 | "ParserPrinter::URLRequestRouterTests" = { 1718 | isa = "PBXNativeTarget"; 1719 | buildConfigurationList = "OBJ_168"; 1720 | buildPhases = ( 1721 | "OBJ_171", 1722 | "OBJ_174" 1723 | ); 1724 | dependencies = ( 1725 | "OBJ_179", 1726 | "OBJ_180", 1727 | "OBJ_181", 1728 | "OBJ_182" 1729 | ); 1730 | name = "URLRequestRouterTests"; 1731 | productName = "URLRequestRouterTests"; 1732 | productReference = "ParserPrinter::URLRequestRouterTests::Product"; 1733 | productType = "com.apple.product-type.bundle.unit-test"; 1734 | }; 1735 | "ParserPrinter::URLRequestRouterTests::Product" = { 1736 | isa = "PBXFileReference"; 1737 | path = "URLRequestRouterTests.xctest"; 1738 | sourceTree = "BUILT_PRODUCTS_DIR"; 1739 | }; 1740 | }; 1741 | rootObject = "OBJ_1"; 1742 | } 1743 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/xcshareddata/xcschemes/ParserPrinter-Package.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 71 | 77 | 78 | 79 | 81 | 87 | 88 | 89 | 90 | 91 | 101 | 102 | 108 | 109 | 111 | 112 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /ParserPrinter.xcodeproj/xcshareddata/xcschemes/generate-partial-isos.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 55 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 74 | 75 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /ParserPrinter.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ParserPrinter.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ↔️ Parser-Printer 2 | 3 | [![Swift 4.2](https://img.shields.io/badge/swift-4.2-ED523F.svg?style=flat)](https://swift.org/download/) [![iOS/macOS/tvOS CI](https://img.shields.io/circleci/project/github/pointfreeco/swift-parser-printer/master.svg?label=ios/macos/tvos)](https://circleci.com/gh/pointfreeco/swift-parser-printer) [![Linux CI](https://img.shields.io/travis/pointfreeco/swift-parser-printer/master.svg?label=linux)](https://travis-ci.org/pointfreeco/swift-parser-printer) [![@pointfreeco](https://img.shields.io/badge/contact-@pointfreeco-5AA9E7.svg?style=flat)](https://twitter.com/pointfreeco) 4 | 5 | Parse _and_ print at the same time! 6 | 7 | ⚠️ This is a work in progress, not ready for use. ⚠️ 8 | -------------------------------------------------------------------------------- /Sources/GeneratePartialIsos/GeneratePartialIsos.swift: -------------------------------------------------------------------------------- 1 | import SwiftSyntax 2 | 3 | public final class Visitor: SyntaxVisitor { 4 | private var `enum` = "" 5 | public private(set) var out = "import PartialIso\n" 6 | 7 | override public func visit(_ node: EnumDeclSyntax) { 8 | self.enum = node.identifier.text 9 | super.visit(node) 10 | } 11 | 12 | override public func visit(_ node: EnumCaseElementSyntax) { 13 | if let associatedValue = node.associatedValue { 14 | let type: String 15 | if associatedValue.parameterList.count == 1 { 16 | type = associatedValue.parameterList[0].type?.description ?? "" 17 | } else { 18 | type = "(" 19 | + associatedValue.parameterList 20 | .map { param -> String in 21 | let name = param.firstName.map { $0.text + ": " } ?? "" 22 | let type = param.type?.description ?? "" 23 | return name + type 24 | } 25 | .joined(separator: ", ") 26 | + ")" 27 | } 28 | 29 | self.out += """ 30 | extension PartialIso where A == \(type), B == \(self.enum) { 31 | static let \(node.identifier.text) = PartialIso( 32 | apply: \(self.enum).\(node.identifier.text), 33 | unapply: { 34 | guard case let .\(node.identifier.text)(value) = $0 else { return nil } 35 | return value 36 | } 37 | ) 38 | } 39 | 40 | """ 41 | } else { 42 | self.out += """ 43 | extension PartialIso where A == Void, B == \(self.enum) { 44 | static let \(node.identifier.text) = PartialIso( 45 | apply: { .\(node.identifier.text) }, 46 | unapply: { 47 | guard case .\(node.identifier.text) = $0 else { return nil } 48 | return () 49 | } 50 | ) 51 | } 52 | 53 | """ 54 | } 55 | super.visit(node) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Sources/PartialIso/ExpressibleByStringLiteral.swift: -------------------------------------------------------------------------------- 1 | extension PartialIso: ExpressibleByUnicodeScalarLiteral where A == String, B == () { 2 | public init(unicodeScalarLiteral value: String) { 3 | self = PartialIso.init( 4 | apply: { str in str == value ? () : nil }, 5 | unapply: { _ in value } 6 | ) 7 | } 8 | 9 | public typealias UnicodeScalarLiteralType = String.UnicodeScalarLiteralType 10 | } 11 | 12 | 13 | extension PartialIso: ExpressibleByExtendedGraphemeClusterLiteral where A == String, B == () { 14 | public typealias ExtendedGraphemeClusterLiteralType = String.ExtendedGraphemeClusterLiteralType 15 | 16 | public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) { 17 | let value = String(value) 18 | self = PartialIso.init( 19 | apply: { str in str == value ? () : nil }, 20 | unapply: { _ in value } 21 | ) 22 | } 23 | } 24 | 25 | extension PartialIso: ExpressibleByStringLiteral where A == String, B == () { 26 | public typealias StringLiteralType = String 27 | 28 | public init(stringLiteral value: String) { 29 | self = PartialIso.init( 30 | apply: { str in str == value ? () : nil }, 31 | unapply: { _ in value } 32 | ) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Sources/PartialIso/Flatten.swift: -------------------------------------------------------------------------------- 1 | extension PartialIso { 2 | public static func leftFlatten() -> PartialIso where A == ((C, D), E), B == (C, D, E) { 3 | return PartialIso( 4 | apply: { tuple in 5 | (tuple.0.0, tuple.0.1, tuple.1) 6 | }, unapply: { tuple in 7 | ((tuple.0, tuple.1), tuple.2) 8 | }) 9 | } 10 | 11 | public static func leftFlatten() -> PartialIso where A == (((C, D), E), F), B == (C, D, E, F) { 12 | return PartialIso( 13 | apply: { tuple in 14 | (tuple.0.0.0, tuple.0.0.1, tuple.0.1, tuple.1) 15 | }, unapply: { tuple in 16 | (((tuple.0, tuple.1), tuple.2), tuple.3) 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/PartialIso/PartialIso.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct PartialIso { 4 | public let apply: (A) -> B? 5 | public let unapply: (B) -> A? 6 | 7 | public init(apply: @escaping (A) -> B?, unapply: @escaping (B) -> A?) { 8 | self.apply = apply 9 | self.unapply = unapply 10 | } 11 | } 12 | 13 | extension PartialIso { 14 | public init(case: @escaping (A) -> B) { 15 | self.init(apply: `case`) { root in 16 | guard 17 | let (label, anyValue) = Mirror(reflecting: root).children.first, 18 | let value = anyValue as? A 19 | ?? Mirror(reflecting: anyValue).children.first?.value as? A, 20 | Mirror(reflecting: `case`(value)).children.first?.label == label 21 | else { return nil } 22 | return value 23 | } 24 | } 25 | 26 | /// Inverts the partial isomorphism. 27 | public var inverted: PartialIso { 28 | return .init(apply: self.unapply, unapply: self.apply) 29 | } 30 | 31 | /// A partial isomorphism between `(A, B)` and `(B, A)`. 32 | public static var commute: PartialIso<(A, B), (B, A)> { 33 | return .init( 34 | apply: { ($1, $0) }, 35 | unapply: { ($1, $0) } 36 | ) 37 | } 38 | 39 | public static func pipe(_ lhs: PartialIso, _ rhs: PartialIso) -> PartialIso { 40 | return PartialIso( 41 | apply: { a in 42 | lhs.apply(a).flatMap(rhs.apply) 43 | }, 44 | unapply: { c in 45 | rhs.unapply(c).flatMap(lhs.unapply) 46 | }) 47 | } 48 | 49 | public static func compose(_ lhs: PartialIso, _ rhs: PartialIso) -> PartialIso { 50 | return PartialIso( 51 | apply: { a in 52 | rhs.apply(a).flatMap(lhs.apply) 53 | }, 54 | unapply: { c in 55 | lhs.unapply(c).flatMap(rhs.unapply) 56 | }) 57 | } 58 | 59 | public static func ?? (lhs: PartialIso, rhs: PartialIso) -> PartialIso { 60 | return PartialIso( 61 | apply: { return lhs.apply($0) ?? rhs.apply($0) }, 62 | unapply: { return rhs.unapply($0) ?? lhs.unapply($0) } 63 | ) 64 | } 65 | } 66 | 67 | extension PartialIso where B == A? { 68 | public static var some: PartialIso { 69 | return PartialIso( 70 | apply: Optional.some, 71 | unapply: { $0 } 72 | ) 73 | } 74 | } 75 | 76 | extension PartialIso { 77 | public static func optional(_ iso: PartialIso) -> PartialIso where A == A0?, B == B0? { 78 | return PartialIso( 79 | apply: { .some($0.flatMap(iso.apply)) }, 80 | unapply: { .some($0.flatMap(iso.unapply)) } 81 | ) 82 | } 83 | 84 | public static func require(_ iso: PartialIso) -> PartialIso where A == A0? { 85 | return PartialIso( 86 | apply: { $0.flatMap(iso.apply) }, 87 | unapply: iso.unapply 88 | ) 89 | } 90 | } 91 | 92 | extension PartialIso where A == B { 93 | /// The identity partial isomorphism. 94 | public static var id: PartialIso { 95 | return .init(apply: { $0 }, unapply: { $0 }) 96 | } 97 | } 98 | 99 | extension PartialIso { 100 | public static func const(_ b: B) -> PartialIso { 101 | return PartialIso( 102 | apply: { _ in b }, 103 | unapply: { _ in nil } 104 | ) 105 | } 106 | } 107 | 108 | extension PartialIso where B == (A, ()) { 109 | /// An isomorphism between `A` and `(A, Unit)`. 110 | public static var unit: PartialIso { 111 | return .init( 112 | apply: { ($0, ()) }, 113 | unapply: { $0.0 } 114 | ) 115 | } 116 | } 117 | 118 | extension PartialIso where A == String, B == String { 119 | public static let string = id 120 | } 121 | 122 | extension PartialIso where A == String, B: LosslessStringConvertible { 123 | public static var losslessStringConvertible: PartialIso { 124 | return PartialIso( 125 | apply: B.init, 126 | unapply: String.init 127 | ) 128 | } 129 | } 130 | 131 | extension PartialIso where B: RawRepresentable, B.RawValue == A { 132 | public static var rawRepresentable: PartialIso { 133 | return PartialIso( 134 | apply: B.init(rawValue:), 135 | unapply: { $0.rawValue } 136 | ) 137 | } 138 | } 139 | 140 | extension PartialIso where A == String, B == Bool { 141 | public static let bool = losslessStringConvertible 142 | } 143 | 144 | extension PartialIso where A == String, B == Int { 145 | public static let int = losslessStringConvertible 146 | } 147 | 148 | extension PartialIso where A == String, B == Int64 { 149 | public static let int64 = losslessStringConvertible 150 | } 151 | 152 | extension PartialIso where A == String, B == Int32 { 153 | public static let int32 = losslessStringConvertible 154 | } 155 | 156 | extension PartialIso where A == String, B == Int16 { 157 | public static let int16 = losslessStringConvertible 158 | } 159 | 160 | extension PartialIso where A == String, B == Int8 { 161 | public static let int32 = losslessStringConvertible 162 | } 163 | 164 | extension PartialIso where A == String, B == UInt64 { 165 | public static let uint64 = losslessStringConvertible 166 | } 167 | 168 | extension PartialIso where A == String, B == UInt32 { 169 | public static let uint32 = losslessStringConvertible 170 | } 171 | 172 | extension PartialIso where A == String, B == UInt16 { 173 | public static let uint16 = losslessStringConvertible 174 | } 175 | 176 | extension PartialIso where A == String, B == UInt8 { 177 | public static let uint32 = losslessStringConvertible 178 | } 179 | 180 | extension PartialIso where A == String, B == Double { 181 | public static let double = losslessStringConvertible 182 | } 183 | 184 | extension PartialIso where A == String, B == Float { 185 | public static let float = losslessStringConvertible 186 | } 187 | 188 | extension PartialIso where A == String, B == Float80 { 189 | public static let float80 = losslessStringConvertible 190 | } 191 | 192 | extension PartialIso where A == String, B == UUID { 193 | public static var uuid: PartialIso { 194 | return PartialIso( 195 | apply: UUID.init(uuidString:), 196 | unapply: { $0.uuidString } 197 | ) 198 | } 199 | } 200 | 201 | extension PartialIso where A == Data, B: Codable { 202 | public static func json(_ type: B.Type, decoder: JSONDecoder = .init(), encoder: JSONEncoder = .init()) -> PartialIso { 203 | return PartialIso( 204 | apply: { try? decoder.decode(B.self, from: $0) }, 205 | unapply: { try? encoder.encode($0) } 206 | ) 207 | } 208 | 209 | public static var json: PartialIso { 210 | return self.json(B.self) 211 | } 212 | } 213 | 214 | extension PartialIso { 215 | public static func filter(_ isIncluded: @escaping (A) -> Bool) -> PartialIso<[A], [A]> { 216 | return PartialIso<[A], [A]>( 217 | apply: { $0.filter(isIncluded) }, 218 | unapply: { $0 } 219 | ) 220 | } 221 | 222 | public static func first(where predicate: @escaping (A) -> Bool) -> PartialIso<[A], A> { 223 | return PartialIso<[A], A>( 224 | apply: { $0.first(where: predicate) }, 225 | unapply: { [$0] } 226 | ) 227 | } 228 | 229 | public static func key(_ key: K) -> PartialIso<[K: V], V> { 230 | return PartialIso<[K: V], V>( 231 | apply: { $0[key] }, 232 | unapply: { [key: $0] } 233 | ) 234 | } 235 | } 236 | 237 | extension PartialIso where A == String, B == Data { 238 | public static func data(_ encoding: String.Encoding) -> PartialIso { 239 | return PartialIso( 240 | apply: { $0.data(using: encoding) }, 241 | unapply: { String(data: $0, encoding: encoding) } 242 | ) 243 | } 244 | } 245 | 246 | extension PartialIso where A == String, B == String { 247 | public static func percentEncoding(withAllowedCharacters characters: CharacterSet) -> PartialIso { 248 | return PartialIso( 249 | apply: { $0.addingPercentEncoding(withAllowedCharacters: characters) }, 250 | unapply: { $0.removingPercentEncoding } 251 | ) 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /Sources/Syntax/Numeric.swift: -------------------------------------------------------------------------------- 1 | extension Syntax where A == Int, M == String { 2 | /// Consumes an integer from the front of the string. 3 | public static let int = Syntax.init( 4 | monoid: .joined, 5 | parse: { str in 6 | let prefix = str.prefix(while: { ("0"..."9").contains($0) }) 7 | str.removeFirst(prefix.count) 8 | return Int(String(prefix)) 9 | }, 10 | print: { "\($0)" } 11 | ) 12 | } 13 | 14 | extension Syntax where A == Double, M == String { 15 | /// Consumes a double from the front of the string. 16 | public static let double = Syntax.init( 17 | monoid: .joined, 18 | parse: { str in 19 | let prefix = str.prefix(while: { ("0"..."9").contains($0) || $0 == "." }) 20 | str.removeFirst(prefix.count) 21 | return Double(String(prefix)) 22 | }, 23 | print: { "\($0)" } 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Syntax/String.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Syntax where A == (), M == String { 4 | /// Parses a single string literal from the front of the string, and prints that string literal. 5 | public static func lit(_ s: String) -> Syntax<(), String> { 6 | return Syntax<(), String>.init( 7 | monoid: .joined, 8 | parse: { str in 9 | let hasPrefix = str.hasPrefix(s) 10 | if str.count >= s.count { str.removeFirst(s.count) } 11 | return hasPrefix ? () : nil 12 | }, 13 | print: { _ in s } 14 | ) 15 | } 16 | 17 | /// Parses all whitespace from the front of the string, and prints the preferred number of spaces. 18 | public static func ws(preferred: Int) -> Syntax<(), String> { 19 | return Syntax<(), String>.init( 20 | monoid: .joined, 21 | parse: { str in 22 | let trimIndex = str 23 | .firstIndex(where: { !$0.unicodeScalars.allSatisfy(CharacterSet.whitespaces.contains) }) 24 | ?? str.endIndex 25 | str.removeSubrange(.. Syntax { 42 | return Syntax( 43 | monoid: .joined, 44 | parse: { str in 45 | guard length <= str.count else { return nil } 46 | let result = String(str[.. Bool) -> Syntax { 54 | return Syntax( 55 | monoid: .joined, 56 | parse: { str in 57 | let endIndex = str.firstIndex(where: p) ?? str.endIndex 58 | let result = String(str[..: SyntaxOperator 6 | infix operator %>: SyntaxOperator 7 | infix operator <%: SyntaxOperator 8 | 9 | public struct Syntax { 10 | public let monoid: Monoid 11 | public let _parse: (inout M) -> A? 12 | public let _print: (A) -> M? 13 | 14 | public init(monoid: Monoid, parse: @escaping (inout M) -> A?, print: @escaping (A) -> M?) { 15 | self.monoid = monoid 16 | self._parse = parse 17 | self._print = print 18 | } 19 | 20 | public func parse(_ m: M) -> A? { 21 | var m = m 22 | guard let match = self._parse(&m) else { return nil } 23 | guard m == self.monoid.empty else { return nil } 24 | return match 25 | } 26 | 27 | public func run(_ m: M) -> (M, A?) { 28 | var m = m 29 | let match = self._parse(&m) 30 | return (m, match) 31 | } 32 | 33 | public func print(_ a: A) -> M? { 34 | return self._print(a) 35 | } 36 | 37 | public func map( 38 | _ f: @escaping (A) -> B?, 39 | _ g: @escaping (B) -> A? 40 | ) -> Syntax { 41 | 42 | return Syntax( 43 | monoid: self.monoid, 44 | parse: { m in 45 | let possibleMatch = self._parse(&m) 46 | guard let match = possibleMatch else { return nil } 47 | return f(match) 48 | }, 49 | print: { b in 50 | g(b).flatMap(self._print) 51 | }) 52 | } 53 | 54 | public func map(_ iso: PartialIso) -> Syntax { 55 | return self.map(iso.apply, iso.unapply) 56 | } 57 | 58 | public func keep(and other: Syntax) -> Syntax<(A, B), M> { 59 | return self <%> other 60 | } 61 | public static func <%>(_ lhs: Syntax, _ rhs: Syntax) -> Syntax<(A, B), M> { 62 | return Syntax<(A, B), M>( 63 | monoid: lhs.monoid, 64 | parse: { m in 65 | guard let a = lhs._parse(&m) else { return nil } 66 | guard let b = rhs._parse(&m) else { return nil } 67 | return (a, b) 68 | }, 69 | print: { a, b in 70 | let lhsPrint = lhs._print(a) 71 | let rhsPrint = rhs._print(b) 72 | return Optional.zip(with: lhs.monoid.combine, lhsPrint, rhsPrint) 73 | // TODO: are these needed? 74 | // ?? lhsPrint 75 | // ?? rhsPrint 76 | }) 77 | } 78 | 79 | public static func <%>(_ lhs: Syntax, _ rhs: Syntax<(), M>) -> Syntax { 80 | return Syntax( 81 | monoid: lhs.monoid, 82 | parse: { m in 83 | guard let a = lhs._parse(&m) else { return nil } 84 | guard let _ = rhs._parse(&m) else { return nil } 85 | return a 86 | }, 87 | print: { a in 88 | let lhsPrint = lhs._print(a) 89 | let rhsPrint = rhs._print(()) 90 | return Optional.zip(with: lhs.monoid.combine, lhsPrint, rhsPrint) 91 | // TODO: are these needed? 92 | // ?? lhsPrint 93 | // ?? rhsPrint 94 | }) 95 | } 96 | 97 | public func keep(discarding: Syntax<(), M>) -> Syntax { 98 | return self <% discarding 99 | } 100 | public static func <%(_ lhs: Syntax, _ rhs: Syntax<(), M>) -> Syntax { 101 | return Syntax( 102 | monoid: lhs.monoid, 103 | parse: { m in 104 | guard let a = lhs._parse(&m) else { return nil } 105 | guard let _ = rhs._parse(&m) else { return nil } 106 | return a 107 | }, 108 | print: { a in 109 | let lhsPrint = lhs._print(a) 110 | let rhsPrint = rhs._print(()) 111 | return Optional.zip(with: lhs.monoid.combine, lhsPrint, rhsPrint) 112 | // TODO: are these needed? 113 | // ?? lhsPrint 114 | // ?? rhsPrint 115 | }) 116 | } 117 | 118 | public func or(_ other: @escaping @autoclosure () -> Syntax) -> Syntax { 119 | return Syntax( 120 | monoid: self.monoid, 121 | parse: { m in 122 | let copy = m 123 | if let a = self._parse(&m) { return a } 124 | m = copy 125 | return other()._parse(&m) 126 | }, 127 | print: { m in self._print(m) ?? other()._print(m) } 128 | ) 129 | } 130 | } 131 | 132 | extension Syntax where A == () { 133 | public func discard(keeping other: Syntax) -> Syntax { 134 | return self %> other 135 | } 136 | public static func %>(_ lhs: Syntax, _ rhs: Syntax) -> Syntax { 137 | return Syntax( 138 | monoid: lhs.monoid, 139 | parse: { m in 140 | guard let _ = lhs._parse(&m) else { return nil } 141 | guard let a = rhs._parse(&m) else { return nil } 142 | return a 143 | }, 144 | print: { a in 145 | let lhsPrint = lhs._print(()) 146 | let rhsPrint = rhs._print(a) 147 | return Optional.zip(with: lhs.monoid.combine, lhsPrint, rhsPrint) 148 | // TODO: are these needed? 149 | // ?? lhsPrint 150 | // ?? rhsPrint 151 | }) 152 | } 153 | public static func <%>(_ lhs: Syntax, _ rhs: Syntax) -> Syntax { 154 | return Syntax( 155 | monoid: lhs.monoid, 156 | parse: { m in 157 | guard let _ = lhs._parse(&m) else { return nil } 158 | guard let a = rhs._parse(&m) else { return nil } 159 | return a 160 | }, 161 | print: { a in 162 | let lhsPrint = lhs._print(()) 163 | let rhsPrint = rhs._print(a) 164 | return Optional.zip(with: lhs.monoid.combine, lhsPrint, rhsPrint) 165 | // TODO: are these needed? 166 | // ?? lhsPrint 167 | // ?? rhsPrint 168 | }) 169 | } 170 | } 171 | 172 | extension Optional { 173 | fileprivate static func zip( 174 | with f: @escaping (Wrapped, B) -> C, 175 | _ a: Wrapped?, 176 | _ b: B?) -> C? { 177 | guard let a = a, let b = b else { return nil } 178 | return f(a, b) 179 | } 180 | } 181 | 182 | extension Syntax { 183 | public init(_ monoid: Monoid) { 184 | self = Syntax.init( 185 | monoid: monoid, 186 | parse: { _ in nil }, 187 | print: { _ in nil } 188 | ) 189 | } 190 | } 191 | 192 | extension Syntax { 193 | /// Runs a syntax multiple times on the input until it can't be run anymore. 194 | public static func many(_ syntax: Syntax) -> Syntax where A == [Element] { 195 | return Syntax( 196 | monoid: syntax.monoid, 197 | parse: { m in 198 | var result: [Element] = [] 199 | while (true) { 200 | let copy = m 201 | if let a = syntax._parse(&m) { result.append(a); continue } 202 | m = copy 203 | break 204 | } 205 | return result 206 | 207 | }, print: { xs in 208 | return xs.reduce(syntax.monoid.empty) { accum, x in 209 | syntax.monoid.combine(accum, syntax._print(x) ?? syntax.monoid.empty) 210 | } 211 | }) 212 | } 213 | 214 | /// Runs a syntax multiple times on the input, separated by runs of the `separatedBy` syntax. 215 | public static func many( 216 | _ syntax: Syntax, 217 | separatedBy: Syntax<(), M> 218 | ) -> Syntax where A == [Element] { 219 | 220 | return Syntax( 221 | monoid: syntax.monoid, 222 | parse: { m in 223 | var result: [Element] = [] 224 | while (true) { 225 | let copy = m 226 | if let a = syntax._parse(&m), let _ = separatedBy._parse(&m) { result.append(a); continue } 227 | m = copy 228 | if let a = syntax._parse(&m) { result.append(a); break } 229 | m = copy 230 | break 231 | } 232 | return result 233 | 234 | }, print: { xs in 235 | var idx = 0 236 | return xs.reduce(into: syntax.monoid.empty) { accum, x in 237 | if idx > 0 { 238 | syntax.monoid.mcombine(&accum, separatedBy._print(()) ?? syntax.monoid.empty) 239 | } 240 | syntax.monoid.mcombine(&accum, syntax._print(x) ?? syntax.monoid.empty) 241 | idx += 1 242 | } 243 | }) 244 | } 245 | } 246 | 247 | extension Syntax { 248 | public func flatten() -> Syntax<(B, C, D), M> where A == ((B, C), D) { 249 | return self.map(.leftFlatten()) 250 | } 251 | 252 | public func flatten() -> Syntax<(B, C, D, E), M> where A == (((B, C), D), E) { 253 | return self.map(.leftFlatten()) 254 | } 255 | } 256 | 257 | extension Syntax { 258 | public func flatten( 259 | _ apply: @escaping (B, C, D) -> Z, 260 | _ unapply: @escaping (Z) -> (B, C, D) 261 | ) -> Syntax where A == ((B, C), D) { 262 | 263 | return self.flatten().map(apply, unapply) 264 | } 265 | 266 | public func flatten( 267 | _ apply: @escaping (B, C, D, E) -> Z, 268 | _ unapply: @escaping (Z) -> (B, C, D, E) 269 | ) -> Syntax where A == (((B, C), D), E) { 270 | 271 | return self.flatten().map(apply, unapply) 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /Sources/URLRequestRouter/RequestData.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Monoid 3 | import Syntax 4 | import PartialIso 5 | 6 | public struct Method: RawRepresentable, Equatable { 7 | public let rawValue: String 8 | 9 | public init(rawValue: String) { 10 | self.rawValue = rawValue 11 | } 12 | 13 | public static let get = Method(rawValue: "GET") 14 | public static let head = Method(rawValue: "HEAD") 15 | public static let post = Method(rawValue: "POST") 16 | public static let put = Method(rawValue: "PUT") 17 | public static let patch = Method(rawValue: "PATCH") 18 | public static let delete = Method(rawValue: "DELETE") 19 | } 20 | 21 | public struct RequestData: Equatable { 22 | public var method: Method? 23 | public var path: [String] 24 | public var query: [(key: String, value: String?)] 25 | public var body: Data? 26 | 27 | public init( 28 | method: Method? = nil, 29 | path: [String] = [], 30 | query: [(key: String, value: String?)] = [], 31 | body: Data? = nil) { 32 | 33 | self.method = method 34 | self.path = path 35 | self.query = query 36 | self.body = body 37 | } 38 | 39 | public static func == (lhs: RequestData, rhs: RequestData) -> Bool { 40 | return lhs.method == rhs.method 41 | && lhs.path == rhs.path 42 | && lhs.query.count == rhs.query.count 43 | && zip(lhs.query, rhs.query).reduce(true) { $0 && $1.0 == $1.1 } 44 | && lhs.body == rhs.body 45 | } 46 | 47 | public var urlRequest: URLRequest? { 48 | return self.urlRequest() 49 | } 50 | 51 | public func urlRequest(baseUrl: URL? = nil) -> URLRequest? { 52 | let url = self.path.isEmpty && self.query.isEmpty 53 | ? (baseUrl ?? URL(string: "/")) 54 | : self.urlComponents.url(relativeTo: baseUrl) 55 | 56 | return url.map { url in 57 | var request = URLRequest(url: url) 58 | request.httpMethod = self.method?.rawValue 59 | request.httpBody = self.body 60 | return request 61 | } 62 | } 63 | 64 | private var urlComponents: URLComponents { 65 | var components = URLComponents() 66 | components.path = self.path.joined(separator: "/") 67 | 68 | let query = self.query.filter { $0.value != nil } 69 | if !query.isEmpty { 70 | components.queryItems = query.map(URLQueryItem.init(name:value:)) 71 | } 72 | 73 | return components 74 | } 75 | } 76 | 77 | extension RequestData { 78 | public init(request: URLRequest) { 79 | self.method = request.httpMethod.map(Method.init(rawValue:)) ?? .get 80 | 81 | guard let url = request.url else { 82 | self.path = [] 83 | self.query = [] 84 | self.body = nil 85 | return 86 | } 87 | 88 | self.path = url.path 89 | .split(separator: "/", omittingEmptySubsequences: true) 90 | .map(String.init) 91 | 92 | self.query = (URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems ?? []) 93 | .map { item in (key: item.name, value: item.value) } 94 | 95 | self.body = request.httpBody 96 | } 97 | 98 | public init(url: URL) { 99 | self.init(request: URLRequest(url: url)) 100 | } 101 | } 102 | 103 | extension Monoid where A == RequestData { 104 | public static let requestData = Monoid( 105 | empty: RequestData(), 106 | combine: { lhs, rhs in 107 | return .init( 108 | method: lhs.method ?? rhs.method, 109 | path: lhs.path + rhs.path, 110 | query: lhs.query + rhs.query, 111 | // TODO: is coalescing enough or should we be appending? 112 | body: lhs.body ?? rhs.body 113 | ) 114 | }) 115 | } 116 | -------------------------------------------------------------------------------- /Sources/URLRequestRouter/URLRequestRouter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Monoid 3 | import Syntax 4 | import PartialIso 5 | 6 | infix operator : SyntaxOperator 7 | infix operator : SyntaxOperator 8 | infix operator <&>: SyntaxOperator 9 | 10 | public typealias Router = Syntax 11 | 12 | extension Syntax where M == RequestData { 13 | 14 | public func match(request: URLRequest) -> A? { 15 | return self.route(requestData: RequestData(request: request)) 16 | } 17 | 18 | public func match(url: URL) -> A? { 19 | return self.match(request: URLRequest(url: url)) 20 | } 21 | 22 | public func match(urlString: String) -> A? { 23 | return URL(string: urlString).flatMap(self.match(url:)) 24 | } 25 | 26 | public func request(for a: A) -> URLRequest? { 27 | return self._print(a).flatMap { $0.urlRequest } 28 | } 29 | 30 | public func url(for a: A) -> URL? { 31 | return self._print(a).flatMap { $0.urlRequest?.url } 32 | } 33 | 34 | public func urlString(for a: A) -> String? { 35 | return self._print(a).flatMap { $0.urlRequest?.url?.absoluteString } 36 | } 37 | 38 | /* todo: public? */ func route(requestData: RequestData) -> A? { 39 | var requestData = requestData 40 | guard let match = (self <% .end)._parse(&requestData) else { return nil } 41 | guard requestData == self.monoid.empty else { return nil } 42 | return match 43 | } 44 | 45 | public init(parse: @escaping (inout RequestData) -> A?, print: @escaping (A) -> RequestData?) { 46 | self.init(monoid: .requestData, parse: parse, print: print) 47 | } 48 | 49 | public init(_ routes: Syntax...) { 50 | self = routes.reduce(into: .init(.requestData)) { $0 = $0.or($1) } 51 | } 52 | 53 | // public static func match(_ f: PartialIso, to syntax: Syntax) -> Syntax { 54 | // return (syntax <% .end).map(f) 55 | // } 56 | 57 | public static func match(_ f: A, to syntax: Syntax) -> Syntax { 58 | return (syntax <% .end).map(PartialIso(case: { _ in f })) 59 | } 60 | 61 | public static func match(_ f: @escaping (A0) -> A, to syntax: Syntax) -> Syntax { 62 | return (syntax <% .end).map(PartialIso(case: f)) 63 | } 64 | 65 | public static func pathParam(_ iso: PartialIso) -> Syntax { 66 | return Syntax( 67 | parse: { request in 68 | guard !request.path.isEmpty else { return nil } 69 | let path = request.path.removeFirst() 70 | return iso.apply(path) 71 | }, print: { a in 72 | RequestData( 73 | path: iso.unapply(a).map { [$0] } ?? [] 74 | ) 75 | }) 76 | } 77 | 78 | public static func queryParam(_ key: String, _ iso: PartialIso) -> Syntax { 79 | return Syntax( 80 | parse: { request in 81 | iso.apply(request.query.first(where: { $0.key == key })?.value) 82 | }, 83 | print: { a in 84 | RequestData( 85 | query: iso.unapply(a).map { [(key, $0)] } ?? [] 86 | ) 87 | } 88 | ) 89 | } 90 | 91 | public static func (lhs: Syntax, rhs: PartialIso) -> Syntax<(A, B), M> { 92 | return lhs <%> .pathParam(rhs) 93 | } 94 | 95 | public static func (lhs: Syntax, rhs: PartialIso) -> Syntax { 96 | return lhs <% .pathParam(rhs) 97 | } 98 | 99 | public static func ( 100 | lhs: Syntax, 101 | rhs: (key: String, iso: PartialIso) 102 | ) -> Syntax<(A, B), M> { 103 | 104 | return lhs <%> .queryParam(rhs.key, rhs.iso) 105 | } 106 | 107 | public static func <&> ( 108 | lhs: Syntax, 109 | rhs: (key: String, iso: PartialIso) 110 | ) -> Syntax<(A, B), M> { 111 | 112 | return lhs <%> .queryParam(rhs.key, rhs.iso) 113 | } 114 | } 115 | 116 | extension Syntax where A == Void, M == RequestData { 117 | 118 | public static func method(_ method: Method) -> Syntax { 119 | return Syntax( 120 | parse: { request in 121 | guard 122 | let requestMethod = request.method, 123 | requestMethod.rawValue.caseInsensitiveCompare(method.rawValue) == .orderedSame 124 | else { return nil } 125 | 126 | request.method = nil 127 | return () 128 | }, print: { a in 129 | return RequestData( 130 | method: .some(method) 131 | ) 132 | }) 133 | } 134 | 135 | public static let get = method(.get).or(method(.head)) 136 | public static let delete = method(.delete) 137 | 138 | public static func (lhs: Syntax, rhs: PartialIso) -> Syntax { 139 | return lhs %> .pathParam(rhs) 140 | } 141 | 142 | public static func ( 143 | lhs: Syntax, 144 | rhs: (key: String, iso: PartialIso) 145 | ) -> Syntax { 146 | 147 | return lhs %> .queryParam(rhs.key, rhs.iso) 148 | } 149 | 150 | public static var end: Syntax { 151 | return Syntax( 152 | parse: { request in 153 | guard request.path.isEmpty else { return nil } 154 | request = Monoid.requestData.empty 155 | return () 156 | }, print: { a in 157 | return Monoid.requestData.empty 158 | }) 159 | } 160 | 161 | } 162 | 163 | extension Syntax where A: Codable, M == RequestData { 164 | 165 | public static func body(_ iso: PartialIso) -> Syntax { 166 | return Syntax( 167 | parse: { request in 168 | guard let body = request.body else { return nil } 169 | request.body = nil 170 | return iso.apply(body) 171 | }, print: { a in 172 | return RequestData(body: iso.unapply(a)) 173 | }) 174 | } 175 | 176 | public static func post(_ iso: PartialIso) -> Syntax { 177 | return .method(.post) %> .body(iso) 178 | } 179 | 180 | public static func put(_ iso: PartialIso) -> Syntax { 181 | return .method(.put) %> .body(iso) 182 | } 183 | 184 | public static func patch(_ iso: PartialIso) -> Syntax { 185 | return .method(.patch) %> .body(iso) 186 | } 187 | 188 | } 189 | -------------------------------------------------------------------------------- /Sources/generate-partial-isos/main.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import GeneratePartialIsos 3 | import SwiftSyntax 4 | 5 | let arguments = CommandLine.arguments.dropFirst() 6 | 7 | guard !arguments.isEmpty else { 8 | fputs("Usage: swift run generate-partial-isos [file.swift ...]\n", stderr) 9 | exit(EXIT_FAILURE) 10 | } 11 | 12 | let visitor = Visitor() 13 | try arguments.forEach { file in 14 | visitor.visit(try SyntaxTreeParser.parse(URL(fileURLWithPath: file))) 15 | } 16 | print(visitor.out) 17 | -------------------------------------------------------------------------------- /Tests/GeneratePartialIsosTests/Fixture.swift: -------------------------------------------------------------------------------- 1 | struct Category { 2 | struct Id { 3 | let id: Int 4 | } 5 | 6 | let name: String 7 | } 8 | 9 | enum Routes { 10 | case home 11 | case episode(id: Int) 12 | case login(username: String, password: String) 13 | case search(String, Category.Id) 14 | case pathological() 15 | } 16 | -------------------------------------------------------------------------------- /Tests/GeneratePartialIsosTests/GeneratePartialIsosTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import GeneratePartialIsos 3 | import SnapshotTesting 4 | import SwiftSyntax 5 | 6 | extension Snapshotting where Value == URL, Format == String { 7 | public static var visitor: Snapshotting { 8 | var strategy: Snapshotting = SimplySnapshotting.lines.pullback { 9 | let visitor = Visitor() 10 | visitor.visit(try! SyntaxTreeParser.parse($0)) 11 | return visitor.out 12 | } 13 | strategy.pathExtension = "swift" 14 | return strategy 15 | } 16 | } 17 | 18 | final class GeneratePartialIsosTests: SnapshotTestCase { 19 | func test() throws { 20 | assertSnapshot( 21 | matching: URL(fileURLWithPath: #file) 22 | .deletingLastPathComponent() 23 | .appendingPathComponent("Fixture.swift"), 24 | as: .visitor 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Tests/GeneratePartialIsosTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | extension GeneratePartialIsosTests { 4 | static let __allTests = [ 5 | ("test", test), 6 | ] 7 | } 8 | 9 | #if !os(macOS) 10 | public func __allTests() -> [XCTestCaseEntry] { 11 | return [ 12 | testCase(GeneratePartialIsosTests.__allTests), 13 | ] 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /Tests/GeneratePartialIsosTests/__Snapshots__/GeneratePartialIsosTests/test.1.swift: -------------------------------------------------------------------------------- 1 | import PartialIso 2 | extension PartialIso where A == Void, B == Routes { 3 | static let home = PartialIso( 4 | apply: { .home }, 5 | unapply: { 6 | guard case .home = $0 else { return nil } 7 | return () 8 | } 9 | ) 10 | } 11 | extension PartialIso where A == Int, B == Routes { 12 | static let episode = PartialIso( 13 | apply: Routes.episode, 14 | unapply: { 15 | guard case let .episode(value) = $0 else { return nil } 16 | return value 17 | } 18 | ) 19 | } 20 | extension PartialIso where A == (username: String, password: String), B == Routes { 21 | static let login = PartialIso( 22 | apply: Routes.login, 23 | unapply: { 24 | guard case let .login(value) = $0 else { return nil } 25 | return value 26 | } 27 | ) 28 | } 29 | extension PartialIso where A == (String, Category.Id), B == Routes { 30 | static let search = PartialIso( 31 | apply: Routes.search, 32 | unapply: { 33 | guard case let .search(value) = $0 else { return nil } 34 | return value 35 | } 36 | ) 37 | } 38 | extension PartialIso where A == (), B == Routes { 39 | static let pathological = PartialIso( 40 | apply: Routes.pathological, 41 | unapply: { 42 | guard case let .pathological(value) = $0 else { return nil } 43 | return value 44 | } 45 | ) 46 | } 47 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import GeneratePartialIsosTests 4 | import PartialIsoTests 5 | import URLRequestRouterTests 6 | import SyntaxTests 7 | 8 | var tests = [XCTestCaseEntry]() 9 | tests += GeneratePartialIsosTests.__allTests() 10 | tests += PartialIsoTests.__allTests() 11 | tests += URLRequestRouterTests.__allTests() 12 | tests += SyntaxTests.__allTests() 13 | 14 | XCTMain(tests) 15 | -------------------------------------------------------------------------------- /Tests/PartialIsoTests/PartialIsoTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import PartialIso 3 | 4 | final class PartialIsoTests: XCTestCase { 5 | func testExpressibleByStringLiteral() { 6 | let partialIso: PartialIso = "foo" 7 | 8 | XCTAssertNotNil(partialIso.apply("foo")) 9 | XCTAssertNil(partialIso.apply("bar")) 10 | XCTAssertEqual("foo", partialIso.unapply(())) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Tests/PartialIsoTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | extension PartialIsoTests { 4 | static let __allTests = [ 5 | ("testExpressibleByStringLiteral", testExpressibleByStringLiteral), 6 | ] 7 | } 8 | 9 | #if !os(macOS) 10 | public func __allTests() -> [XCTestCaseEntry] { 11 | return [ 12 | testCase(PartialIsoTests.__allTests), 13 | ] 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /Tests/SyntaxTests/SyntaxTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Syntax 3 | import PartialIso 4 | 5 | final class swift_parser_printerTests: XCTestCase { 6 | 7 | func testExample() { 8 | let int = Syntax( 9 | monoid: .joined, 10 | parse: { tokens in 11 | tokens.count == 0 ? nil : Int(tokens.removeFirst()) 12 | }, 13 | print: { int in [String(int)] } 14 | ) 15 | 16 | let string = Syntax( 17 | monoid: .joined, 18 | parse: { tokens in 19 | tokens.count == 0 ? nil : tokens.removeFirst() 20 | }, 21 | print: { str in [str] } 22 | ) 23 | 24 | let bool = Syntax( 25 | monoid: .joined, 26 | parse: { tokens in 27 | tokens.count == 0 ? nil : Bool(tokens.removeFirst()) 28 | }, 29 | print: { bool in [String(describing: bool)] } 30 | ) 31 | 32 | let comma = Syntax<(), [String]>( 33 | monoid: .joined, 34 | parse: { tokens in 35 | tokens.count == 0 ? nil : 36 | tokens.removeFirst() == "," ? () : nil 37 | }, 38 | print: { _ in [","] } 39 | ) 40 | 41 | struct User { 42 | let id: Int 43 | let name: String 44 | let admin: Bool 45 | } 46 | 47 | let syntax = (int <%> comma <%> string <%> comma <%> bool) 48 | .flatten(User.init, { ($0.id, $0.name, $0.admin) }) 49 | 50 | let parsed = syntax.parseCsv("123,Hello,true") 51 | let printed = syntax.printCsv(User(id: 1, name: "Hello", admin: true)) 52 | print(parsed as Any) 53 | print(printed as Any) 54 | print("!") 55 | } 56 | 57 | func testUser_Operators() { 58 | 59 | let idSyntax = lit("id:") <%> optWs <%> int <%> lit(",") <%> optWs 60 | let nameSyntax = lit("name:") <%> optWs <%> quotedString <%> lit(",") <%> optWs 61 | let isAdminSyntax = lit("isAdmin:") <%> optWs <%> bool 62 | 63 | let _userSyntax = lit("User(") 64 | <%> idSyntax 65 | <%> nameSyntax 66 | <%> isAdminSyntax 67 | <%> lit(")") 68 | 69 | let userSyntax = _userSyntax.flatten() 70 | 71 | print(userSyntax.print((123, "Blob", true))!) 72 | print(userSyntax.parse("User(id:123,name:\"Blob\",isAdmin:true)")!) 73 | } 74 | 75 | func testUser_NoOperators() { 76 | 77 | 78 | let idSyntax = field(name: "id", syntax: int) 79 | .keep(discarding: lit(",")) 80 | .keep(discarding: optWs) 81 | 82 | let nameSyntax = field(name: "name", syntax: quotedString) 83 | .keep(discarding: lit(",")) 84 | .keep(discarding: optWs) 85 | 86 | let isAdminSyntax = field(name: "isAdmin", syntax: bool) 87 | 88 | let userModelSyntax = lit("User(") 89 | .discard(keeping: idSyntax) 90 | .keep(and: nameSyntax) 91 | .keep(and: isAdminSyntax) 92 | .keep(discarding: lit(")")) 93 | .flatten() 94 | 95 | XCTAssertEqual( 96 | "User(id: 123, name: \"Blob\", isAdmin: true)", 97 | userModelSyntax.print((123, "Blob", true))! 98 | ) 99 | 100 | XCTAssertEqual3( 101 | (123, "Blob", true), 102 | userModelSyntax.parse("User(id:123,name:\"Blob\",isAdmin:true)")! 103 | ) 104 | } 105 | 106 | func testAdventDay1() { 107 | 108 | let signedNumber = (skipWs <%> sign <%> int) 109 | .map({ sign, int in sign.value * int }, { int in (int.sign, abs(int)) }) 110 | 111 | let parser = Syntax.many(signedNumber, separatedBy: lit(",")) 112 | 113 | XCTAssertEqual([1,-1,2,-3], parser.parse("+1,-1,+2,-3")) 114 | XCTAssertEqual("+1,+2,-3,+4", parser.print([1, 2, -3, 4])) 115 | 116 | XCTAssertEqual(1, signedNumber.parse("+1")) 117 | } 118 | } 119 | 120 | import Monoid 121 | extension Syntax { 122 | init(_ a: A, _ monoid: Monoid) { 123 | self = Syntax.init( 124 | monoid: monoid, 125 | parse: { m in m = monoid.empty; return a }, 126 | print: { _ in monoid.empty } 127 | ) 128 | } 129 | } 130 | 131 | import PartialIso 132 | extension PartialIso where A == () { 133 | static func `nil`() -> PartialIso where B == [C] { 134 | return PartialIso<(), [C]>.init( 135 | apply: { _ in [] }, 136 | unapply: { $0.count == 0 ? () : nil } 137 | ) 138 | } 139 | } 140 | extension PartialIso { 141 | static func cons() -> PartialIso where A == (C, [C]), B == [C] { 142 | return PartialIso<(C, [C]), [C]>.init( 143 | apply: { head, tail in [head] + tail }, 144 | unapply: { xs in 145 | guard let head = xs.first else { return nil } 146 | let tail = xs.suffix(from: 1) 147 | return (head, Array(tail)) 148 | } 149 | ) 150 | } 151 | } 152 | 153 | func XCTAssertEqual3( 154 | _ value: (A, B, C), 155 | _ expected: (A, B, C), 156 | file: StaticString = #file, 157 | line: UInt = #line 158 | ) { 159 | 160 | XCTAssertTrue( 161 | value == expected, 162 | "\(value) is not equal to the expected \(expected)", 163 | file: file, 164 | line: line 165 | ) 166 | } 167 | 168 | extension Syntax where M == [String] { 169 | func parseCsv(_ a: String) -> A? { 170 | return self.parse( 171 | Array(a 172 | .split(separator: ",") 173 | .map { [String($0)] } 174 | .joined(separator: [","])) 175 | ) 176 | } 177 | 178 | func printCsv(_ a: A) -> String? { 179 | return self.print(a)?.joined() 180 | } 181 | } 182 | 183 | enum Sign: String, CaseIterable { 184 | case plus = "+" 185 | case minus = "-" 186 | var value: Int { 187 | switch self { 188 | case .plus: return 1 189 | case .minus: return -1 190 | } 191 | } 192 | } 193 | extension Int { 194 | var sign: Sign { 195 | return self >= 0 ? .plus : .minus 196 | } 197 | } 198 | let sign = Syntax( 199 | monoid: .joined, 200 | parse: { str in 201 | let sign = str.count < 1 ? nil : String(str.removeFirst()) 202 | return sign.flatMap(Sign.init(rawValue:)) 203 | }, 204 | print: { sign in sign.rawValue } 205 | ) 206 | 207 | func field(name: String, syntax: Syntax) -> Syntax { 208 | return lit("\(name):") 209 | .discard(keeping: optWs) 210 | .discard(keeping: syntax) 211 | } 212 | 213 | func lit(_ s: String) -> Syntax<(), String> { 214 | return Syntax<(), String>.init( 215 | monoid: .joined, 216 | parse: { str in 217 | let hasPrefix = str.hasPrefix(s) 218 | if str.count >= s.count { str.removeFirst(s.count) } 219 | return hasPrefix ? () : nil 220 | }, 221 | print: { _ in s } 222 | ) 223 | } 224 | 225 | let skipWs = ws(preferred: 0) 226 | let optWs = ws(preferred: 1) 227 | func ws(preferred: Int) -> Syntax<(), String> { 228 | return Syntax<(), String>.init( 229 | monoid: .joined, 230 | parse: { str in 231 | str = str.trimmingCharacters(in: .whitespaces) 232 | return () 233 | }, 234 | print: { _ in String.init(repeating: " ", count: preferred) } 235 | ) 236 | } 237 | 238 | let int = Syntax.init( 239 | monoid: .joined, 240 | parse: { str in 241 | let prefix = str.prefix(while: { (48...57).contains($0.unicodeScalars.first!.value) }) 242 | str.removeFirst(prefix.count) 243 | return Int(String(prefix)) 244 | }, 245 | print: { "\($0)" } 246 | ) 247 | let quotedString = Syntax.init( 248 | monoid: .joined, 249 | parse: { str in 250 | let parts = str.split(separator: "\"", maxSplits: 2) 251 | let (parsed, rest) = (parts.first, parts.last) 252 | str = rest.map(String.init) ?? "" 253 | return parsed.map(String.init) 254 | }, 255 | print: { str in "\"\(str)\"" } 256 | ) 257 | let bool = Syntax.init( 258 | monoid: .joined, 259 | parse: { str in 260 | 261 | if str.hasPrefix("true") { 262 | str.removeFirst(4) 263 | return true 264 | } else if str.hasPrefix("false") { 265 | str.removeFirst(5) 266 | return false 267 | } 268 | 269 | return nil 270 | }, 271 | print: { "\($0)" } 272 | ) 273 | -------------------------------------------------------------------------------- /Tests/SyntaxTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | extension swift_parser_printerTests { 4 | static let __allTests = [ 5 | ("testAdventDay1", testAdventDay1), 6 | ("testExample", testExample), 7 | ("testUser_NoOperators", testUser_NoOperators), 8 | ("testUser_Operators", testUser_Operators), 9 | ] 10 | } 11 | 12 | #if !os(macOS) 13 | public func __allTests() -> [XCTestCaseEntry] { 14 | return [ 15 | testCase(swift_parser_printerTests.__allTests), 16 | ] 17 | } 18 | #endif 19 | -------------------------------------------------------------------------------- /Tests/URLRequestRouterTests/URLRequestRouterTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Syntax 3 | import PartialIso 4 | import URLRequestRouter 5 | 6 | final class URLRequestRouterTests: XCTestCase { 7 | 8 | func test() { 9 | let route = .get "users" .int ("ref", .require(.string)) <%> .end 10 | 11 | XCTAssertEqual( 12 | RequestData(method: .get, path: ["users", "42"], query: [("ref", "pointfreeco")], body: nil), 13 | route.print((42, "pointfreeco")) 14 | ) 15 | XCTAssertEqual( 16 | "users/42?ref=pointfreeco", 17 | route.urlString(for: ((42, "pointfreeco"))) 18 | ) 19 | 20 | let tuple = route.parse(RequestData(method: .get, path: ["users", "42"], query: [("ref", "pointfreeco")], body: nil)) 21 | XCTAssertEqual(42, tuple?.0) 22 | XCTAssertEqual("pointfreeco", tuple?.1) 23 | } 24 | 25 | func testOptionalRouteParam() { 26 | let route = .get "search" ("q", .optional(.string)) 27 | 28 | XCTAssertEqual( 29 | "search", 30 | route.urlString(for: nil) 31 | ) 32 | XCTAssertEqual( 33 | "search?q=blob", 34 | route.urlString(for: "blob") 35 | ) 36 | 37 | XCTAssertEqual( 38 | .some(.none), 39 | route.match(urlString: "/search?q") 40 | ) 41 | XCTAssertEqual( 42 | .some(.none), 43 | route.match(urlString: "/search?") 44 | ) 45 | XCTAssertEqual( 46 | .some(.none), 47 | route.match(urlString: "/search") 48 | ) 49 | XCTAssertEqual( 50 | .some("blob"), 51 | route.match(urlString: "/search?q=blob") 52 | ) 53 | XCTAssertEqual( 54 | .none, 55 | route.match(urlString: "/searchxyz") 56 | ) 57 | } 58 | 59 | func testRequiredRouteParam() { 60 | let route = .get "search" ("q", .require(.string)) 61 | 62 | XCTAssertEqual( 63 | "search?q=blob", 64 | route.urlString(for: "blob") 65 | ) 66 | 67 | XCTAssertEqual( 68 | .none, 69 | route.match(urlString: "/search?q") 70 | ) 71 | XCTAssertEqual( 72 | .none, 73 | route.match(urlString: "/search?") 74 | ) 75 | XCTAssertEqual( 76 | .none, 77 | route.match(urlString: "/search") 78 | ) 79 | XCTAssertEqual( 80 | .some("blob"), 81 | route.match(urlString: "/search?q=blob") 82 | ) 83 | XCTAssertEqual( 84 | .none, 85 | route.match(urlString: "/searchxyz") 86 | ) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Tests/URLRequestRouterTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | extension URLRequestRouterTests { 4 | static let __allTests = [ 5 | ("test", test), 6 | ] 7 | } 8 | 9 | #if !os(macOS) 10 | public func __allTests() -> [XCTestCaseEntry] { 11 | return [ 12 | testCase(URLRequestRouterTests.__allTests), 13 | ] 14 | } 15 | #endif 16 | --------------------------------------------------------------------------------