为什么我的 FParsec 解析器无法识别块注释?

Why is my FParsec parser failing to recognize a block comment?

提问人:Jerry 提问时间:6/1/2023 更新时间:6/2/2023 访问量:42

问:

我正在尝试使用 FParsec 解析 C 样式注释。不知道为什么会失败:

我的解析器代码:

let openComment : Parser<_,unit>  = pstring "/*"
let closeComment : Parser<_,unit> = pstring "*/"
let comment = pstring "//" >>. restOfLine true
                <|> openComment >>. (charsTillString "*/" true System.Int32.MaxValue) |>> Comment
                //<|> openComment >>. manyCharsTill anyChar closeComment |>> Comment
let spaceComments = many ((spaces1 |>> IgnoreU) <|> comment)
let str s  = spaceComments >>. pstring s .>> spaceComments

测试线束:

let testStr = @"
// test comment
/* a block comment
   */
   x  // another comment
   "
match run (str "x") testStr with
| Success(result, _, _)   -> printfn "Success: %A" result
| Failure(errorMsg, _, _) -> assert false
()

错误消息器。charsTillString 和 manyCharsTill 都是一样的

Error in Ln: 6 Col: 4
   
   ^
Note: The error occurred at the end of the input stream.
Could not find the string '*/'.

Comment 和 IgnoreU 都是一种区分类型的字符串

f# fparsec

评论


答:

5赞 Brian Berns 6/2/2023 #1

问题在于解析器中的组合器没有所需的优先级/关联性。您可以通过使用 parens 分组来解决此问题:comment

let comment = (pstring "//" >>. restOfLine true)
                <|> (openComment >>. (charsTillString "*/" true System.Int32.MaxValue)) |>> Comment

我发现这通常比复杂的解析器更容易阅读:choice<|>

let comment =
    choice [
        pstring "//" >>. restOfLine true
        openComment >>. (charsTillString "*/" true System.Int32.MaxValue)
    ] |>> Comment