2011-12-15 112 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