【问题标题】:Parsing sentences using Scala parser combinator使用 Scala 解析器组合器解析句子
【发布时间】:2014-01-25 19:56:47
【问题描述】:

我刚开始在 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 的定义如下.

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

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

有什么想法吗?

【问题讨论】:

    标签: scala parser-combinators


    【解决方案1】:

    但是,解析器卡住了(添加 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 组合器,但我认为每个句子至少需要一个单词。

    【讨论】:

    • 谢谢。至于简化word,您是对的,在示例中,您的解决方案更有意义。我试图解决的原始问题有一个更复杂的域,其中 character 的等价物更复杂,需要指定自己的解析器。
    猜你喜欢
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多