2

我对 F# 和 FParsec 还很陌生,我什至不想通过展示我到目前为止所拥有的东西来让自己难堪。

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

如果我有一个复杂的类型,它应该包含一个解析过的函数名和它的参数怎么办?

因此,f(a, b, c)将被解析为PFunction具有字符串成员NamePParameter列表成员的类型的对象Parameters。我怎样才能从一个可以匹配的解析器f(a, b, c)变成|>>一个PFunction

到目前为止,我似乎能做的就是创建复合解析器,但不把它变成任何东西。如果 Calculator 示例包含类似 Term 的类型的 AST,但在我看来,它似乎是解释器而不是解析器,因此没有 AST。此外,术语可能只是其他类型缩写组件的元组。

谢谢!

4

3 回答 3

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
于 2011-12-16T15:19:24.220 回答
0

这是一个完全做作的,但我认为它如下所示,使用 pipe2 而不是 |>>

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))
于 2011-12-16T14:28:44.197 回答
0

正如丹尼尔所提到的,功能性的答案是使用有区别的联合。FParsec 还有一个 UserState 可以像状态单子一样使用,所以如果你真的想直接解析成复杂类型,你可以使用它。[1]

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

于 2011-12-16T16:20:40.203 回答