diff --git a/core/shared/src/main/scala/cats/parse/DefaultParser.scala b/core/shared/src/main/scala/cats/parse/DefaultParser.scala new file mode 100644 index 00000000..31597113 --- /dev/null +++ b/core/shared/src/main/scala/cats/parse/DefaultParser.scala @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Typelevel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package cats.parse + +/** Typeclass for "has a Parser" + * + * This is primarily provided to help keep track of `Parser` instances, and as such the omission of + * a `cats.Functor` instance is intentional. + * @tparam A + */ +trait DefaultParser[+A] { + def parser: Parser[A] + + /** Pass through to equivalent method on `Parser` + * @see + * [[Parser.parse]] + */ + def parse(string: String): Either[Parser.Error, (String, A)] = parser.parse(string) + + /** Pass through to equivalent method on `Parser` + * @see + * [[Parser.parseAll]] + */ + def parseAll(string: String): Either[Parser.Error, A] = parser.parseAll(string) +} +object DefaultParser { + def apply[A](implicit P: DefaultParser[A]): P.type = P + + def instance[A](p: Parser[A]): DefaultParser[A] = new Impl[A](p) + + private final class Impl[+A](override val parser: Parser[A]) + extends DefaultParser[A] + with Serializable + + object syntax { + implicit final class DefaultParserOps(private val raw: String) extends AnyVal { + def parse[A: DefaultParser]: Either[Parser.Error, (String, A)] = + DefaultParser[A].parser.parse(raw) + + def parseAll[A: DefaultParser]: Either[Parser.Error, A] = + DefaultParser[A].parser.parseAll(raw) + } + } +} diff --git a/core/shared/src/main/scala/cats/parse/DefaultParser0.scala b/core/shared/src/main/scala/cats/parse/DefaultParser0.scala new file mode 100644 index 00000000..64870789 --- /dev/null +++ b/core/shared/src/main/scala/cats/parse/DefaultParser0.scala @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Typelevel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package cats.parse + +/** Typeclass for "has a Parser0" + * + * This is primarily provided to help keep track of `Parser0` instances, and as such the omission + * of a `cats.Functor` instance is intentional. + * @tparam A + */ +trait DefaultParser0[+A] { + def parser0: Parser0[A] + + /** Pass through to equivalent method on `Parser0` + * @see + * [[Parser0.parse]] + */ + def parse(string: String): Either[Parser.Error, (String, A)] = parser0.parse(string) + + /** Pass through to equivalent method on `Parser0` + * @see + * [[Parser0.parseAll]] + */ + def parseAll(string: String): Either[Parser.Error, A] = parser0.parseAll(string) +} +object DefaultParser0 { + def apply[A](implicit P: DefaultParser0[A]): P.type = P + + def instance[A](p: Parser0[A]): DefaultParser0[A] = new Impl[A](p) + + private final class Impl[+A](override val parser0: Parser0[A]) + extends DefaultParser0[A] + with Serializable + + object syntax { + implicit final class DefaultParser0Ops(private val raw: String) extends AnyVal { + def parse[A: DefaultParser0]: Either[Parser.Error, (String, A)] = + DefaultParser0[A].parser0.parse(raw) + + def parseAll[A: DefaultParser0]: Either[Parser.Error, A] = + DefaultParser0[A].parser0.parseAll(raw) + } + } + + implicit def defaultParserIsDefaultParser0[A: DefaultParser]: DefaultParser0[A] = + DefaultParser0.instance(DefaultParser[A].parser) +}