Scala组合器解析器,什么是>?意思是? [英] Scala combinator parser, what does >> mean?

查看:92
本文介绍了Scala组合器解析器,什么是>?意思是?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对scala中的">>"感到困惑. Daniel在 Scala解析器组合器解析xml中说过说,它可以用于参数化解析器基于先前解析器的结果.有人可以给我一些例子/提示吗?我已经阅读了scaladoc,但仍然不明白.

I am little bit confusing about ">>" in scala. Daniel said in Scala parser combinators parsing xml? that it could be used to parameterize the parser base on result from previous parser. Could someone give me some example/hint ? I already read scaladoc but still not understand it.

谢谢

推荐答案

正如我所说,它用于对解析器进行参数化,但是让我们通过一个例子来阐明它.

As I said, it serves to parameterize a parser, but let's walk through an example to make it clear.

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

Let's start with a simple parser, that parses a number follow by a word:

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

下RegexParsers ,这将解析"3个水果"之类的内容.

Under RegexParsers, this will parse stuff like "3 fruits".

现在,假设您还想要这些"n事物"的清单.例如,"3个水果:香蕉,苹果,橙子".让我们尝试对其进行分析,以了解其进展.

Now, let's say you also want a list of what these "n things" are. For example, "3 fruits: banana, apple, orange". Let's try to parse that to see how it goes.

首先,我该如何解析"N"个东西?碰巧的是,有一个repN方法:

First, how do I parse "N" things? As it happen, there's a repN method:

def threeThings = repN(3, word)

这将解析香蕉苹果橙",而不是香蕉,苹果,橙".我需要一个分隔符.有repsep可以提供该功能,但不能让我指定所需的重复次数.因此,让我们自己提供分隔符:

That will parse "banana apple orange", but not "banana, apple, orange". I need a separator. There's repsep that provides that, but that won't let me specify how many repetitions I want. So, let's provide the separator ourselves:

def threeThings = word ~ repN(2, "," ~> word)

好吧,那句话.现在,我们可以为三个示例编写整个示例,如下所示:

Ok, that words. We can write the whole example now, for three things, like this:

def listOfThings = "3" ~ word ~ ":" ~ threeThings
def word         = "\\w+".r
def threeThings  = word ~ repN(2, "," ~> word)

这种工作方式,除了我要在3中固定"N"外,我想让用户指定数量.这就是>>的地方,也称为into(是的,对于ParserflatMap).首先,让我们更改threeThings:

That kind of works, except that I'm fixing "N" in 3. I want to let the user specify how many. And that's where >>, also known as into (and, yes, it is flatMap for Parser), comes into. First, let's change 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]].但是,如何将参数传递给事物呢?我的意思是,这行不通:

This is slightly more complicated than you might have expected, because I'm forcing it to return Parser[List[String]]. But how do I pass a parameter to things? I mean, this won't work:

def listOfThings = number ~ word ~ ":" ~ things(/* what do I put here?*/)

但是我们可以这样重写:

But we can rewrite that like this:

def listOfThings = (number ~ word <~ ":") >> {
  case n ~ what => things(n.toInt)
}

那几乎够了,除了我现在丢失了nwhat:它只返回列表(香蕉,苹果,橙子)",而不是应该有多少,以及它们是什么.我可以这样:

That is almost good enough, except that I now lost n and what: it only returns "List(banana, apple, orange)", not how many there ought to be, and what they are. I can do that like this:

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?这不是单子/理解性吗?" 为什么,是的,是的! :-)这是另一种编写listOfThings的方法:

Just a final comment. You might have wondered asked yourself "what do you mean flatMap? Isn't that a monad/for-comprehension thingy?" Why, yes, and yes! :-) Here's another way of writing 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 <~ ":",因为它在Scala中使用了filterwithFilter,而Parsers并未实现.但是这里还有另一种写法,它不具有完全相同的语义,但是产生相同的结果:

I'm not doing n ~ what <- number ~ word <~ ":" because that uses filter or withFilter in Scala, which is not implemented by Parsers. But here's even another way of writing it, that doesn't have the exact same semantics, but produce the same results:

def listOfThings   = for {
  n    <- number
  what <- word
  _    <- ":" : Parser[String]
  list <- things(n.toInt)
}  yield new ~(n.toInt, new ~(what, list))

这甚至可能使人们认为,也许单子无处不在" 的说法可能有所帮助. :-)

This might even give one to think that maybe the claim that "monads are everywhere" might have something to it. :-)

这篇关于Scala组合器解析器,什么是&gt;?意思是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆