开发者

Expected type of Parser in method "|"

开发者 https://www.devze.com 2023-01-10 13:18 出处:网络
I have the following code being compiled against scala 2.8.0: import scala.util.parsing.combinator.{syntacti开发者_C百科cal,PackratParsers}

I have the following code being compiled against scala 2.8.0:

import scala.util.parsing.combinator.{syntacti开发者_C百科cal,PackratParsers}
import syntactical.StandardTokenParsers

object MyParser extends StandardTokenParsers with PackratParsers{
  lexical.reserved ++= Set("int","char","boolean")

  lazy val primitiveType:PackratParser[PrimitiveType[_]] = primitiveChar | primitiveInt | primitiveBool

  lazy val primitiveInt:PackratParser[PrimitiveType[Int]] = "int" ^^ { _ => PrimitiveType[Int]() }

  lazy val primitiveChar:PackratParser[PrimitiveType[Char]] = "char" ^^ { _ => PrimitiveType[Char]() }

  lazy val primitiveBool:PackratParser[PrimitiveType[Boolean]] = "boolean" ^^ { _ => PrimitiveType[Boolean]() }
}

object MyParser2 extends StandardTokenParsers with PackratParsers{
  lexical.reserved ++= Set("int","char","boolean")

  lazy val primitiveType:PackratParser[PrimitiveType[_]] =  primitiveChar | primitiveIntOrBool

  lazy val primitiveIntOrBool:PackratParser[PrimitiveType[_]] = "int" ^^ { _ => PrimitiveType[Int]() } | "boolean" ^^ {_ => PrimitiveType[Boolean]()}

  lazy val primitiveChar:PackratParser[PrimitiveType[Char]] = "char" ^^ { _ => PrimitiveType[Char]()} 
}

case class PrimitiveType[T]()

Compiling MyParser1 gives:

error: inferred type arguments  [this.PrimitiveType[_ >: _1 with Boolean <: AnyVal]] do not conform to method |'s type parameter bounds [U >: this.PrimitiveType[_ >: Char with Int <: AnyVal]]

I believe it fails because of the | method type signature, defined as:

def | [U >: T](q: => Parser[U]): Parser[U]

why does U have to be a supertype of T? What should be the return value of "primitiveType"?


You need to change your last line into

case class PrimitiveType[+T]()

This allows for PrimitiveType[Int] <: PrimitiveType[AnyVal] which is needed when you want to merge the results of PrimitiveType[Boolean] and PrimitiveType[Int] parsers via |.

BTW, I would also suggest to write

PrimitiveType[AnyVal]

instead of

PrimitiveType[_]

since this is more precise in your case.


You might be better changing your generic case class PrimitiveType[T] to a class hierarchy. The generic type parameters aren't available at runtime, so you won't be able to do much with your parse results...

This would give you the following (untested code now tested):

object MyParser extends StandardTokenParsers with PackratParsers{
  lexical.reserved ++= Set("int","char","boolean")

  lazy val primitiveType:Parser[PrimitiveType] = primitiveChar | primitiveInt | primitiveBool

  lazy val primitiveInt:PackratParser[PrimitiveType] = "int" ^^^ PrimitiveInt

  lazy val primitiveChar:PackratParser[PrimitiveType] = "char" ^^^ PrimitiveChar

  lazy val primitiveBool:PackratParser[PrimitiveType] = "boolean" ^^^ PrimitiveBoolean
}

sealed trait PrimitiveType
case object PrimitiveInt extends PrimitiveType
case object PrimitiveChar extends PrimitiveType
case object PrimitiveBoolean extends PrimitiveType
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号