Scala中的应用解析器示例 [英] Applicative parser example in Scala

查看:128
本文介绍了Scala中的应用解析器示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我以前的问题

我们可以将解析器定义为type Parser[A] = String => List[(A, String)].解析器接受输入字符串,并产生一对序列.每对都包含解析结果和输入的未使用部分. (请参见此文章中的更多内容)

We can define a parser as type Parser[A] = String => List[(A, String)]. The parser takes an input string and yields a sequence of pairs. Each pair consists of the parsing result and unconsumed part of the input. (See more in this article)

现在我们可以定义一个解析器pa,如果第一个输入字符为a,则解析器将成功,否则将失败.

Now we can define a parser pa, which succeeds if the 1st input character is a and fails otherwise.

def symbol(c: Char): Parser[Char] = {s: String => 
  s.toList match { case x :: xs if x == c => List((x, xs.mkString)); case _ => Nil } 
}

val pa = symbol('a')

我们还可以为Parser[A]定义mapflatMap,然后使用它们来构成解析器:

We can also define map and flatMap for Parser[A] and then use them to compose parsers:

val pa = symbol('a')
val pb = symbol('b')
val pab: Parser[(Char, Char)] = for (a <- pa; b <- pa) yield (a, b)

尽管结果我们也可以用<*>组成解析器.

It is turned out though that we can compose parsers with <*> too.

应用解析器的示例.假设我们要识别嵌套的括号并计算最大嵌套深度.语法S->(S)S | epsilon描述了这种结构,它直接反映在解析器中.

An example of an applicative parser. Suppose we want to recognise nested parentheses and compute the maximum nesting depth. The grammar S -> (S)S | epsilon describes this structure, which is directly reflected in the parser.

pS = (max . (+1)) <$ pSym '(' <*> pS <* pSym ')' <|> pure 0

不幸的是,我无法理解这个例子.所以我的问题是:

Unfortunately I can't get my head around this example. So my questions are:

  • 如何为解析器定义<*>? (不适用于flatMap)?
  • 如何将此示例转换为Scala(使用scalaz)?
  • How to define <*> for parsers ? (not with flatMap) ?
  • How to translate this example to Scala (with scalaz) ?

推荐答案

<*>(可怕的名字)显然具有以下签名:

<*> (terrible name) apparently has this signature:

<*>[B](f: F[(A) ⇒ B]): F[B]

因此,让我们逐一介绍类型,考虑解析器应该做什么-借助List已经实现flatMap的事实的帮助:

So let's just chase the types through, thinking about what a parser should do - helped by the fact that List already implements flatMap:

def <*>[A, B](fa: Parser[A], fab: Parser[(A) => B]) =
  new Parser[B] {
    def apply(s: String) =
      for {
        (a, rem1) ← fa(s)
        (ab, rem2) ← fab(rem1)
      } yield (ab(a), rem2)
  }

这似乎是一个明智的实现-首先解析a,然后从其余部分解析ab,然后得到结果.

That looks like a sensible implementation - parse a first, then parse ab from the remainder, and then we have our result.

该示例对我来说太象征性了,我不知道Haskell-如果您可以找到<$<|>的文档,那么我将继续.

That example is too symbolic for me and I don't know Haskell - if you can find documentation for the <$ and <|> then I'll give it a go.

这篇关于Scala中的应用解析器示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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