parser-combinators-kotlin
parser-combinators-kotlin copied to clipboard
Parser combinators for Kotlin
parser-combinators
This repository contains some utilies for parser combinators in the Kotlin programming language. The OSS license can be found in the LICENSE.md file of the repository.
Installation
This library is available on JitPack.io. Make sure to add the following Maven repository in your root build.gradle file :
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
You can now add the library modules in your application build.gradle file :
dependencies {
implementation "com.github.alexandrepiveteau.parser-combinators-kotlin:parser-combinators:1.1.0"
implementation "com.github.alexandrepiveteau.parser-combinators-kotlin:parser-combinators-primitives:1.1.0"
}
Usage
The library contains a single module, versioned using semantic versioning :
- parser-combinators - Offers some primitives for building
Parserinstances, and combinators for manipulatingParserinstances. - parser-combinators-primitives - Offers some functions for building
Parseron primitive data types in Kotlin.
parser-combinators
A Parser<Input, Output, Error> is a structure accepting a Input as input, and returning an Either<Error, Pair<Output, Input>>, where the Error case of the Either represents a problem that occurred while parsing the input, and the Value case of the Either represents a pair of the parser output, and the remaining Input that has not been parsed yet. A parser combinator is a function that accepts one or multiple parsers as input and outputs a different parser.
Each Parser instance is just an immutable wrapper around a parsing function. Therefore, it is easily possible to create your own instances of Parser from scratch. Nevertheless, some default Parser implementations are provided :
/*
* This Parser will always fail, no matter what input sequence is provided to it. This can
* be useful when combining multiple Parsers together.
*/
val l = Parser.fail<String, Int, Throwable> { IllegalArgumentException("This parser always fail.") }
/*
* This Parser uses a lazily evaluated lambda as its argument. It can easily be used to
* recursively call itself. The lambda has the type () -> Parser<Int, String> in this
* example.
*/
val e = Parser.lazy<String, Int, String> { TODO("Make a recursive call, lazily evaluated.") }
/*
* This Parser always succeeds. It will produce a Parser<Unit, T> instance, and therefore
* has can be mapped to produce a "default" value of any type.
*/
val x = Parser.succeed<String, String>().map { 34 } // Parser<String, Int, String>
Multiple combinators are provided as extension functions in the library. For instance, the map { } function (used at the end of the previous snippet) is a combinator that transforms the value produced by a Parser. These high-level functions can be used to build high-level Parser objects, which can for instance contain some custom types.
The following parser combinators are provided as extension functions (in each one of these, the first argument is always the current Parser instance) :
map(f: (O1) -> O2)- Returns aParserthat transforms the value produced using a mapping function.flatMap(f: (O1) -> Either<E, O2>)- Returns aParserthat, likemap {}, transforms the value produced using a mapping function. It can also transform the value into anEither.Error, which will make theParserfail. This can be used when you want to validate your model with some logic that can't be easily built into parsers otherwise.and(other: Parser<I, O2, E>)- Returns aParserthat pairs the responses of the two combined parsers.after(other: Parser<I, O2, E>)- Same asand, but returns only the second value of the pair.before(other: Parser<I, O2, E>)- Same asand, but returns only the first value of the pair.or(other: Parser<I, O2, E>)- Tries the firstParserinstance, and, if it fails, tries theotherinstance. Returns aParserformed of anEitherbased on the result of the parsing.flatOr(other: Parser<I, O, E>)- Same asor, but because bothParserhave the same type, the resultingEithercan safely be flattened.loop()- Returns aParserthat applies itself repeatedly, until it fails. Returns aListof the results of each iteration.