Scala外部DSL - 由替代重复引起的无限循环

时间:2013-05-23 10:19:15

标签: scala grammar dsl parser-combinators

我正在尝试在Scala中构建一个简单的外部DSL,它能够解析像:

这样的字符串
value = "john${tom}peter${greg}${sue}meg"

通常,引号内的子字符串包含${}之间的隔行扫描名称和名称。

我的语法如下:

class Grammar extends JavaTokenParsers {
  def workflow = "value" ~> "=" ~> "\"" ~> pair <~ "\""

  def pair = rep(str | token)

  def str = rep(char)

  def char: Parser[String] = """[a-z]""".r

  def token = "$" ~> "{" ~> str <~ "}"
}

并执行:

var res = parseAll(workflow, str)
println(res)

我认为方法def pair = rep(str | token)可以正确解析它。它不仅不起作用,而且还导致parseAll方法中的无限循环。

我如何解析这样的字符串呢?似乎替代重复(rep)不是正确的方法。

1 个答案:

答案 0 :(得分:1)

您应该将rep替换为rep1

rep总是成功的(除非它是Error),所以在rep(char) | token右边(token)是没用的 - 你会得到一个空的 rep(char)的成功结果。

此外,您可以将"""[a-z]""".r替换为accept('a' to 'z'),也可以将str定义为def str: Parser[String] = """[a-z]+""".r。使用Regex来匹配单个Char是一种过度杀伤。