Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing Scala中用monad设计非严格语法分析器_Parsing_Scala_Monads_Scalaz - Fatal编程技术网

Parsing Scala中用monad设计非严格语法分析器

Parsing Scala中用monad设计非严格语法分析器,parsing,scala,monads,scalaz,Parsing,Scala,Monads,Scalaz,我需要帮助设计非严格语法解析器与单子。语法结构如下所示: 标题 第一节 第2节 这些部分中的每一部分都可能丢失,流可能在任何地方结束,所以,我需要返回到目前为止我已经解析的内容 我成功地使用状态monad为每个部分将解析器构造成s=>(a,s)类型的函数。状态s保存了其余的输入和当前捕获的数据。在类似Scala的伪代码中: val parser = for { _ <- readHeader _ <- readSection1 _ <- readSection

我需要帮助设计非严格语法解析器与单子。语法结构如下所示:

  • 标题
  • 第一节
  • 第2节
这些部分中的每一部分都可能丢失,流可能在任何地方结束,所以,我需要返回到目前为止我已经解析的内容

我成功地使用状态monad为每个部分将解析器构造成s=>(a,s)类型的函数。状态s保存了其余的输入和当前捕获的数据。在类似Scala的伪代码中:

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

parser(input)

这种方法可行吗?我想知道有没有更好的解决方案?

看起来Iteratee也可以满足我的需要。
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)))