使用Scala解析器组合器解析句子

时间:2014-01-25 19:56:47

标签: scala parser-combinators

我刚刚开始在Scala中使用解析器组合器,但却被困在解析器上来解析诸如“我喜欢Scala”之类的句子。 (单词以空格或句点结尾(.))。

我从以下实施开始:

package example

import scala.util.parsing.combinator._

object Example extends RegexParsers {
  override def skipWhitespace = false

  def character: Parser[String] = """\w""".r

  def word: Parser[String] =
    rep(character) <~ (whiteSpace | guard(literal("."))) ^^ (_.mkString(""))

  def sentence: Parser[List[String]] = rep(word) <~ "."
}

object Test extends App {
  val result = Example.parseAll(Example.sentence, "I like Scala.")

  println(result)
}

使用guard()背后的想法是有一个句点划分单词结尾,但不消耗它以便句子可以。但是,解析器卡住了(添加log()显示它反复尝试wordcharacter解析器。)

如果我按如下所示更改wordsentence定义,它会解析句子,但语法描述看起来不正确,如果我尝试为段落添加解析器({ {1}})等。

rep(sentence)

这里可能有什么想法?

1 个答案:

答案 0 :(得分:2)

  

然而,解析器卡住了(添加log()显示它反复尝试单词和字符解析器)。

rep组合符对应于perl样式正则表达式中的*。这意味着它匹配 或更多字符。我认为您希望它与 一个 或更多字符相匹配。将其更改为rep1(对应于perl样式正则表达式中的+)应该可以解决问题。

但是,你的定义对我来说似乎有点冗长。为什么要解析单个字符而不是仅使用\w+作为单词的模式?这是我写的方式:

object Example extends RegexParsers {
  override def skipWhitespace = false

  def word: Parser[String] = """\w+""".r

  def sentence: Parser[List[String]] = rep1sep(word, whiteSpace) <~ "."
}

请注意,我使用rep1sep来解析由空格分隔的非空单词列表。还有一个repsep组合子,但我认为你每个句子至少需要一个单词。