FParsec 中的前向引用问题

Problems with Forward References in FParsec

提问人:bookofproofs 提问时间:8/21/2023 最后编辑:bookofproofs 更新时间:8/22/2023 访问量:59

问:

我正在尝试使用 FParsec 编写一个解析器来解析嵌套的布尔表达式,例如:

false
true
and(false,true,true,true,true)
or(true,true)
and(or(false,true),and(true,true,true,true))

因为我的语法涉及相互递归的定义,所以我在这篇文章中读到我需要createParserForwardedToRef

我的问题是,一旦我这样做,F#编译器就会生成错误Error FS0037: Duplicate definition of value 'predicateListRef'

这是重现错误的工作示例:

open FParsec

type Predicate =
    | True
    | False
    | And of Predicate list
    | Or of Predicate list

let leftParen: Parser<_, unit> = skipChar '('
let rightParen: Parser<_, unit> = skipChar ')'
let comma: Parser<_, unit> = skipChar ','
let keywordTrue: Parser<_,unit> = skipString "true" >>% Predicate.True  
let keywordFalse: Parser<_,unit> = skipString "false" >>% Predicate.False  
let keywordAnd: Parser<_,unit> = skipString "and"
let keywordOr: Parser<_,unit> = skipString "or"

////// resolving recursive parsers
let predicateList, predicateListRef = createParserForwardedToRef()

let primePredicate = choice [
    keywordTrue
    keywordFalse
]

let conjunction = (keywordAnd >>. leftParen >>. predicateList) .>> rightParen |>> Predicate.And
let disjunction = (keywordOr >>. leftParen >>. predicateList) .>> rightParen |>> Predicate.Or

let compoundPredicate = choice [
    conjunction
    disjunction
]

let predicate = choice [
    primePredicate
    compoundPredicate
]

let predicateListRef = sepBy1 predicate comma  // the error occurs at this line

我做错了什么(对不起,我不熟悉 FParsec、F# 和函数式编程)?

参考 f# 向前 fparsec

评论


答:

1赞 Martin521 8/22/2023 #1

你的最后一行应该是

predicateListRef.Value <- sepBy1 predicate comma

您已在代码中将 predicateListRef 进一步绑定到引用单元格,现在必须设置其值。

评论

0赞 bookofproofs 8/23/2023
谢谢。同时,我发现了似乎也是另一种解决方案“predicateListRef := sepBy1 谓词逗号”。它在 F# / FParsec 中是等效的还是其他的?
0赞 Martin521 8/24/2023
是的,这仍然有效,但已被弃用