Dao*_*Wen 6 compiler-construction parsing scala 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
Run Code Online (Sandbox Code Playgroud)
完整的源文件发布在这里.由于case class Var类声明缺少其结束括号,您会认为编译器会告诉您该声明的开头括号(第11行)缺少其右括号.但是,scalac报告称它"假定"在前一个case class声明中间缺少右括号(第7行).(完整的错误输出包含在发布的代码的底部.)
scalac如果您了解语言的内部,大多数错误消息都有意义,但我在这里完全失去了.在后面的类声明中,缺少的右括号如何最终传播到文件中较早的已成功解析的类定义?
你到底如何向Scala初学者解释这个问题?离开一个右大括号正是Scala新手常常会犯的那种错误,但是这里的错误信息似乎会导致用户误入歧途,因此报告类似的东西可能会更有帮助error: you seem to be missing a '}' somewhere.
注意:我知道像这样的问题的通常答案只是"使用IDE并且增量编译将立即标记它"或"语法突出显示应该使此错误显而易见" - 但我的问题是具体询问scalac输出,所以请请记住,我知道这些是有效点,但我真的只是想了解编译器在这里发生了什么.
让我尝试一种不同的方法来解释我的困惑.错误源于缺少右括号,所以它显然是支撑嵌套的问题.转换我发布到一系列行号+括号对的片段中的文本(代码),我们得到这个:
1{ 4}
6{ 9}
11{ 12{ 15}
19{ 22}
24{ 26}
28{ 33}
Run Code Online (Sandbox Code Playgroud)
我们显然缺少一个结束支架.我可以理解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
Run Code Online (Sandbox Code Playgroud)
但是,这就是输出的内容scalac:
+----- I THINK YOU ARE MISSING A
| CLOSING BRACE RIGHT HERE!
1{ V 4}
6{ x 9}
11{ 12{ 15}
19{ 22}
24{ 26}
28{ 33}
Run Code Online (Sandbox Code Playgroud)
输入的那部分已经很好地嵌套了!怎么可能添加另一个右支撑可能有任何意义?
编辑:我觉得我应该再次重申我的主要问题:你将如何解释这个错误消息(以及如何在源代码中找到错误的根源)给Scala的新手?
考虑以下示例(我故意删除了缩进):
case class Foo( i: Int ) {
case class Bar( d: Double ) {
def get = d
}
Run Code Online (Sandbox Code Playgroud)
它没有编译,但有几个可能正确的代码:
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
}
Run Code Online (Sandbox Code Playgroud)
那么编译器应该如何猜测哪个版本是正确的呢?在这种情况下,它选择了第一个有意义的位置:
hello.scala:3: error: Missing closing brace `}' assumed here
def get = d
Run Code Online (Sandbox Code Playgroud)
这对应于第三种选择.
按照 J\xc3\xb6rg W Mittag 在对我的问题的评论中提出的建议,我在 Scala 问题跟踪器中重新打开了一张旧票: Confusing Unmatched close braces Errors。我已添加此问题中的代码作为此类令人困惑的错误消息的新的、简短的、可重现的示例。
\n| 归档时间: |
|
| 查看次数: |
1781 次 |
| 最近记录: |