我试图解析一个简单的scala表达式:val a = 4 + 5
4.
然而,每当我运行它,我得到错误:
line 1:0 extraneous input 'val a = 4 + 5' expecting {<EOF>, 'implicit', 'lazy', 'case', '@', 'override', 'abstract', 'final', 'sealed', 'private', 'protected', 'import', 'class', 'trait', 'package', ';'}
下面是我的代码:
object AntlrMain {
val v = "val a = 4 + 5"
val stream = new ANTLRInputStream(v)
val lexer = new ScalaLexer(stream)
val tokens = new CommonTokenStream(lexer)
val parser = new ScalaParser(tokens)
val tree: ParseTree = parser.compilationUnit()
}
ScalaLexer和ScalaParser是从这里的scala语法生成的:https://github.com/antlr/grammars-v4/blob/master/scala/Scala.g4
我做错了什么?
编辑
在sepp2k的注释之后,我试图将val v更改为以下内容:
val v = "object Test { def a(): Int = 4 + 5 }"
,但是同样的错误仍然存在。至于使用blockStat()的建议-它适用于v的前一个值
val a = 4 + 5
不是有效的Scala文件。val
需要在class
, trait
或object
内(或在其中一个def
内)。错误信息给出了一个关键字列表,您可以在顶层或文件中使用这些关键字。
如果您希望能够单独解析val
定义,您应该解析与compilationUnit
不同的规则。如果你试图实现类似REPL的东西,blockStat
可能是有意义的,它包括任何可以在块中作为语句出现的东西(如局部定义或表达式)。
至于为什么它不能与object
一起工作:显然,语法只允许object
,如果它前面有case
(您会注意到object
没有出现在最初期望的令牌列表中)。如果我们查看语法内部,我们会发现:
tmplDef
: 'case'? 'class' classDef
| 'case' 'object' objectDef
| 'trait' traitDef
;
所以case
关键字在类定义之前是可选的,但在对象定义之前是必需的。
这显然是语法中的一个错误。在真正的Scala语言中,case
是可选的。