匹配大括号代码不会终止

时间:2015-06-26 04:24:03

标签: scala parsing

我有以下代码来检查字符串。我们想要验证它以'{'开头并以'}'结尾,并且它包含非“{}”字符序列和具有此属性的字符串。

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死亡。我做错了什么,我应该做些什么呢?

1 个答案:

答案 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 } {}}
  }
}