1

我只想解析以下字符串,直到END令牌然后忽略其余部分:

val input = """
0)
blah1
blah2
blah3
1)
blah4
blah5
END
blah6
"""

使用

object Pars extends RegexParsers {
  def strings: Parser[List[String]] = rep(str) <~ end
  def str:     Parser[String]       = ".*".r
  def end:     Parser[String]       = "END" <~ rep(".*".r)
}

Pars.parseAll(Pars.strings, input)

进入无限循环和 OutOfMemoryError。我做错了什么,如何解决这个问题?

4

2 回答 2

4

只是不要使用parseAll. 改为使用parse

至于你遇到的问题,你在几个地方说了两次同样的事情:

rep(".*".r)

rep两者*都表示“任意次数的重复”。现在,.*匹配空字符串,rep然后继续匹配无限数量的空字符串。

这是我重写它的方法:

object Pars extends RegexParsers {
  def strings: Parser[List[String]] = 
    ( "END" ^^^ Nil 
    | ".+".r ~ strings ^^ { case head ~ tail => head :: tail }
    )
}
于 2012-06-25T00:17:19.380 回答
0
object Pars extends RegexParsers { 
  def strings: Parser[List[String]] = rep(str) <~ "END"
  def str:     Parser[String]       = """.*\r?\n""".r ^? { 
    case s if !(s matches """END\r?\n""") => s.replaceAll("""[\r\n]""", "")
  }
}

Pars.parse(Pars.strings, input) // note parse, not parseAll
  //[9.4] parsed: List(0), blah1, blah2, blah3, 1), blah4, blah5)

关键似乎是你不能只匹配.*- 你必须匹配.*\r?\n才能获得一行文本(\rWindows格式文件需要)。我也尝试^.*$了我认为可行的方法,但没有。也没有".*" <~ """\r?\n""".r

^?类似于,^^除了它需要一个偏函数。)

如果有人可以使它更优雅,请告诉我!

于 2012-06-25T02:47:45.183 回答