Skip to content

Commit

Permalink
Get ready for 0.1.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikaelhg committed Jun 21, 2021
1 parent 8587057 commit a24b8d6
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 4 deletions.
124 changes: 124 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,132 @@
# Karslet

[![Release](https://jitpack.io/v/com.github.mikaelhg/kotlin-peg-dsl.svg)]
(https://jitpack.io/#com.github.mikaelhg/kotlin-peg-dsl)

A Kotlin domain specific language (DSL) and library for easily creating
recursive descent parsers in the [parsing expression grammar (PEG)][1] tradition.

A work in progress.

## Usage

```kotlin
import java.nio.CharBuffer

import io.mikael.karslet.Karslet

data class PxKeyword(val keyword: String, val language: String?, val specifiers: List<String>?)

data class PxValue(val numberValue: Long?, val stringValue: String?, val listValue: List<String>?)

typealias PxRow = Pair<PxKeyword, PxValue>

class Usage {

private fun stringOrList() = Karslet.sequence<List<String>> {

character('"')
val first = characters(min = 0) { it != '"' }
character('"')

val last = zeroOrMore<List<String>> {
val state = mutableListOf<String>()
beforeAttempt { state.clear() }

character(',')
character('"')
val current = characters(min = 0) { it != '"' }
character('"')

onIteration { state += current.value() }
onSuccess { state }
}

onSuccess { listOf(first.value()) + last.value() }
}

private fun keywordLanguage() = Karslet.optional<String?> {

var state: String? = null
beforeAttempt { state = null }

character('[')
val lang = characters(min = 2, max = 2) { it.isLetter() }
character(']')

onIteration { state = lang.value() }
onSuccess { state }
}

private fun keywordSpecifiers() = Karslet.optional<List<String>?> {

var state: List<String>? = null
beforeAttempt { state = null }

character('(')
val strings = include(stringOrList())
character(')')

onIteration { state = strings.value() }
onSuccess { state }
}

private fun pxKeyword() = Karslet.sequence<PxKeyword> {
val kw = characters(min = 1) { it !in arrayOf('[', '(', '=') }
val lang = include(keywordLanguage())
val spec = include(keywordSpecifiers())

onSuccess { PxKeyword(kw.value(), lang.value(), spec.value()) }
}

private fun pxValue() = Karslet.choice<PxValue> {
val strings = sequence<List<String>?> {
val x = include(stringOrList())
character(';')
onSuccess { x.value() }
}
val numbers = sequence<Long?> {
val x = characters(min = 1) { it.isDigit() }
character(';')
onSuccess { x.value().toLongOrNull() }
}
val letters = sequence<String?> {
val x = characters(min = 1) { it.isLetterOrDigit() }
character(';')
onSuccess { x.value() }
}
onSuccess { PxValue(numbers.value(), letters.value(), strings.value()) }
}

@Test
fun pxParserDemo() {

val parser = Karslet.oneOrMore<List<PxRow>> {
val state = mutableListOf<PxRow>()

val row = sequence<PxRow> {
val k = include(pxKeyword())
character('=')
val v = include(pxValue())
whitespace()

onSuccess { PxRow(k.value(), v.value()) }
}

beforeAttempt { state.clear() }
onIteration { state += row.value() }
onSuccess { state }
}

TestData.rows.forEach { row ->
val success = parser.parse(CharBuffer.wrap(row))
println("$success ${parser.value()}")
}

}

}

```

[1]: https://en.wikipedia.org/wiki/Parsing_expression_grammar
5 changes: 2 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group = "io.mikael.karslet"
version = "0.0.1-SNAPSHOT"
version = "0.1.0"

java {
toolchain {
Expand All @@ -19,7 +19,7 @@ repositories {

dependencies {
implementation(enforcedPlatform(kotlin("bom")))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation(kotlin("stdlib-jdk8"))
testImplementation(enforcedPlatform("org.junit:junit-bom:5.7.2"))
testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
Expand All @@ -34,7 +34,6 @@ tasks.withType<Test> {

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}
24 changes: 24 additions & 0 deletions src/main/kotlin/io/mikael/karslet/Karslet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,30 @@ const val MAX_REPEATS = Integer.MAX_VALUE

/**
* Karslet is a Parsing Expression Grammar (PEG) domain specific language (DSL) library.
*
* ```kotlin
* val rule = Karslet.sequence<List<String>> {
* character('"')
* val first = characters(min = 0) { it != '"' }
* character('"')
*
* val last = zeroOrMore<List<String>> {
* val state = mutableListOf<String>()
* beforeAttempt { state.clear() }
*
* character(',')
* character('"')
* val current = characters(min = 0) { it != '"' }
* character('"')
*
* onIteration { state += current.value() }
* onSuccess { state }
*
* }
* onSuccess { listOf(first.value()) + last.value() }
* }
* ```
*/
object Karslet {

Expand Down
2 changes: 1 addition & 1 deletion src/test/kotlin/io/mikael/karslet/tests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class Demos {
@Test
fun pxParserDemo() {

val parser = Karslet.zeroOrMore<List<PxRow>> {
val parser = Karslet.oneOrMore<List<PxRow>> {
val state = mutableListOf<PxRow>()

val row = sequence<PxRow> {
Expand Down

0 comments on commit a24b8d6

Please sign in to comment.