我有以下代码来检查字符串。我们想要验证它以'{'开头并以'}'结尾,并且它包含非“{}”字符序列和具有此属性的字符串。
import util.parsing.combinator._
class Comp extends RegexParsers with PackratParsers {
lazy val bracefree: PackratParser[String] = """[^{}]*""".r ^^ {
case a => a
}
lazy val matching: PackratParser[String] = (
"{" ~ rep(bracefree | matching) ~ "}") ^^ {
case a ~ b ~ c => a + b.mkString("") + c
}
}
object Brackets extends Comp {
def main(args: Array[String])= {
println(parseAll(matching, "{ foo {hello 3 } {}}").get)
}
}
所需的输出是回显{ foo {hello 3 } {}}
,但最终需要很长时间才能从java.lang.OutOfMemoryError: GC overhead limit exceeded
死亡。我做错了什么,我应该做些什么呢?
答案 0 :(得分:2)
你的无支撑字符串的正则表达式甚至匹配一个空字符串,因此rep()
生成的解析器成功而不消耗任何输入,并且会无休止地循环。
使用+
量词而不是*
:
lazy val bracefree: PackratParser[String] = """[^{}]+""".r ^^ {
case a => a
}
此外,默认情况下RegexParsers
将跳过空字符串和空格。要关闭此行为,只需覆盖方法skipWhitespace
即可始终返回false
。最后,您的解析器将如下所示:
import util.parsing.combinator._
class Comp extends RegexParsers with PackratParsers {
override def skipWhitespace = false
lazy val bracefree: PackratParser[String] = """[^{}]+""".r ^^ {
case a => a
}
lazy val matching: PackratParser[String] = (
"{" ~ rep(bracefree | matching) ~ "}") ^^ {
case a ~ b ~ c => a + b.mkString("") + c
}
}
object Brackets extends Comp {
def main(args: Array[String])= {
println(parseAll(matching, "{ foo {hello 3 } {}}").get)
// prints: { foo {hello 3 } {}}
}
}