3

斯卡拉 2.8.1

我已经使用解析器/组合器实现了一个非常简单的外部 DSL,用于 QA 编写验收测试。

最近我添加了像这样循环一组表达式的能力

sealed trait Expr

...
//insert other case classes extending 'Expr' here
...

case class Repetition(times: Int, expressions: List[Expr]) extends Expr

class TestFixtureParser(....) extends RegexParsers {
  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    case (times: Int) ~ (exprs: List[Expr]) => {
      Repetition(times, exprs)
    }
  }

  private val expressions: Parser[List[Expr]] = (repeatParser | 
    /*insert other Parser[Expr]s '|' together here */ | verifyParser ).*

}

warning: non variable type-argument ... is unchecked since it is eliminated by erasure构建时,我在模式匹配时收到警告。我也尝试过使用以下内容进行提取。

  //Doesn't build with error
  /*
    error: missing parameter type for expanded function ((x0$2) => x0$2 match {
      case $tilde((times @ _), (exprs @ _)) => Repetition(times, exprs)
    })
        r: ~[Int, List[Expr]] => {
  */
  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    r: ~[Int, List[Expr]] => {
      case times ~ exprs =>
        Repetition(times, exprs)
    }
  }

  //Actually this does build without warning. 
  //I am unfortunately using intelliJ and it doesn't like it
  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    repetitions: ~[Int, List[Expr]] => {
      val ~(times, exprs) = repetitions
      Repetition(times, exprs)
    }
  }

  //Builds but same warning
  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    repetitions => {
      val ~(times: Int, exprs: List[Expr]) = repetitions
      Repetition(times, exprs)
    }
  }

exprs有没有人有任何建议在没有这个警告的情况下以优雅的方式提取?它按原样运行。我应该忽略它吗?我不想养成无视警告的习惯。

编辑:回答。这实际上是我首先尝试的,但后来我添加了类型,因为 intelliJ scala 插件无法推断它们。

  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
      case times ~ exprs =>
          Repetition(times, exprs)
  }
4

2 回答 2

5

我认为您的语法不适合第一个“不构建”示例(看起来您正在返回部分函数而不是应用它,这不是您想要的)。试着写:

val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    case times ~ exprs =>
        Repetition(times, exprs)
}

恐怕我无法对此进行测试,因为我没有它所依赖的其余代码,但这种构造通常有效。

于 2011-11-15T23:35:46.680 回答
2

公认的答案是最好的,但是当它不起作用时,这里有替代方案:

r: ~[t1, t2] => {
  case times ~ exprs =>
    Repetition(times, exprs)
}

上面 ,t1t2推断, 他们可能只是被推断Any. 但是,无论它们被推断为什么,这是您可以使用该语法做的最好的事情。

val ~(times: Int, exprs: List[t]) = repetitions

在这里,因为您正在提取值,所以您实际上可以检查类型。您不是在测试是否有~[Int,List[Int]]- 您正在测试提取的值是否具有类型IntList[t]. 请注意,您收到的警告来自 type 参数 to List

于 2011-11-16T03:04:27.933 回答