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

使用しないでくださいparseAllparse代わりに使用してください。

あなたが抱えている問題については、いくつかの場所で同じことを 2 回言っています。

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)

重要なことは、一致するだけではいけないということです。テキスト行を取得するに.*は、一致する必要があります ( Windows 形式のファイルにはこれが必要です)。うまくいくと思っていたものも試しましたが、うまくいきません。どちらもありません。.*\r?\n\r^.*$".*" <~ """\r?\n""".r

(^?は に似て^^いますが、部分関数を取る点が異なります。)

誰かがこれをよりエレガントにすることができる場合は、私に知らせてください!

于 2012-06-25T02:47:45.183 に答える