# Parsel

Parsel is a parser combinator library that makes it easy to write parsers. Parser combinators lets you create simple parses that can be combined together to very complex ones. Take for example a parser that parses a digit from a given String: (You can use the pre-defined lexical parser for digit: `L.digit`)

``````let digit = Parser<String, Int> { input in
guard let first = input.first, let number = Int(String(first)) else {
return .fail(/* some pre-defined error */)
}
return .success(result: number, rest: String(input.dropFirst()))
}
``````

We can now simply extend this to create a parser that parses an addition of two digits from a string:

``````let addition = (digit ~ L.plus ~ digit).map { a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign

try! result.unwrap() // Int: 6
``````

# Why should I use this?

Parsing is a very common task, it does not always mean to parse source code or JSON strings. Parsing means to transform an unstructured input to a structured output. In case of source code this means to parse a raw string to an AST (abstract syntax tree), in case of an addition it means to parse the result of adding two numbers out of a string. Parsing can always fail, if the input does not match the needed grammer. If the input string in the above example would have been `1+`, it would have been failed because the second number is missing. The advantage of parser combinators is that you start with a very basic parser. In the above example `digit` parses only one digit. But it is not hard, to add a parser that parses more than one digit. A number is a repetition of mulitple digits. For repetition, we can use `rep`, which tries to apply the parser until it fails and collects the result as an array. Parsing an integer addition is as easy as

``````func intFromDigits(_ digits: [Int]) -> Int {
return digits.reduce(0) { res, e in
return res * 10 + e
}
}

let number = digit.rep.map(intFromDigits)
let addition = number ~ L.plus ~ number ^^ { a, _, b in // ^^ is convenience for map
return a + b
}

try! result.unwrap() // Int: 579
``````

(There is also a pre-defined lexical parser for numbers `L.number` that is able to parse a number in different formats [binary, octal, hexadecimal, decimal])

Since parser combinators are very high level, they abstract the whole process of parsing a lot. That means it is easier to use but it also means that the performance is not as good as an optimized, handwritten parser.

# Installation

Parsel is currently available via Swift Package Manager and Cocoapods. Support for Carthage will come later.

## Swift Package Manager

To use Parsel in your project, just add it as a dependency in your `Package.swift` file and run `swift package update`.

``````import PackageDescription

let package = Package(
name: "MyAwesomeApp",
dependencies: [
.package(url: "https://github.com/BenchR267/Parsel", from: "2.2.0")
]
)
``````

## Cocoapods

To use Parsel with Cocoapods, just add this entry to your Podfile and run `pod install`:

``````target 'MyAwesomeApp' do
use_frameworks!

pod 'Parsel'
end
``````

# Requirements

• Swift 4.0
• Parsel is written in Swift 4.0 development snapshots and will be available when Swift 4.0 is released

# Example

Calculator is a small example I wrote with Parsel.

# Documentation

Check out the documentation on the Github page.