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 curry(self.init)
<^> json !! "string"
<*> json !? "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 curry
ing, 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)
- Current JSON parsing is 70x~ slower than
- 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)