使用FParsec解析嵌套布尔表达式时遇前向引用重复定义错误
解决FParsec互递归解析器的重复定义错误
你尝试用FParsec解析嵌套布尔表达式时遇到了Error FS0037: Duplicate definition of value 'predicateListRef'错误,问题出在重复定义了同一个变量,以下是具体分析和修正方案:
错误原因
createParserForwardedToRef()已经返回了元组(predicateList, predicateListRef),其中predicateListRef是一个可修改的引用,用于后续绑定实际的解析逻辑。但你最后一行又用let predicateListRef重新定义了同名变量,违反了F#的变量定义规则,导致重复定义错误。
正确的做法是给引用赋值,而非重新定义变量,F#中对引用赋值需要使用:=操作符。
修正后的完整代码
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" ////// 处理递归解析器 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 ] // 给引用赋值,而非重新定义变量 predicateListRef := sepBy1 predicate comma
额外说明
createParserForwardedToRef的作用是创建一个“占位”解析器和对应引用,用来处理互递归的语法结构(比如这里predicate依赖predicateList,而predicateList又依赖predicate)- 最后通过
predicateListRef := ...把实际的列表解析逻辑绑定到之前的占位引用上,递归关系就能正确建立
内容的提问来源于stack exchange,提问作者bookofproofs
相关产品推荐
相关产品推荐

