Slide 1

Slide 1 text

Parser Combinators 1

Slide 2

Slide 2 text

Self Intro » Name: Joshua Kaplan » Interests: ! λ " » Company: GMO Pepabo » Service: minne 2

Slide 3

Slide 3 text

What are Parser Combinators? 3

Slide 4

Slide 4 text

» Higher-order function that takes multiple parsers and /combines/ them into a new parser » CS theory » Parsec, Haskell 4

Slide 5

Slide 5 text

Slide 6

Slide 6 text

Characteristics » Monadic » Composable » Generic » Immutable 6

Slide 7

Slide 7 text

Use let int = Parser { input in let num = input.prefix(while: { $0.isNumber }) guard let number = Int(num) else { throw ParserError.IntError.notANumber(num) } input.removeFirst(num.count) return number } 7

Slide 8

Slide 8 text

func removingLiteral(_ string: String) -> Parser { return Parser { input in guard input.hasPrefix(string) else { throw ParserError.StringError.literalNotFound(string[...]) } input.removeFirst(string.count) } } 8

Slide 9

Slide 9 text

Higher order functions » map » flatMap (bind, >>=) » zip 9

Slide 10

Slide 10 text

struct Coordinate { let x, y: Int } let str = "1,2" let coordinateParser = zip( int, removingLiteral(","), int ).map { x, _, y in Coordinate(x: x, y: y) } let (coordinate, _) = try coordinateParser.run(str[...]) ▿ Coordinate - x: 1 - y: 2 10

Slide 11

Slide 11 text

func substring(while predicate: @escaping (Character) -> Bool) -> Parser { return Parser { input in let p = input.prefix(while: predicate) input.removeFirst(p.count) return p } } 11

Slide 12

Slide 12 text

Let's make another parser! struct Person { let name: String; let age: Int } let str = "name: John, age: 90" 12

Slide 13

Slide 13 text

Name and age parsers let nameParser = zip( removingLiteral("name: "), substring(while: { $0.isLetter }) ).map { _, name in return String(name) } let ageParser = zip( removingLiteral("age: "), int ).map { _, age in return age } 13

Slide 14

Slide 14 text

Person parser let personParser = zip( nameParser, removingLiteral(", "), ageParser ).map { name, _, age in return Person(name: name, age: age) } let (person, _) = try personParser.run(str[...]) ▿ Person - name: "John" - age: 90 14

Slide 15

Slide 15 text

Comparison » By hand » Scanner 15

Slide 16

Slide 16 text

Why and when? 16

Slide 17

Slide 17 text

References » https://github.com/pointfreeco/episode-code- samples/tree/master/0064-parser-combinators-pt3 » https://talk.objc.io/episodes/S01E13-parsing- techniques » https://github.com/johnpatrickmorgan/Sparse » https://github.com/davedufresne/SwiftParsec » https://github.com/thoughtbot/Argo » https://github.com/tryswift/TryParsec 17