Its my first time using scala's parser combinators. I have this situation where I have a list of 'types' and they can extend other types, or not. If they do I just create a map between the type and its parent type. If not I just map the type to 'object'. (Types are just string names)
They are written like this:
type1 type2 type3 - parentType
or
type0a type0b
in which case they will implicitly be - object
I tried to implement it in the following way, but its not compiling. Its saying that it requires an Option[~List[String, String] and it found ~[a,b]. Its also saying it cannot find the value names in the first for comprehension, when in fact its specified in the case pattern match. A bit confused now what is actually happening.
def type_list = ((name+) ~ ("-" ~> parent_type)?) ^^ {
case names ~ parent_type => for (name <- names) yield name -> parent_type
case names => for (name <- names) yield name -> "object"
}
def name = """[a-zA-Z\d]+""".r
Actually I just want this to return a Map[String, String]
, if the parent_type
is missing it should default to "object".
How is it best to approach this?
There's a couple of things going on here.
Firstly the precedence of ~ and ? means that instead of combining (name+) which is a Parser[List[String]] with ( "-" ~> parent_type )? which is a Parser[Option[String]] you're actually wrapping the whole thing in ? and so getting a Parser[Option[~[List[String],String]] if that makes sense.
The easiest solution is to use an extra set of brackets.
So you want to start with:
Then in the mapping function what'll you'll receive is a ~[List[String],Option[String]] with the list of names and an optional parent_type. In terms of pattern matching you always get name ~ parent_type where the latter is an Option[String]. So basically your second pattern is invalid.
So you could either do this:
Or you could simplify this to: