我正在创建一个 DSL,并使用 Scala 的解析器组合库来解析 DSL。DSL 遵循简单的类似 Ruby 的语法。源文件可以包含一系列如下所示的块:
create_model do
at 0,0,0
end
行尾在 DSL 中很重要,因为它们被有效地用作语句终止符。
我写了一个 Scala 解析器,看起来像这样:
class ML3D extends JavaTokenParsers {
override val whiteSpace = """[ \t]+""".r
def model: Parser[Any] = commandList
def commandList: Parser[Any] = rep(commandBlock)
def commandBlock: Parser[Any] = command~"do"~eol~statementList~"end"
def eol: Parser[Any] = """(\r?\n)+""".r
def command: Parser[Any] = commandName~opt(commandLabel)
def commandName: Parser[Any] = ident
def commandLabel: Parser[Any] = stringLiteral
def statementList: Parser[Any] = rep(statement)
def statement: Parser[Any] = functionName~argumentList~eol
def functionName: Parser[Any] = ident
def argumentList: Parser[Any] = repsep(argument, ",")
def argument: Parser[Any] = stringLiteral | constant
def constant: Parser[Any] = wholeNumber | floatingPointNumber
}
由于行尾很重要,因此我进行了覆盖whiteSpace
,以便它只会将空格和制表符视为空格(而不是将新行视为空格,从而忽略它们)。
这有效,除了commandBlock
. 由于我的源文件包含一个尾随的新行,解析器抱怨它只期望一个end
但在end
关键字之后有一个新行。
所以我将commandBlock
' 的定义更改为:
def commandBlock: Parser[Any] = command~"do"~eol~statementList~"end"~opt(eol)
(也就是说,我在“end”之后添加了一个可选的新行)。
但是现在,在解析源文件时,出现以下错误:
[4.1] failure: `end' expected but `' found
我认为这是因为,在它吸收了尾随的新行之后,解析器遇到了一个它认为无效的空字符串,但我不确定它为什么这样做。
有关如何解决此问题的任何提示?我可能会从 Scala 的解析器组合库中扩展错误的解析器,因此也欢迎任何关于如何创建具有重要换行符的语言定义的建议。