我正在尝试在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
)不是正确的方法。
答案 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
是一种过度杀伤。