在Scala中使用monad设计非严格的语法分析器

时间:2013-09-27 14:22:32

标签: parsing scala monads scalaz

我需要帮助设计monad的非严格语法分析器。语法结构如下:

  • SECTION1
  • 第2节
  • ...

这些部分中的每一部分都可能丢失,流可能会在任何地方结束,因此,我需要返回到目前为止我已解析的部分。

我成功使用State monad将我的解析器构建为 s =>类型的函数(a,s)每个部分。状态 s 保留输入的其余部分,此时抓取数据。在类似Scala的伪代码中:

val parser = for {
  _ <- readHeader
  _ <- readSection1
  _ <- readSection2
  - <- ...
} yield ()

parser(input)

现在,我还希望实现提前终止,以便解析器不会尝试读取有关EOF的更多输入。例如,如果在阅读标题后达到EOF,我想返回并且不要进一步阅读。

这是我到目前为止所得到的:

import scalaz._
import Scalaz._

object Playground extends App {
  type Stream = String
  type Mined = List[String]
  type ParserState = (Stream, Mined)

  type MyEither[+T] = Either[ParserState, T]

  val s1 = StateT[MyEither, ParserState, Unit] { s =>
    Right((("input at s1", add(s, "header")), ()))
  }
  val s2 = StateT[MyEither, ParserState, Unit] { s =>
    Right((("input at s2", add(s, "section1")), ()))
  }
  val s3 = StateT[MyEither, ParserState, Unit] { s =>
    Left(s)
  }
  val s4 = StateT[MyEither, ParserState, Unit] { s =>
    Right((("input at s4", add(s, "section3")), ()))
  }

  def add(s: ParserState, mined: String): Mined = mined :: s._2

  val parser =
    for {
      _ <- s1
      _ <- s2
      _ <- s3
      _ <- s4
    } yield ()
  println(parser.run(("input", List())))
}

打印:

Left((input at s2,List(section1, header)))

这种方法是否实用?我想知道有更好的解决方案吗?

0 个答案:

没有答案