解析为复杂类型

时间:2011-12-15 21:13:40

标签: f# fparsec

我在F#和FParsec这么新,我甚至不想通过展示我到目前为止所做的事来让自己难堪。

在FParsec示例中,AST中的每个类型(我看到)都是单个值,列表或元组的类型缩写。

如果我有一个复杂的类型,例如解析的函数名及其参数,该怎么办?

因此,f(a, b, c)将被解析为PFunction类型的对象,该对象具有字符串成员NamePParameter列表成员Parameters。如何从可以将f(a, b, c)|>>匹配的解析器转到PFunction

我似乎能够做到的就是创建复合解析器,但不要把它变成任何东西。计算器示例是相似的,如果它使AST包含类似Term的类型,但在我看来它似乎是一个解释器而不是解析器,所以没有AST。此外,Term可能只是其他类型缩写组件的元组。

谢谢!

3 个答案:

答案 0 :(得分:3)

我认为这就是你要找的东西:

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

答案 1 :(得分:0)

这是一个完全做作的但是我认为它看起来如下所示,使用pipe2而不是|&gt;&gt;

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))

答案 2 :(得分:0)

正如丹尼尔所说,功能性答案将是使用受歧视的联盟。 FParsec还有一个可以像状态monad一样使用的UserState,所以如果你真的想直接解析为复杂类型,你可以使用它。 [1]

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