문제

I'm so new at F# and FParsec, I don't even want to embarrass myself by showing what I've got so far.

In the FParsec examples, every type in the ASTs (that I see) are type abbreviations for single values, lists, or tuples.

What if I have a complex type which is supposed to hold, say, a parsed function name and its parameters?

So, f(a, b, c) would be parsed to an object of type PFunction which has a string member Name and a PParameter list member Parameters. How can I go from a parser which can match f(a, b, c) and |>> it into a PFunction?

All I seem to be able to do so far is create the composite parser, but not turn it into anything. The Calculator example would be similar if it made an AST including a type like Term but instead it seems to me to be an interpreter rather than a parser, so there is no AST. Besides, Term would probably just be a tuple of other type abbreviated components.

Thanks!

도움이 되었습니까?

해결책

I think this is what you're looking for:

let pIdentifier o =
    let isIdentifierFirstChar c = isLetter c || c = '_'
    let isIdentifierChar c = isLetter c || isDigit c || c = '_'
    many1Satisfy2L isIdentifierFirstChar isIdentifierChar "identifier" <| o

let pParameterList p = 
    spaces >>. 
        pchar '(' >>. spaces >>. sepBy (spaces >>. p .>> spaces) (pchar ',') 
            .>> spaces .>> pchar ')'

type FunctionCall(Name: string, Parameters: string list) =
    member this.Name = Name
    member this.Parameters = Parameters

let pFunctionCall o= 
    pipe2 (pIdentifier) (pParameterList pIdentifier) (fun name parameters -> FunctionCall(name, parameters)) <|o

다른 팁

This is a completely contrived but here's what I think it would look like the following, using pipe2 instead of |>>

type FunctionCall(Name: string, Parameters: string list) =
    member this.Name = Name
    member this.Parameters = Parameters

let pFunctionCall = 
    pipe2 (pIdentifier) (pstring "(" >>. pParameterList .>> pstring ")") (fun name parameters -> FunctionCall(name, parameters))

The functional answer would be to use a discriminated union, as Daniel mentioned. FParsec also has a UserState that can be used like a state monad, so if you really want to parse directly into a complex type, you can use that. [1]

[1] http://cs.hubfs.net/topic/None/60071

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top