Modern

Parsley employs modern design developed over five years of research, supporting many parser combinator design pattterns out of the box.

Stack-Safe

Parsley promises to not stack-overflow during the runtime of the parser, preventing vulnerabilities.

Great Errors

Parsley has good out-of-the-box error messages, with a lot of support for improving the content of error messages and their formatting.

Easily Debuggable

Parsley parsers are easy to debug thanks to special combinators and debuggers.

Cross-Compatible

Supports Scala 2.12, 2.13, and 3.0; as well as support for Scala Native and Scala-JS.

Cats Friendly

Intregration available for Typelevel's Cats Ecosystem, providing instances for relevant typeclasses.

Getting Started

Parsley can be added to your project by one of the following configuration commands.

// SBT
libraryDependencies += "com.github.j-mie6" %% "parsley" % "4.5.1"

// scala-cli
--dependency com.github.j-mie6::parsley:4.5.1
// or in file
//> using dep com.github.j-mie6::parsley:4.5.1

// mill
ivy"com.github.j-mie6::parsley:4.5.1"

Alternatively, the most up-to-date development pre-release is 5.0.0-M6 and the most bleeding-edge snapshot is 5.0-6e73e55-SNAPSHOT.

Examples

Parsley can leverage string and character literals in Scala by implicit conversions, keeping the description of the parser uncluttered:

import parsley.Parsley
import parsley.syntax.character.{charLift, stringLift}

val hello: Parsley[Unit] = ('h' ~> ("ello" | "i") ~> " world!").void
// hello: Parsley[Unit] = parsley.Parsley@c9838ee
hello.parse("hello world!")
// res0: parsley.Result[String, Unit] = Success(())
hello.parse("hi world!")
// res1: parsley.Result[String, Unit] = Success(())
hello.parse("hey world!")
// res2: parsley.Result[String, Unit] = Failure((line 1, column 2):
//   unexpected "ey"
//   expected "ello"
//   >hey world!
//     ^^)

Combinators exist to collapse results efficiently for iterative parsers, allowing for concise definitions of simple numbers:

import parsley.character.digit
val natural: Parsley[Int] = digit.foldLeft1(0)((n, d) => n * 10 + d.asDigit)
// natural: Parsley[Int] = parsley.Parsley@5a833dcb
natural.parse("0")
// res3: parsley.Result[String, Int] = Success(0)
natural.parse("123")
// res4: parsley.Result[String, Int] = Success(123)