我最近一直在使用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