我最近一直在使用FParsec,并且发现缺乏通用解析器对我来说是一个主要的停止点。我的这个小库的目标是简单以及对通用输入的支持。你能想到任何可以改善这一点的补充,或者是特别糟糕的吗?这是解析器组合器库的合理基础吗?
open LazyList type State<'a, 'b> (input:LazyList<'a>, data:'b) = member this.Input = input member this.Data = data type Result<'a, 'b, 'c> = | Success of 'c * State<'a, 'b> | Failure of string * State<'a, 'b> type Parser<'a,'b, 'c> = State<'a, 'b> -> Result<'a, 'b, 'c> let (>>=) left right state = match left state with | Success (result, state) -> (right result) state | Failure (message, _) -> Result<'a, 'b, 'd>.Failure (message, state) let (<|>) left right state = match left state with | Success (_, _) as result -> result | Failure (_, _) -> right state let (|>>) parser transform state = match parser state with | Success (result, state) -> Success (transform result, state) | Failure (message, _) -> Failure (message, state) let (<?>) parser errorMessage state = match parser state with | Success (_, _) as result -> result | Failure (_, _) -> Failure (errorMessage, state) type ParseMonad() = member this.Bind (f, g) = f >>= g member this.Return x s = Success(x, s) member this.Zero() s = Failure("", s) member this.Delay (f:unit -> Parser<_,_,_>) = f() let parse = ParseMonad()
回溯
令人惊讶的是并没有采取太多的代码来实现你的描述。这是有点草率,但似乎工作得很好。
let (>>=) left right state =
seq {
for res in left state do
match res with
| Success(v, s) ->
let v =
right v s
|> List.tryFind (
fun res ->
match res with
| Success (_, _) -> true
| _ -> false
)
match v with
| Some v -> yield v
| None ->()
} |> Seq.toList
let (<|>) left right state =
left state @ right state
回溯第2部分
开关周围的代码,以使用惰性列表和尾部调用优化递归。
let (>>=) left right state =
let rec readRight lst =
match lst with
| Cons (x, xs) ->
match x with
| Success (r, s) as q -> LazyList.ofList [q]
| Failure (m, s) -> readRight xs
| Nil -> LazyList.empty<Result<'a, 'b, 'd>>
let rec readLeft lst =
match lst with
| Cons (x, xs) ->
match x with
| Success (r, s) ->
match readRight (right r s) with
| Cons (x, xs) ->
match x with
| Success (r, s) as q -> LazyList.ofList [q]
| Failure (m, s) -> readRight xs
| Nil -> readLeft xs
| Failure (m, s) -> readLeft xs
| Nil -> LazyList.empty<Result<'a, 'b, 'd>>
readLeft (left state)
let (<|>) (left:Parser<'a, 'b, 'c>) (right:Parser<'a, 'b, 'c>) state =
LazyList.delayed (fun() -> left state)
|> LazyList.append
<| LazyList.delayed (fun() -> right state)
说不上来,如果有什么有用的东西,但也可能http://lorgonblog.wordpress.com/2008/02/看16/monadic-parser-combinators-in-f/ – Brian 2010-11-11 07:08:47
@Brian - 说实话,post是我开始解析器组合体学习体验的地方。 :) – ChaosPandion 2010-11-11 14:40:15