score:5
It's possible with Shapeless2 library. For given:
object MyParser extends scala.util.parsing.combinator.RegexParsers
import MyParser._
val foo: Parser[String] = "foo"
val bar: Parser[String] = "bar"
val car: Parser[String] = "car"
case class Record(f: String, b: String, c: String)
You can combine parsers using generic foldRight
intead of ~
:
import shapeless._
object f extends Poly2 {
implicit def parser[T, U <: HList] =
at[Parser[T], Parser[U]]{(a, b) =>
for {aa <- a; bb <- b} yield aa :: bb
}
}
val p: Parser[Record] = (foo :: bar :: car :: HNil)
.foldRight(success(HNil))(f).map(Generic[Record].from)
Result:
scala> parseAll(p, "foo bar car").get
res50: Record = Record(foo,bar,car)
P.S. The problem with built-in scala functionality is that they built ~
-based typed binary tree, which is hard to traverse and flatten to tuple. Shapeless solves this problem - it has it's own ::
-based binary tree called HList
, it's simmilar but has interesting operations, like convertion to tuples or case classes (probably macro-based). In this example I use foldLeft
to build Shapeless-hlist and for-comprehension (expands to flatMap
on parser) to combine parsers as they have monadic nature. In shapeless you have to define foldLeft
's handler as set of generic implicits, that can process generic input (like T
or U
).
You can reuse my f
object to combine any parsers in typesafe way (you can combine even different types here - that's fine).
Second, less generic, way is:
implicit class as2[A, B](t: Parser[A ~ B]){ def ^^^^[T] (co: (A, B) => T) = t map {tt => val (a ~ b) = tt; co(a, b)} }
implicit class as3[A, B, C](t: Parser[A ~ B ~ C]){ def ^^^^[T] (co: (A, B, C) => T) = t map {tt => val (a ~ b ~ c) = tt; co(a, b, c)} }
...
implicit class as21 ...
Usage:
scala> val p = foo ~ bar ~ car ^^^^ Record
p: MyParser.Parser[Record] = Parser ()
scala> parseAll(p, "foo bar car").get
res53: Record = Record(foo,bar,car)
It's not so cool, but doesn't require external libraries.
Source: stackoverflow.com
Related Query
- Apply parser combinator to case class
- How to override apply in a case class companion
- Scala case class private constructor but public apply method
- Case Class default apply method
- Prohibit generating of apply for case class
- scala case class private apply method( repl bug ?)
- How can I apply a macro annotation to a case class with a context bound?
- Scala: method apply is defined twice when trying to overload case class apply method
- How to apply toJson to instance of a case class using spray-json library
- How to retrieve the apply method of a case class
- In scala, use reflection on a case class classtag to find the companion object's apply method
- Why scala case class generates two apply methods?
- How to partially apply case class with type parameter in Scala
- How to apply a function on each field of a case class
- How to apply @ConstructorProperties to a case class in Scala?
- Scala Parser Combinator compilation issue: failing to match multiple variables in case
- Scala ambiguous case class generated and companion apply method
- How to apply functions in Scala case class for transforming dataframes
- Scala case class and companion object can't override apply with diff signature
- Omiting parameter in case class apply
- Case class apply method, What does this syntax means?
- No apply function found when trying to convert a case class (derived from Trait) to Json
- Apply a method to all fileds of a case class of a specific type
- How to automatically apply modifications to all/some fields of a case class in Scala?
- Scala 3 Varargs apply method for case class
- Scala - Split array within array, extract certain information and apply to case class
- Scala Reflect Case Class Apply Method Runtime
- How do I define Json format for a case class with more than one apply method?
- What is the difference between Scala's case class and class?
- How to clone a case class instance and change just one field in Scala?
More Query from same tag
- Scala: Using TypeTag in a method
- I have installed sbt, but still I do not get the REPL
- Scala: Checking if 2 variables are of the same type
- How to create query in Elastic4s
- How to get just directory name from HDFS
- Scala: modify a NodeSeq
- how to execute a command in scala?
- Failed to created JLineReader (Scala REPL)
- standardized way to include unique vcs (e.g. GIT sha) to maven artifact
- Scala : Retry with try/catch for exception handling
- Spark - Scala - Replacing value in dataframe with lookup value from another data frame
- How to parse Json data returned from a HTTP request in scala
- Why does overloading polymorphic methods with different upper bounds not compile in Scala
- Angularjs + OAuth + Play 2.0
- Where do Scala console commands come from and what are they syntactically?
- Is it possible to reorder tasks in Spark stage
- Reference field of object using string value scala macro
- What is the best way to manage handing off of closeable resources in Scala?
- How do I give global access to an object in Scala without making it a singleton or passing it to everything?
- How do you match with guards in Racket?
- Mixing scala and java in Play Framework
- kafka how to pass argument to a consumer using scala
- Variable reference inside SQLSyntax when constructing SQL query in ScalalikeJdbc
- Dynamically choose implementation of logger in Scala
- Why += doesn't work with Lists?
- Apache Flink: InvalidProgramException: Table program cannot be compiled
- type mismatch error declaring list of classes
- Regex throws error while having pipe symbol on scala code
- Split key value in map scala
- Strategy pattern in Akka