我在F#和FParsec这么新,我甚至不想通过展示我到目前为止所做的事来让自己难堪。
在FParsec示例中,AST中的每个类型(我看到)都是单个值,列表或元组的类型缩写。
如果我有一个复杂的类型,例如解析的函数名及其参数,该怎么办?
因此,f(a, b, c)
将被解析为PFunction
类型的对象,该对象具有字符串成员Name
和PParameter
列表成员Parameters
。如何从可以将f(a, b, c)
和|>>
匹配的解析器转到PFunction
?
我似乎能够做到的就是创建复合解析器,但不要把它变成任何东西。计算器示例是相似的,如果它使AST包含类似Term的类型,但在我看来它似乎是一个解释器而不是解析器,所以没有AST。此外,Term可能只是其他类型缩写组件的元组。
谢谢!
答案 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]