Ожидаемый тип парсера в методе "|" - PullRequest
4 голосов
/ 05 августа 2010

У меня следующий код, скомпилированный для scala 2.8.0:

import scala.util.parsing.combinator.{syntactical,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]()

Компиляция MyParser1 дает:

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]]

Я полагаю, что это не получается из-за |сигнатура типа метода, определяемая как:

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

, почему U должен быть супертипом T?Каким должно быть возвращаемое значение "primitiveType"?

Ответы [ 2 ]

5 голосов
/ 05 августа 2010

Вам нужно изменить свою последнюю строку на

case class PrimitiveType[+T]()

Это позволяет использовать PrimitiveType [Int]

Кстати, я бы тоже предложил написать

PrimitiveType[AnyVal]

вместо

PrimitiveType[_]

, поскольку это более точно в вашем случае.

3 голосов
/ 05 августа 2010

Возможно, вам лучше изменить общий case class PrimitiveType[T] на иерархию классов. Параметры универсального типа недоступны во время выполнения, поэтому вы не сможете многое сделать с результатами анализа ...

Это даст вам следующее ( непроверенный код сейчас проверено):

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
...