Step 1: Quickstart

Build your first parser in minutes. This guide walks through a minimal example that demonstrates the core DSL concepts.

Your First Parser

Let’s build a simple key-value parser that matches patterns like count=42:

import io.github.mirrgieriana.xarpeg.*
import io.github.mirrgieriana.xarpeg.parsers.*

val identifier = +Regex("[a-zA-Z][a-zA-Z0-9_]*") map { it.value } named "identifier"
val number = +Regex("[0-9]+") map { it.value.toInt() } named "number"
val kv: Parser<Pair<String, Int>> =
    identifier * -'=' * number map { (key, value) -> key to value }

fun main() {
    val result = kv.parseAll("count=42").getOrThrow()
    check(result == ("count" to 42))  // Verifies result is (count, 42)
}

Understanding the Code

The unary + operator converts literals and regex patterns into parsers:

The * operator chains parsers in order (example: identifier * -'=' * number). Results are packaged into typed tuples.

The unary - operator matches a parser but excludes its value from the result tuple (example: -'=' drops the = character).

The map function transforms parsed values:

The named function assigns names to parsers for better error messages (example: named "identifier").

Running the Parser

Use parseAll(...).getOrThrow() to parse and require the entire input to be consumed:

import io.github.mirrgieriana.xarpeg.*
import io.github.mirrgieriana.xarpeg.parsers.*

val identifier = +Regex("[a-zA-Z][a-zA-Z0-9_]*") map { it.value } named "identifier"
val number = +Regex("[0-9]+") map { it.value.toInt() } named "number"
val kv: Parser<Pair<String, Int>> =
    identifier * -'=' * number map { (key, value) -> key to value }

fun main() {
    // Success cases
    check(kv.parseAll("count=42").getOrThrow() == ("count" to 42))  // ✓
    check(kv.parseAll("x=100").getOrThrow() == ("x" to 100))        // ✓

    // Error cases would throw exceptions:
    // kv.parseAll("=42").getOrThrow()        // ✗ ParseException
    // kv.parseAll("count").getOrThrow()      // ✗ ParseException
    // kv.parseAll("count=42x").getOrThrow()  // ✗ ParseException
}

Exception types:

Key Takeaways

Best Practices

When choosing parser types, follow these guidelines for optimal performance and clarity:

Use Char tokens for single characters:

Use String tokens for fixed strings:

Use Regex tokens with named for patterns:

Summary:

Next Steps

Now that you understand the basics, learn how to combine parsers in more sophisticated ways.

Step 2: Combinators