Xarpeg: Kotlin PEG Parser
Lightweight PEG-style parser combinators for Kotlin Multiplatform
Xarpeg (/ˈʃɑrpɛɡ/) is a compact, operator-driven parser combinator library for Kotlin. It targets JVM, JS (Node.js), and Native platforms (Linux x64, Linux ARM64, Windows x64), works directly on raw input strings without tokenization, and includes built-in memoization for predictable backtracking performance.
Why Xarpeg?
- 🎯 Intuitive DSL - Operator-based syntax feels natural:
+for literals/regex/choice,*for sequences,-to ignore tokens - 📦 Multiplatform - Write once, run on JVM, JS (IR/Node.js), and Native (Linux/Windows)
- 🔧 No Tokenizer Needed - Parse directly from strings using character, string, and regex parsers
- ⚡ Built-in Memoization - Automatic caching keeps backtracking predictable; disable for lower memory use
- 🎨 Type-Safe Results - Sequences yield
Tuple0..Tuple16so you explicitly control what’s kept or dropped
Quick Example
Here’s a complete arithmetic expression parser in just a few lines:
import io.github.mirrgieriana.xarpeg.*
import io.github.mirrgieriana.xarpeg.parsers.*
val expr: Parser<Int> = object {
val number = +Regex("[0-9]+") map { it.value.toInt() } named "number"
val brackets: Parser<Int> = -'(' * ref { root } * -')'
val factor = number + brackets
val mul = leftAssociative(factor, -'*') { a, _, b -> a * b }
val add = leftAssociative(mul, -'+') { a, _, b -> a + b }
val root = add
}.root
fun main() {
check(expr.parseAll("2*(3+4)").getOrThrow() == 14) // ✓ Evaluates to 14
}
Key concepts:
+'x'/+"xyz"/+Regex("...")create parsers from literals or patterns*sequences parsers, returning typed tuples-parsermatches but ignores the result (useful for delimiters)+(binary) tries alternatives in ordernamedimproves error messagesref { }enables recursive grammarsleftAssociativehandles operator precedence without manual recursion
Best practices:
- Use
+'x'for single characters, not+"x" - Use
+"xyz"for fixed strings, not+Regex("xyz") - Always use
namedwithRegexparsers for better error messages
💡 New to parser combinators? Start with our step-by-step tutorial!
📚 Learn Xarpeg Step by Step
Follow our comprehensive tutorial to master parser combinators:
- Quickstart - Your first parser in minutes
- Combinators - Sequences, choices, repetition, and naming
- Expressions & Recursion - Build recursive grammars with
ref { } - Runtime Behavior - Errors, exceptions, and caching
- Parsing Positions - Extract location information with
mapEx - Template Strings - Parse embedded expressions naturally
→ Start the Tutorial: [English] [日本語]
🎮 Try It Live
Interactive browser-based parser that demonstrates:
- Real-time parsing and evaluation
- Error reporting with suggestions
- Kotlin/JS multiplatform capabilities
API Quick Reference
Core Combinators
| Operation | Syntax | Description |
|---|---|---|
| Literals | +'x', +"xyz", +Regex("...") |
Create parsers from characters, strings, or regex |
| Sequence | parserA * parserB |
Match parsers in order, return typed tuple |
| Choice | parserA + parserB |
Try alternatives; first match wins |
| Ignore | -parser |
Match but drop result from tuple |
| Repetition | .zeroOrMore, .oneOrMore, .list(min, max) |
Collect matches into List<T> |
| Serial | serial(p1, p2, ...) |
Parse multiple different parsers, return List<T> (no tuple limit) |
| Optional | .optional |
Try to match; rewind on failure |
| Transform | .map { ... } |
Convert parsed value to another type |
| Position | .mapEx { ctx, result -> ... } |
Access context and position info |
| Position | .result |
Get full ParseResult<T> with value and positions |
| Lookahead | !parser |
Succeed if parser fails (zero width) |
| Naming | parser named "name" |
Assign name for error messages |
| Hidden | parser.hidden |
Mark parser to exclude from error suggestions |
| Recursion | ref { parser } |
Forward reference for recursive grammars |
| Associativity | leftAssociative(...), rightAssociative(...) |
Build operator chains |
| Boundaries | startOfInput, endOfInput |
Match at position boundaries |
Parsing Methods
parseAll(input).getOrThrow()- Parse entire input or throw exceptionparseOrNull(context, start)- Attempt parse at position; returnParseResult<T>?
Error Handling
ParseException- Thrown when parsing fails (either because no parser matched at the current position or because trailing input remains after successful parse)- The exception provides
contextwitherrorPositionandsuggestedParsersfor detailed error reporting
Performance
- Memoization - Enabled by default (
useMemoization = true); disable withuseMemoization = falsefor lower memory usage - Backtracking - Memoized results make repeated attempts predictable; alternatives backtrack automatically
Examples & Use Cases
Complete Examples
- JSON Parser - Full JSON implementation with escape sequences, numbers, arrays, and nested objects
- Arithmetic Interpreter - Expression parser with evaluation and error reporting
- Online Parser Demo - Interactive browser-based parser (source)
Real-World Usage
Xarpite - The original project from which Xarpeg was extracted. Demonstrates:
- Large-scale grammar design and organization
- Integration into a complete application
- Performance optimization with caching
- Complex parsing scenarios in production
Running the Samples
Try the samples locally to see Xarpeg in action:
Minimal JVM Sample:
cd samples/minimal-jvm-sample && ./gradlew run
Online Parser Sample:
cd samples/online-parser && ./gradlew build
# Open samples/online-parser/build/site/index.html in your browser
Arithmetic Interpreter:
cd samples/interpreter && ./gradlew run --args='-e "2*(3+4)"'
Installation
Add Xarpeg to your project using Gradle. Replace <latest-version> with the version from Releases.
repositories {
mavenCentral()
}
dependencies {
implementation("io.github.mirrgieriana:xarpeg:<latest-version>")
}
The xarpeg artifact uses Gradle module metadata to automatically resolve to the correct platform-specific variant (JVM, JS, Native, etc.) based on your project configuration.
Note: The API may evolve as we refine the DSL. Pin a specific version for production use.
Resources
- Documentation - Complete tutorial [English] [日本語]
- API Reference - Browse source for KDoc
- Examples - Sample applications
- Issues - Bug reports and feature requests
- Releases - Version history
⚠️ Documentation Notice: The natural language descriptions throughout this documentation (including this README) were predominantly generated by AI and may contain inaccuracies. When in doubt, please verify against the actual source code and test the behavior directly.
License
MIT License - See LICENSE for details.
Logo uses Monaspace