Applicative parser example in Scala

天涯浪子 提交于 2019-12-20 03:24:05

问题


This is a new version of my previous question

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)

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')

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.

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:

  • How to define <*> for parsers ? (not with flatMap) ?
  • How to translate this example to Scala (with scalaz) ?

回答1:


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

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

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)
  }

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

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.



来源:https://stackoverflow.com/questions/30685920/applicative-parser-example-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!