diff --git a/core/shared/src/main/scala/cats/parse/Parser.scala b/core/shared/src/main/scala/cats/parse/Parser.scala index 70656240..710bc155 100644 --- a/core/shared/src/main/scala/cats/parse/Parser.scala +++ b/core/shared/src/main/scala/cats/parse/Parser.scala @@ -981,6 +981,22 @@ object Parser { if (str.length == 0) unit else ignoreCase(str) + /** Convert a Map[Char, A] to Parser[A] first match a character, then map it to a value A + */ + def fromCharMap[A](charMap: Map[Char, A]): Parser[A] = + charIn(charMap.keySet).map(charMap) + + /** Convert a Map[String, A] to Parser[A] first match a character, then map it to a value A This + * throws if any of the keys are the empty string + */ + def fromStringMap[A](stringMap: Map[String, A]): Parser[A] = + stringIn(stringMap.keySet).map(stringMap) + + /** Convert a Map[String, A] to Parser[A] first match a character, then map it to a value A + */ + def fromStringMap0[A](stringMap: Map[String, A]): Parser0[A] = + stringIn0(stringMap.keySet).map(stringMap) + /** go through the list of parsers trying each as long as they are epsilon failures (don't * advance) see @backtrack if you want to do backtracking. * diff --git a/core/shared/src/test/scala/cats/parse/ParserTest.scala b/core/shared/src/test/scala/cats/parse/ParserTest.scala index 8e3e77a8..920e5ac6 100644 --- a/core/shared/src/test/scala/cats/parse/ParserTest.scala +++ b/core/shared/src/test/scala/cats/parse/ParserTest.scala @@ -2513,6 +2513,31 @@ class ParserTest extends munit.ScalaCheckSuite { } } + property("fromCharMap works as expected") { + forAll { (cm: Map[Char, Int], str: String) => + val p = Parser.fromCharMap(cm) + + assertEquals(p.parseAll(str), Parser.charIn(cm.keySet).parseAll(str).map(cm(_))) + } + } + + property("fromStringMap works as expected") { + forAll { (cm0: Map[String, Int], str: String) => + val cm = cm0.filterNot(_._1.isEmpty) + val p = Parser.fromStringMap(cm) + + assertEquals(p.parseAll(str), Parser.stringIn(cm.keySet).parseAll(str).map(cm(_))) + } + } + + property("fromStringMap0 works as expected") { + forAll { (cm: Map[String, Int], str: String) => + val p = Parser.fromStringMap0(cm) + + assertEquals(p.parseAll(str), Parser.stringIn0(cm.keySet).parseAll(str).map(cm(_))) + } + } + property("a context0 added is always at the top") { forAll(ParserGen.gen0, Arbitrary.arbitrary[List[String]], Arbitrary.arbitrary[String]) { (genP, ctx, str) =>