我正在尝试使用 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
Run Code Online (Sandbox Code Playgroud)
测试线束:
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
()
Run Code Online (Sandbox Code Playgroud)
错误消息发送器。charsTillString 和 ManyCharsTill 都是相同的
Error in Ln: 6 Col: 4
^
Note: The error occurred at the end of the input stream.
Could not find the string '*/'.
Run Code Online (Sandbox Code Playgroud)
Comment 和 IgnoreU 都是可区分的字符串类型
问题是comment解析器中的组合器没有您想要的优先级/关联性。您可以通过用括号分组来解决此问题:
let comment = (pstring "//" >>. restOfLine true)
<|> (openComment >>. (charsTillString "*/" true System.Int32.MaxValue)) |>> Comment
Run Code Online (Sandbox Code Playgroud)
我发现这通常比复杂的解析器choice更容易阅读:<|>
let comment =
choice [
pstring "//" >>. restOfLine true
openComment >>. (charsTillString "*/" true System.Int32.MaxValue)
] |>> Comment
Run Code Online (Sandbox Code Playgroud)