Skip to content

Commit

Permalink
Added Defer instance, bump to 0.2.0. (#1)
Browse files Browse the repository at this point in the history
By adding `Defer[Parsley]`, there is now support for idiomatic recursive
parser construction.
  • Loading branch information
j-mie6 authored Dec 25, 2022
1 parent 50c706c commit 4b415c8
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 7 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@


## What is `parsley-cats`?
The `parsley-cats` library exposes `cats` instances for `MonoidK[Parsley]`, `Monad[Parsley]`, and `FunctorFilter[Parsley]`.
The `parsley-cats` library exposes `cats` instances for `MonoidK[Parsley]`, `Monad[Parsley]`, and `FunctorFilter[Parsley]` as well as `Defer[Parsley]`.
Care should still be taken to not define truly recursive parsers using the `cats` API (although monadic parser with `flatMap`
may be generally recursive, just slow).
may be generally recursive, just slow). In particular, make use of `Defer[Parsley].fix`
to handle recursion, or plain `lazy val` based construction (as in regular `parsley` use).

## How do I use it? [![parsley-cats Scala version support](https://index.scala-lang.org/j-mie6/parsley-cats/parsley-cats/latest-by-scala-version.svg?platform=jvm)](https://index.scala-lang.org/j-mie6/parsley-cats/parsley-cats) [![parsley-cats Scala version support](https://index.scala-lang.org/j-mie6/parsley-cats/parsley-cats/latest-by-scala-version.svg?platform=sjs1)](https://index.scala-lang.org/j-mie6/parsley-cats/parsley-cats) [![parsley-cats Scala version support](https://index.scala-lang.org/j-mie6/parsley-cats/parsley-cats/latest-by-scala-version.svg?platform=native0.4)](https://index.scala-lang.org/j-mie6/parsley-cats/parsley-cats)

Parsley cats is distributed on Maven Central, and can be added to your project via:

```scala
libraryDependencies += "com.github.j-mie6" %% "parsley-cats" % "0.1.0"
libraryDependencies += "com.github.j-mie6" %% "parsley-cats" % "0.2.0"
```

it requires `parsley` and `cats-core` to also be dependencies of your project. The current version
matrix for `parsley-cats`:

| `parsley-cats` version | `parsley` version | `cats-core` version |
| :--------------------: | :---------------: | :-----------------: |
| `0.1.0` | `>= 4 && < 5` | `>= 2.8 && < 3` |
| `0.1.x` | `>= 4 && < 5` | `>= 2.8 && < 3` |
| `0.2.x` | `>= 4 && < 5` | `>= 2.8 && < 3` |

Documentation can be found [**here**][Link-Scaladoc]

Expand Down
7 changes: 5 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ val Scala3 = "3.2.1"
Global / onChangedBuildSource := ReloadOnSourceChanges

inThisBuild(List(
tlBaseVersion := "0.1",
tlBaseVersion := "0.2",
organization := "com.github.j-mie6",
startYear := Some(2022),
homepage := Some(url("https://github.com/j-mie6/parsley-cats")),
Expand Down Expand Up @@ -38,7 +38,10 @@ lazy val `parsley-cats` = crossProject(JVMPlatform, JSPlatform, NativePlatform)
"com.github.j-mie6" %%% "parsley" % "4.0.0" % Provided,
"org.scalatest" %%% "scalatest" % "3.2.12" % Test,
"org.typelevel" %%% "cats-laws" % "2.8.0" % Test,
)
),
mimaPreviousArtifacts := Set(
"com.github.j-mie6" %% "parsley-cats" % "0.1.0",
),
)
.jsSettings(
Test / scalaJSLinkerConfig := scalaJSLinkerConfig.value.withESFeatures(_.withESVersion(ESVersion.ES2018))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package parsley

import cats.Defer

import Parsley.LazyParsley

private [parsley] class DeferForParsley extends Defer[Parsley] {
def defer[A](p: =>parsley.Parsley[A]): parsley.Parsley[A] = ~p
}
8 changes: 7 additions & 1 deletion parsley-cats/shared/src/main/scala/parsley/cats.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
package parsley

import cats.{Monad, MonoidK, FunctorFilter}
import cats.{Monad, MonoidK, FunctorFilter, Defer}

/** Contains instances for `cats` typeclasses.
*
Expand All @@ -20,4 +20,10 @@ object catsinstances {
with FunctorForParsley
with MonoidKForParsley
with FunctorFilterForParsley

/** Instance for `cats` `Defer` typeclass, which allows for recursive parser generation.
*
* @since 0.2.0
*/
implicit val deferForParsley: Defer[Parsley] = new DeferForParsley
}
8 changes: 8 additions & 0 deletions parsley-cats/shared/src/test/scala/parsley/CatsSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers._
import org.scalactic.source.Position

import parsley.Parsley.pure
import parsley.character.{item, digit, char}
import parsley.catsinstances._

Expand Down Expand Up @@ -48,4 +49,11 @@ class CatsSuite extends AnyFlatSpec {
applyLaw(monoidKLaws.monoidKLeftIdentity(item), monoidKLaws.monoidKRightIdentity(item))("", "a", "b")
applyLaw(monoidKLaws.combineAllK(Vector(char('a'), char('b'), char('c'))))("", "a", "b", "c")
}

"Defer" should "allow for the construction of recursive parsers" in {
val manya = deferForParsley.fix[List[Char]] { self =>
char('a') <::> self <|> pure(Nil)
}
manya.parse("aaaaaaaaaaaab") shouldBe Success(List.fill(12)('a'))
}
}

0 comments on commit 4b415c8

Please sign in to comment.