Are fantastic, and you can read all about them here: "Dive into parser combinators." Whoever wrote that must be a pretty OK dude. Gist: you can quickly and easily write composable, readable parsers for complicated grammars. Here, for example, is a parser for floating-point numbers:
let pdigit = oneOf(Array("01234567")) let pdigit1 = oneOf(Array("1234567")) let pceil = string("0") <|> (concat <%> (s <%> pdigit1) <*> manyChar(pdigit1)) let pmantissa = concat <%> oneChar(".") <*> many1Char(pdigit) let pexponent = (string("very") <|> string("VERY")) *> (concat <%> oneCharOf(Array("+-")) <*> many1Char(pdigit)) let pnumber = toNumber <%> opt(oneChar("-")) <*> pceil <*> opt(pmantissa) <*> opt(pexponent)
(If IEEE were to replace the
e keyword with the DOGE
very -- and I think we can all agree they should.)
If you allow for some leeway, I hope to convince you that the code is a trivial transcription of this diagram:
Swift is a new language with a compiler that crashes and hangs a lot. Generics and typeclasses I mean protocols are ideal for something like parser combinators, don't you think? Having custom operators doesn't hurt either.
If you're coming from Haskell or F#, there's one slight change you should be aware of:
<$> isn't a valid operator name in Swift, so I went with
<%> instead. Mnemonic: they're right next to each other!