21
SUPERCOMBINATORS A "SWIFTY" PARSER COMBINATOR FRAMEWORK

Super combinators

Embed Size (px)

Citation preview

Page 1: Super combinators

SUPERCOMBINATORS A "SWIFTY" PARSER COMBINATOR

FRAMEWORK

Page 2: Super combinators

SWIFTY

Use term with cautionStill being defined

Should mean "familiar"Can mean baggage !

Page 3: Super combinators

WHY?

Why do this presentation?Why parser combinators?

Why SuperCombinators?

Page 4: Super combinators

STRINGS

Two potential intended users of a string

1. !2. "

Page 5: Super combinators

SNIPS

A lot of work on taking text for humans"Show me walking directions home"

Transform into something for machineschmod +x query.txt

Page 6: Super combinators

ONE APPROACH

Context-free grammar

Assign semantic function to nonterminals

This is not easy to express cleanly in Swift

Page 7: Super combinators

ONE SOLUTION

Define the semantic function as a String

Transform into a closure

More advanced ExpressibleByStringLiteral

Page 8: Super combinators

PARSER COMBINATORS

Conceptually: typealias Parser<Value, Collection> = (Collection) -> (Value, Collection)?

Made to be composable

Unlike familiar Cocoa devices

Page 9: Super combinators

EXISTING SOLUTIONS

A number of frameworks available already

All had downsides▸ Too many custom operators

▸ Memory leaks▸ Swift 2.2

Page 10: Super combinators

EXISTING SOLUTIONS

Demo/teaching tool

Not for production

Page 11: Super combinators

CLONE

First we cloned an existing solution

Migration ❤

Became intimately familiar with every line

Page 12: Super combinators

REIMPLEMENT

What could be made better?▸ String-specific▸ Declarative API

▸ Memory-safe recursion

Other goodies

Page 13: Super combinators

STRING

String can also be a "substring"let substring: String = text.substring(from: substringIndex)

Completely opaque

Captures text

Cheap to get substring with full String API

Page 14: Super combinators

SWIFT TYPE CONVEYS SEMANTICS

Collection takes this to an extreme

Helps compiler and programmer

Page 15: Super combinators

Pattern AND Parser<Value>

Pattern just traverses String

Parser extracts Value

Makes composition implicit while intuitive

Page 16: Super combinators

OPERATORS

Distinction in types allows for simplification

Just || and & for almost all composition

mirrored by explicit .or(_:) and .and(_:) instance methods

Page 17: Super combinators

EXTENSIONS

Distinction in types allows for useful extensionsExpressibleByStringLiteral

Swift 3.1:extension Parser where Value == String {}

Page 18: Super combinators

RECURSIVE PARSERS

Reference cycles

Usually avoidable

Not always obvious how

Page 19: Super combinators

RECURSIVE PARSERS

Use additional object with unowned reference back

lazily generate parsing function

take Parser -> Parser

Page 20: Super combinators

EXAMPLElet digits = Pattern.characters(in: .decimalDigits)let int = digits.stringParser.map { Int($0)! }

let sum = Parser<Int>.recursive { sum in return (int & "+" & sum).map(+) || int}

print(sum.parse("1+2+3")!)// prints 6

Page 21: Super combinators

THANK YOU!

github.com/snipsco/SuperCombinators

Sasha Lopoukhine

github.com/superlopuh@superlopuh