如何实现单子语法分析?

时间:2019-06-09 20:31:44

标签: parsing monads

我坚持了解Monad的工作原理。

1 个答案:

答案 0 :(得分:1)

通常,当我们说“ monadic parsing”时,是指将Parser变成monad。我们写

class Parser[+A] { ... }

Parser[A]接受输入并返回已解析的A,或者它失败,或者可能还有一些输入剩余。让我们保持非常简单:Parser[A]取一个List[Char],而Option则返回一个A和其余的List[Char]

case class Parser[+A](parse: List[Char] => Option[(A, List[Char])]) {
  def accepts(l: List[Char]): Boolean
    = parse(l).map(_._2.isEmpty).getOrElse(false)
  // do not bother with the List('#') stuff
}

您可以使用组合器来构建Parsera.flatMap(b)是与a后跟b

匹配的解析器
// case class Parser[+A](...) {
  def flatMap[B](f: A => Parser[B]): Parser[B] = Parser { input =>
    parse(input).flatMap { case (x, midput) => f(x).parse(midput) }
  }
// }

Parser.unit(x)在不消耗任何输入的情况下返回x,这就是Monad很重要的原因。您还应该具有map,它可以更改返回的值而不更改匹配的值。您还需要一个组合器来进行交替。我将这些留给您实施。

object Parser {
    def unit[T](x: T): Parser[T] = ???
}
// case class Parser[+A](...) {
    def map[B](f: A => B): Parser[B] = ???

    // left-biased greedy: if this parser succeeds (produces Some) then
    // that parser is never tried (i.e. no backtracking)
    // replacing Option with Seq is the easiest way to get backtracking
    // but we don't need it to define S
    def orElse[B](that: Parser[B]): Parser[Either[A, B]] = ???
// }

您还希望一些基本的Parser从中构建更复杂的Parser.char(x)x与单个字符// object Parser { def char(c: Char): Parser[Unit] = Parser { case x :: rest if c == x => Some(((), rest)) case _ => None } // } 匹配,并且没有返回任何有用的信息。

S

然后,您可以非常自然地定义Int。您甚至可以使解析器返回a /匹配的b / lazy val S: Parser[Int] = (for { _ <- Parser.char('a') i <- S _ <- Parser.char('b') } yield (i + 1)).orElse(Parser.unit(0)).map(_.merge) // i.e lazy val S: Parser[Int] = Parser.char('a').flatMap { _ => S.flatMap { i => Parser.char('b').map { _ => i + 1 } } }.orElse(Parser.unit(0)).map(_.merge) S.accepts("".toList) // true S.accepts("aaabbb".toList) // true S.accepts("aaa".toList) // false S.accepts("bbbaaa".toList) // false 数量的一个List[Char]

S

您不必在onclick的定义中四处移动Select,因为我们编写的组合器为您做到了这一点,仅留下了语法本身的逻辑。