Parser Takes input data (frequently text) and builds a data structure, e.g. abstract syntax tree (AST) • Lexer • Strings/Bytes → Tokens • Parser • Tokens → Syntax Tree
Combinator • Lambda expression without free variables • I = λx.x = { x in x } • K = λxy.x = { x, y in x } • S = λxyz.xz(yz) = { x, y, z in x(z)(y(z))} • Y = S(K(SII))(S(S(KS)K)(K(SII))) • ι = λx.xSK
Parser Combinator Higher-order function which takes: • Input: Parser(s) • Output: New Parser Combining simple parsers to construct more complex parsers → Functional Programming approach
// Applicative sequential application func <*> (p: Parser B>, q: Parser) -> Parser { return p >>- { f in f <^> q } } // Sequence actions, discarding the value of the second argument func <* (p: Parser, q: Parser) -> Parser { return const <^> p <*> q } // Sequence actions, discarding the value of the first argument func *> (p: Parser, q: Parser) -> Parser { return const(id) <^> p <*> q }
enum JSON enum JSON { case String(Swift.String) case Number(Double) case Bool(Swift.Bool) case Null case Array([JSON]) case Object([Swift.String : JSON]) }
struct Model struct Model { let string: String let num: Double let bool: Bool let null: Any? let array: [Any] let dict: [String : Any] let subModel: SubModel let dummy: Bool? // doesn't exist in raw JSON }
Summary (TryParsec) • Supports CSV / XML / JSON • Simple, readable, and easy to create your own parsers • Caveats • Needs performance improvements • FromJSON / ToJSON doesn't work in some nested structure • Swift 3 (with higher kinded types support) will surely solve this problem!