28
Parsing Swi+ly

Parsing swiftly-Cocoaheads-2015-02-12

Embed Size (px)

Citation preview

Page 1: Parsing swiftly-Cocoaheads-2015-02-12

Parsing(Swi+ly

Page 2: Parsing swiftly-Cocoaheads-2015-02-12

ParsingLexing'(Tokenizing)

Parsing((Extrac.ng(meaning)

Page 3: Parsing swiftly-Cocoaheads-2015-02-12

What%is%the%Type%of%a%parser?

Page 4: Parsing swiftly-Cocoaheads-2015-02-12

Parsing(an(Int

Page 5: Parsing swiftly-Cocoaheads-2015-02-12

String'(>'Int

Page 6: Parsing swiftly-Cocoaheads-2015-02-12

String'(>'(Int,'remainder:'String)

Page 7: Parsing swiftly-Cocoaheads-2015-02-12

String'(>'(Int,'remainder:'String)?

Page 8: Parsing swiftly-Cocoaheads-2015-02-12

<ValueType>+String+2>+(ValueType,+remainder:+String)?

Page 9: Parsing swiftly-Cocoaheads-2015-02-12

struct Parser<ValueType> { let apply:(String) -> (ValueType, String)?}

Page 10: Parsing swiftly-Cocoaheads-2015-02-12

struct Parser<ValueType> { typealias Function = (String) -> (ValueType, String)? let apply:Function

init(apply: Function) { self.apply = apply }}

Page 11: Parsing swiftly-Cocoaheads-2015-02-12
Page 12: Parsing swiftly-Cocoaheads-2015-02-12

Building(Blocks

Parser.result()Parser.zero()Parser.item()

Page 13: Parsing swiftly-Cocoaheads-2015-02-12

Parser.result()

static func result(value:ValueType) -> Parser { return Parser { (input) in return (value, remainder:input) }}

Page 14: Parsing swiftly-Cocoaheads-2015-02-12

Parser.zero()

static func zero() -> Parser { return Parser { (input) in return nil }}

Page 15: Parsing swiftly-Cocoaheads-2015-02-12

Parser.item()static func item() -> Parser<Character> { return Parser<Character> { (input) in

let firstIndex = input.startIndex

if firstIndex == input.endIndex { return nil } else { return (input[firstIndex], remainder: String(dropFirst(input))) } }}

Page 16: Parsing swiftly-Cocoaheads-2015-02-12

Let$Our$Parsers$Combine!

Page 17: Parsing swiftly-Cocoaheads-2015-02-12

bindfunc bind<T, U>(parserT:Parser<T>, lift:(T -> Parser<U>)) -> Parser<U> { return Parser<U> { (input) in if let (theT, theRemainder) = parserT.apply(input) { return lift(theT).apply(theRemainder) } else { return nil } }}

Page 18: Parsing swiftly-Cocoaheads-2015-02-12

sa#sfyfunc satisfy(predicate:(Character -> Bool)) -> Parser<Character> { return bind(Parser<Character>.item()) { theChar in if predicate(theChar) { return Parser.result(theChar) } else { return Parser.zero() } }}

Page 19: Parsing swiftly-Cocoaheads-2015-02-12

char

func char(x:Character) -> Parser<Character> { return satisfy { $0 == x }}

Page 20: Parsing swiftly-Cocoaheads-2015-02-12

func charIn<CharSeq: SequenceType where CharSeq.Generator.Element == Character> (x:CharSeq) -> Parser<Character> { return satisfy { Set(x).contains($0) }}

Page 21: Parsing swiftly-Cocoaheads-2015-02-12

let digit:Parser<Character> = satisfy { "0"..."9" ~= $0 }let lower:Parser<Character> = satisfy { "a"..."z" ~= $0 }let upper:Parser<Character> = satisfy { "A"..."Z" ~= $0 }

Page 22: Parsing swiftly-Cocoaheads-2015-02-12

I"Said""Let"Our"Parsers"Combine!"let nsParser:Parser<String> = bind(char("N")) { (theLetterN) in bind(char("S")) { (theLetterS) in Parser<String>.result(String([theLetterN, theLetterS])) }}

nsParser.apply("NS")nsParser.apply("AB")

Page 23: Parsing swiftly-Cocoaheads-2015-02-12

a"small"detourextension Optional { internal func bind<U>(f: T -> U?) -> U? { if let x = self { return f(x) } else { return nil } }}

func headAndTail(input:String) -> (head:Character, tail:String)? { return first(input).bind { head in

return (head:head, tail:String(dropFirst(input))) }}

Page 24: Parsing swiftly-Cocoaheads-2015-02-12

Words!func word(x:String) -> Parser<String> { if let found = headAndTail(x) { return bind(char(found.head)) { (a:Character) in return bind(word(found.tail)) { (b:String) in return Parser<String>.result(x) } } } else { return Parser<String>.result(x) }}

Page 25: Parsing swiftly-Cocoaheads-2015-02-12

Choicefunc choice<T>(lhs:Parser<T>, rhs:Parser<T>) -> Parser<T> { return Parser { (input) in if let leftParse = lhs.apply(input) { return leftParse } else { return rhs.apply(input) } }}

Page 26: Parsing swiftly-Cocoaheads-2015-02-12

Parse&you&a&Monad

Page 27: Parsing swiftly-Cocoaheads-2015-02-12

Monadic(Parser(CombinatorsGraham&Hu)on&and&Erik&Meijer

• h#p://www.cs.no#.ac.uk/~gmh/monparsing.pdf)

Parsec:(Direct(Style(Monadic(Parser(Combinators(For(The(Real(WorldDaan$Leijen

• h#p://research.microso0.com/en2us/um/people/daan/download/papers/parsec2paper.pdf

Page 28: Parsing swiftly-Cocoaheads-2015-02-12

Examples

• Rob%Rix%(%Madness%(%h0ps://github.com/robrix/Madness

• Parsec%