CocoaPods trunk is moving to be read-only. Read more on the blog, there are 19 months to go.

TryParsec 0.1.0

TryParsec 0.1.0

TestsTested βœ“
LangLanguage SwiftSwift
License MIT
ReleasedLast Release Mar 2016
SPMSupports SPM βœ“

Maintained by Yasuhiro Inami.



TryParsec 0.1.0

  • By
  • Yasuhiro Inami

TryParsec

Monadic Parser Combinator for try! Swift.

  • Inspired by Haskell Attoparsec & Aeson, Swift Argo.
  • Supports CSV, XML, JSON (+ mapping)
  • Doesn’t try, but please try :)

NOTE: This library is still in early development. Please see TODO & FIXME.

Quick Play

Open Examples/TryParsecPlayground.playground.

$ sudo gem install fastlane
$ fastlane play   # prepares Xcode Playground

How to use

// Simple Arithmetic
let ans = parseArithmetic(" ( 12 + 3 )         * 4+5").value
expect(ans) == 65

// CSV
let csv = parseCSV("foo,bar,baz\r\n1,22,333\r\n").value
expect(csv) == [["foo", "bar", "baz"], ["1", "22", "333"]]

// XML
let xmlString = "<p class=\"welcome\"><a href=\"underground.html\" target=\"_blank\">Hello</a><?php echo ' Cruel'; ?> World<!-- πŸ’€ --><![CDATA[πŸ’£->πŸ˜‡]]></p>"
let xml = parseXML(xmlString).value
expect(xml) == [.Element("p", [XML.Attribute("class", "welcome")], [.Element("a", [XML.Attribute("href", "underground.html"), XML.Attribute("target", "_blank")], [.Text("Hello")]), .ProcessingInstruction("php echo ' Cruel'; "), .Text(" World"), .Comment(" πŸ’€ "), .Text("πŸ’£->πŸ˜‡")])]

// JSON
let jsonString = "{ \"string\" : \"hello\", \"array\" : [1, \"two\", [true, null]] }"
let json = parseJSON(jsonString).value
expect(json) == JSON.Object([
    "string" : .String("hello"),
    "array" : .Array([.Number(1), .String("two"), .Array([.Bool(true), .Null])])
])

JSON Decoding & Encoding

import Curry

struct Model: FromJSON, ToJSON
{
    let string: String
    let array: [Any]?

    static func fromJSON(json: JSON) -> Result<Model, JSON.ParseError>
    {
        return fromJSONObject(json) {
            curry(self.init)
                <^> $0 !! "string"
                <*> $0 !? "array"
        }
    }

    static func toJSON(model: Model) -> JSON
    {
        return toJSONObject([
            "string" ~ model.string,
            "array" ~ model.array
        ])
    }
}

let jsonString = "{ \"string\" : \"hello\", \"array\" : [1, \"two\", [true, null]] }"

// JSON String -> Model
let decoded: Result<Model, JSON.ParseError> = decode(jsonString)

// Model -> JSON String
let encoded: String = encode(decoded.value!)

For currying, see thoughtbot/Curry for more information.

Supported functions

  • Basic Operators: >>-, <^>, <*>, *>, <*, <|>, <?>
  • Combinators: zeroOrOne, many, many1, manyTill, skipMany, skipMany1, sepBy, sepBy1, sepEndBy, sepEndBy1, count, chainl, chainl1, chainr, chainr1
  • Text (UnicodeScalarView): peek, endOfInput, satisfy, skip, skipWhile, take, takeWhile, any, char, not, string, asciiCI, oneOf, noneOf, digit, hexDigit, lowerAlphabet, upperAlphabet, alphabet, alphaNum, space, skipSpaces, endOfLine, number

TODO & FIXME

  • Improve overall performance
    • Current JSON parsing is 70x~ slower than NSJSONSerialization (even with whole-module-optimization)

  • Improve error reporting
  • Support indent parser (e.g. YAML)
  • Once apple/swift supports Higher Kinded Types…
    • Support incremental input
    • Remove workarounds e.g. reflection-based JSON encoding

Acknowledgement

This library is heavily inspired by following developers & libraries:

  • Bryan O'Sullivan: Author of Attoparsec & Aeson (Haskell)
  • Daan Leijen: Author of Parsec (Haskell)
  • thoughtbot: Author of Argo (Swift JSON decoding library)

References

Licence

MIT