Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Parsing with Blocks
Search
Chris Eidhof | @chriseidhof
May 08, 2014
Technology
270
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Parsing with Blocks
CocoaHeads Hamburg
Chris Eidhof | @chriseidhof
May 08, 2014
More Decks by Chris Eidhof | @chriseidhof
See All by Chris Eidhof | @chriseidhof
Dutch FP Day 2015
chriseidhof
2
410
Tiny Networking in Swift
chriseidhof
2
19k
Functional Swift - Brooklyn
chriseidhof
3
1.3k
Functional Swift - SF
chriseidhof
6
26k
Functional Swift
chriseidhof
6
1.3k
Functional Swift
chriseidhof
1
180
Functional Programming in Swift
chriseidhof
40
19k
Lighter View Controllers
chriseidhof
4
220
Practical Concurrent Programming
chriseidhof
4
310
Other Decks in Technology
See All in Technology
あるけみー式LTスライド作成術
alchemy1115
1
210
目の前の楽しいが人生を変える - コミュニティの螺旋の歩き方と楽しむコツ / change your life
soudai
PRO
4
550
omasushiというライブラリを作った
polidog
PRO
0
220
積み重なった技術負債への挑戦 〜初手としての全社ゴト化〜
techtekt
PRO
0
590
顧客に向き合う開発組織へ。リアーキテクチャとフィーチャーチーム化で挑む組織改革
safie
0
1.2k
Genieを崇めよ
kameitomohiro
0
110
LTのテーマ どうきめてる?〜5つの型と私のやり方〜
yama3133
1
100
AI時代のAPI品質を支えるガードレール / API Guardrails for API quality in the AI era
yokawasa
1
250
20260912_スクフェス三河
kgnkhkr
0
350
銀行勘定系システムにおける開発プロセス刷新×AIによる環境モダナイゼーション / Development Process Transformation and AI-Driven Environment Modernization
muit
0
1.5k
2026-09-10 【Snowflake World Tour Tokyo 2026】dbt Core と Snowflake で実現する多層的なデータガバナンス / Multi-Layered Data Governance Powered by dbt Core and Snowflake
civitaspo
0
380
Sigmaで作る業務アプリ
kazushiro_honma
0
130
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.3k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Speed Design
sergeychernyshev
33
2.1k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
190
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
510
The browser strikes back
jonoalderson
0
1.7k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
240
Prompt Engineering for Job Search
mfonobong
0
450
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.6k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
830
Transcript
Parsing with Blocks CocoaHeads Hamburg Chris Eidhof
Warning All of this is a bit crazy
Building languages is magical
stylesheet { multiplier = if(slide.onlyHeader, 2, 1), baseFontSize = 45
* multiplier, splitBaseFontSize = 25, backgroundColor = colorScheme.backgroundColor, bodyFont = { family = "Apercu", color = colorScheme.textColor, size = baseFontSize } }
DSLs → SQL → AutoLayout → NSPredicate → Regular Expressions
→ ActiveRecord
DSLs External vs. Internal
DSLs: External → SQL → CSS → NSPredicate format syntax
DSLs: Internal [view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(superview.mas_top).with.offset(padding.top); make.left.equalTo(superview.mas_left).with.offset(padding.left); make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom); make.right.equalTo(superview.mas_right).with.offset(-padding.right);
}] Source: Masonry
V:[topField]-10-[bottomField] [flexibleButton(>=70,<=100)] |-[find]-[findNext]-[findField(>=20)]-|
None
Building an external DSL
None
Parsing 1. String → Stream of tokens 2. Stream of
tokens → Syntax Tree 3. Interpret Syntax Tree
Existing approaches → Hand-rolled parsers → Parser generators → ParseKit
/ CoreParse
An alternative approach → Based on functional programming → Backtracking
→ Immutable objects
The language
1 + 2 * 3 Expr ← Sum Sum ←
Product '+' Product Product ← Atom '*' Atom Atom ← Number
1 + 2 * 3 Expr ← Sum Sum ←
Product '+' Product | Product Product ← Atom '*' Atom | Atom Atom ← Number
(1 + 2) * 3
(1 + 2) * 3 Expr ← Sum Sum ←
Product '+' Product | Product Product ← Atom '*' Atom | Atom Atom ← Number | '(' Expr ')'
Block Syntax returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...}; Source: http://goshdarnblocksyntax.com
Live Coding
A stylesheet language
stylesheet { multiplier = if(slide.onlyHeader, 2, 1), baseFontSize = 45
* multiplier, splitBaseFontSize = 25, backgroundColor = colorScheme.backgroundColor, bodyFont = { family = "Apercu", color = colorScheme.textColor, size = baseFontSize } }
Rule stylesheet = ^(State *p) { __block NSArray *functions =
nil; return p.identifier().token(@"{"). manySepBy(method, comma).bind(to(functions)). token(@"}").yield(^id { return [[StylesheetObject alloc] initWithFunctions:functions]; }); };
Rule method = ^(State * p) { __block NSString* name
= nil; __block id body= nil; __block NSArray *parameters = nil; return p.identifier().bind(to(name)). optional(parameterList).bind(to(parameters)). token(@"="). rule(self.expression).bind(to(body)). yield(^id { return [[StylesheetFunction alloc] initWithName:name body:body parameters:parameters]; }); };
Rule mulExpression = infix(@"*", infix(@"/", functionCallExpression)); Rule addExpression = infix(@"+",
infix(@"-", mulExpression));
API
typedef State *(^Rule)(State *p);
@interface State : NSObject @property (nonatomic, strong) id result; @property
(nonatomic) BOOL failed; @property (nonatomic) NSString *errorMessage; @property (nonatomic) State *(^token)(NSString *); @property (nonatomic) State *(^identifier)(); @property (nonatomic) State *(^yield)(id (^)()); @property (nonatomic) State *(^bind)(void(^)(id result)); @property (nonatomic) State *(^oneOf)(NSArray *); @property (nonatomic) State *(^optional)(Rule); @property (nonatomic) State *(^eof)(); @property (nonatomic) State *(^rule)(Rule); @end
State Internals @interface State () @property (nonatomic) NSArray *tokens; @property
(nonatomic) NSUInteger tokenIndex; @end
self.token = ^(NSString* token) { if (self.failed) return self; NSString*
peek = self.peek; if ([token isEqual:peek]) { return [self next:peek]; } else { NSString* msg = [NSString stringWithFormat:@"Expected '%@', saw '%@'", token, peek]; return [self fail:msg]; } };
- (State *)next:(id)result { if (self.failed) return self; State *next
= [self copy]; next.failed = NO; next.result = result; next.tokenIndex++; return next; }
We created two DSLs → One for parsing (embedded) →
One external https://github.com/chriseidhof/parsingwithblocks
Thanks → @chriseidhof → http://www.objc.io → http://www.uikonf.com → http://www.decksetapp.com