Parsing(Swi+ly
ParsingLexing'(Tokenizing)
Parsing((Extrac.ng(meaning)
What%is%the%Type%of%a%parser?
Parsing(an(Int
String'(>'Int
String'(>'(Int,'remainder:'String)
String'(>'(Int,'remainder:'String)?
<ValueType>+String+2>+(ValueType,+remainder:+String)?
struct Parser<ValueType> { let apply:(String) -> (ValueType, String)?}
struct Parser<ValueType> { typealias Function = (String) -> (ValueType, String)? let apply:Function
init(apply: Function) { self.apply = apply }}
Building(Blocks
Parser.result()Parser.zero()Parser.item()
Parser.result()
static func result(value:ValueType) -> Parser { return Parser { (input) in return (value, remainder:input) }}
Parser.zero()
static func zero() -> Parser { return Parser { (input) in return nil }}
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))) } }}
Let$Our$Parsers$Combine!
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 } }}
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() } }}
char
func char(x:Character) -> Parser<Character> { return satisfy { $0 == x }}
func charIn<CharSeq: SequenceType where CharSeq.Generator.Element == Character> (x:CharSeq) -> Parser<Character> { return satisfy { Set(x).contains($0) }}
let digit:Parser<Character> = satisfy { "0"..."9" ~= $0 }let lower:Parser<Character> = satisfy { "a"..."z" ~= $0 }let upper:Parser<Character> = satisfy { "A"..."Z" ~= $0 }
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")
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))) }}
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) }}
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) } }}
Parse&you&a&Monad
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
Examples
• Rob%Rix%(%Madness%(%h0ps://github.com/robrix/Madness
• Parsec%