我只想解析以下字符串,直到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。我做错了什么,以及如何解决这个问题?
答案 0 :(得分: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 }
)
}
答案 1 :(得分: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
上匹配才能获得一行文字(Windows需要\r
- 格式文件)。我也试过^.*$
,我认为它会起作用,但事实并非如此。 ".*" <~ """\r?\n""".r
也没有。
(^?
与^^
类似,但它需要部分功能。)
如果有人能让这更优雅,请告诉我!