モナドを使用した非正格文法パーサーの設計について助けが必要です。文法構造は次のようになります。
- ヘッダ
- セクション1
- 第2節
- ...
これらの各セクションは欠落している可能性があり、ストリームは任意の場所で終了する可能性があるため、これまでに解析したものを返す必要があります。
State モナドを使用して、パーサーを各セクションのタイプ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)))
このアプローチは実用的ですか?もっと良い解決策があるのだろうか?