2011-12-15 81 views
2

我对F#和FParsec很新颖,我甚至不想让自己难堪,通过展示我到目前为止已经得到的东西。解析成一个复杂的类型

在FParsec实施例中,在每一个AST的类型(我看到)是用于单值,列表或元组类型的缩写。

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

所以,f(a, b, c)将被解析以PFunction类型的对象,其具有绳部件NamePParameter列表成员Parameters。我怎样才能从一个解析器,它可以匹配f(a, b, c)|>>它到PFunction

所有我似乎能够做到目前为止是创建复合解析器,但没有把它变成任何东西。计算器的例子是类似的,如果它做了一个AST,包括像Term这样的类型,但是在我看来,它似乎是一个解释器而不是解析器,所以没有AST。此外,Term可能只是其他类型缩写组件的元组。

谢谢!

+1

我没有用过FParsec,但在fsyacc您通常其建模为区分联合。例如,`输入Func = string *参数列表` – Daniel 2011-12-15 21:22:07

回答

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

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

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