parsing - Scala组合器解析器,>>是什么意思?

标签 parsing scala parser-combinators

我对scala中的“>>”有点困惑。丹尼尔在 Scala parser combinators parsing xml? 中说它可以用来根据前一个解析器的结果参数化解析器。有人可以给我一些例子/提示吗?我已经阅读了scaladoc,但仍然不明白。

谢谢

最佳答案

正如我所说,它用于参数化解析器,但让我们通过一个示例来说明清楚。

让我们从一个简单的解析器开始,它解析一个数字后跟一个单词:

def numberAndWord = number ~ word
def number        = "\\d+".r
def word          = "\\w+".r

RegexParsers 下,这将解析像“3个水果”这样的东西。

现在,假设您还想要这些“n 事物”的列表。例如,“3 种水果:香蕉、苹果、橙子”。让我们尝试解析它,看看它是如何进行的。

首先,我如何解析“N”个东西?碰巧,有一个 repN方法:
def threeThings = repN(3, word)

这将解析“香蕉苹果橙”,而不是“香蕉,苹果,橙”。我需要一个分隔符。有repsep这提供了这一点,但这不会让我指定我想要多少次重复。所以,让我们自己提供分隔符:
def threeThings = word ~ repN(2, "," ~> word)

好吧,那句话。我们现在可以为三件事编写整个示例,如下所示:
def listOfThings = "3" ~ word ~ ":" ~ threeThings
def word         = "\\w+".r
def threeThings  = word ~ repN(2, "," ~> word)

那种工作,除了我在3中修复“N”。我想让用户指定多少。这就是>> ,也称为 into (并且,是的,它是 flatMap 对于 Parser ),进入。首先,让我们更改threeThings :
def things(n: Int) = n match {
  case 1          => word ^^ (List(_))
  case x if x > 1 => word ~ repN(x - 1, "," ~> word) ^^ { case w ~ l => w :: l }
  case x          => err("Invalid repetitions: "+x)
}

这比您预期的要复杂一些,因为我强制它返回 Parser[List[String]] .但是如何将参数传递给事物?我的意思是,这行不通:
def listOfThings = number ~ word ~ ":" ~ things(/* what do I put here?*/)

但是我们可以这样重写:
def listOfThings = (number ~ word <~ ":") >> {
  case n ~ what => things(n.toInt)
}

这几乎已经足够了,只是我现在输了nwhat :它只返回“列表(香蕉,苹果,橙子)”,而不是应该有多少,以及它们是什么。我可以这样做:
def listOfThings   = (number ~ word <~ ":") >> {
  case n ~ what => things(n.toInt) ^^ { list => new ~(n.toInt, new ~(what, list)) }
}
def number         = "\\d+".r
def word           = "\\w+".r
def things(n: Int) = n match {
  case 1          => word ^^ (List(_))
  case x if x > 1 => word ~ repN(x - 1, "," ~> word) ^^ { case w ~ l => w :: l }
  case x          => err("Invalid repetitions: "+x)
}

只是最后的评论。你可能想知道问自己“你是什么意思flatMap?那不是一个单子(monad)/理解的东西吗?”为什么,是的,是的! :-) 这是另一种写法listOfThings :
def listOfThings   = for {
  nOfWhat  <- number ~ word <~ ":"
  n ~ what = nOfWhat
  list     <- things(n.toInt)
}  yield new ~(n.toInt, new ~(what, list))

我不做n ~ what <- number ~ word <~ ":"因为那使用 filterwithFilter在 Scala 中,Parsers 未实现.但这里甚至还有另一种写法,它没有完全相同的语义,但产生相同的结果:
def listOfThings   = for {
  n    <- number
  what <- word
  _    <- ":" : Parser[String]
  list <- things(n.toInt)
}  yield new ~(n.toInt, new ~(what, list))

这甚至可能让人认为“单子(monad)无处不在”的说法可能有一定的意义。 :-)

关于parsing - Scala组合器解析器,>>是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7979154/

相关文章:

haskell - 使用解析器组合器解析 Haskell 本身

json - Swift - 保存异步数据

Scala - 为紧凑性定义类型还是为了可读性而明确地编写它?

scala - 映射 Spark 行中数组的每个值

scala - 在scala中匹配大小未知的元组

parsing - 基于 Agda 上的一篇论文在 Idris 中实现 Total Parser

java - 将 XML 解析为 Java 对象,需要澄清

python - 在最后一个正斜杠和第一个连字符之前获取文本

python - 找到时间戳列表中的最大间隔(Perl 首选)

用于递归 bnf 的 Scala Parser Combinators 技巧?