scalac缺少关闭括号错误报告与奇怪的行号

时间:2012-08-21 07:31:38

标签: parsing scala compiler-construction scalac

由于我一直在学习Scala,因此在阅读g++的神秘输出时,我常常会想到scalac编译器错误。然而,今天我遇到了一些我怀疑即使在g++宇宙中也会发生的事情。

朋友给我发了一个非常简单的代码片段,其中包含一个相当常见的错误:

case class Var(name: String) extends ArithExpr {
  override def eval(env: Env) =  env.lookup(name) match {
    case Some(d) => d
    case None => throw new IllegalArgumentException("Env " + env + " does not contain a binding for " + name)
  }
  override def exprString = name
// } // <-- MISSING THIS BRACE

完整的源文件is posted here。由于case class Var类声明缺少其右括号,您会认为编译器会告诉您该声明的开括号(第11行)缺少其右括号。但是,scalac报告它在前一个case class声明的中间“假设”缺少右括号(第7行)。 (完整的错误输出包含在发布的代码的底部。)

如果你理解语言的内部,那么大多数scalac错误信息都有意义,但我在这里完全失败了。在后面的类声明中,缺少的右括号如何最终传播到文件中先前已成功解析的类定义?

你到底如何向Scala初学者解释这个问题?离开一个右大括号正是Scala新手常常会犯的那种错误,但是这里的错误信息似乎会导致用户误入歧途,报告像{{1}这样的东西可能会更有帮助。而不是。

注意:我知道像这样的问题的通常答案只是“使用IDE并且增量编译会立即标记它”或“语法突出显示应该使此错误显而易见” - 但我的问题是具体要求关于error: you seem to be missing a '}' somewhere输出,所以请记住,我知道这些是有效点,但我真的只是想了解编译器在这里发生了什么。

更新

让我尝试一种不同的方法来解释我的困惑。错误源于缺少右括号,所以它显然是支撑嵌套的问题。转换我发布到一系列行号+括号对的片段中的文本(代码),我们得到了这个:

scalac

我们显然缺少一个闭合支撑。我能理解1{ 4} 6{ 9} 11{ 12{ 15} 19{ 22} 24{ 26} 28{ 33} 猜测丢失的括号可以进入这些地方中的任何一个(每个地方用scalac表示):

x

然而,这是1{ 4} 6{ 9} 11{ x 12{ x 15} x <-- HERE OR HERE OR HERE 19{ x 22} x <-- OR HERE OR HERE 24{ x 26} x <-- OR HERE OR HERE 28{ x 33} x <-- OR HERE OR HERE 的输出所说的:

scalac

输入的那部分已经很好地嵌套了!怎么可能在那里添加另一个右支架呢?

编辑:我觉得我应该再次重申我的主要问题:您将如何解释此错误消息(以及如何在源中找到错误的根源) Scala的新手?

2 个答案:

答案 0 :(得分:5)

考虑以下示例(我故意删除了缩进):

case class Foo( i: Int ) {
case class Bar( d: Double ) {
def get = d 
}

它没有编译,但有几种可能正确的代码:

case class Foo( i: Int ) {
}
case class Bar( d: Double ) {
  def get = d 
}

//OR

case class Foo( i: Int ) {
  case class Bar( d: Double ) {
    def get = d 
  }
}

//OR even (still won't compile but the structure is correct so the compiler will proceed with
//another error)

case class Foo( i: Int ) {
  case class Bar( d: Double ) { }
  def get = d 
}

那么编译器应该如何猜测哪个版本是正确的?在这种情况下,它选择了第一个有意义的位置:

hello.scala:3: error: Missing closing brace `}' assumed here
def get = d

这对应于第三种选择。

答案 1 :(得分:1)

根据JörgWMittag在我的问题评论中提出的建议,我已经在Scala问题跟踪器中重新打开旧票证:Confusing Unmatched closing brace errors。我已经将此问题的代码添加为此类令人困惑的错误消息的一个新的,简短的,可重现的示例。