"Exposing the stream" is not really a "trick". You're just directly using the "lower-level" FParsec API, which sometimes can be the most elegant or readable way to implement a parser.

One issue with your code is that your UserState type is mutable. If you mutate the user state value (instead of replacing the user state value with a new value) FParsec won't be able to restore old values when a parser backtracks. So you might want to use a UserState type like the following instead:

1
2
3
4
type UserState = {
    Verb: IVerb option
    Target: ITarget option  
}

If you wanted to use the higher-level primitives for pverb, you could do something like

1
2
3
4
5
6
7
let pverb =
    verb |> If (fun lexeme -> lexeme.Count > 0)
    >>= fun lexeme ->
            if lexeme.IsMatched then
                updateUserState (fun us ->  {us with Verb = Some lexeme}) >>% Expr.Verb lexeme
            else
                preturn (Expr.Verbs lexeme)

Or you could directly access the stream and user state like here:

1
2
3
4
5
6
7
8
let pverb =
    verb |> If (fun lexeme -> lexeme.Count > 0)
    >>= fun lexeme stream ->
            if lexeme.IsMatched then
                 stream.UserState <- {stream.UserState with Verb = Some lexeme}
                 Reply(Expr.Verb lexeme)
             else
                 Reply(Expr.Verbs lexeme)
By on 8/26/2011 12:20 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper