英文:
Why is my FParsec parser failing to recognize a block comment?
问题
我正在尝试使用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都是字符串的枚举类型。
英文:
I'm trying to parse C style comments using FParsec. Not sure why this is failing:
My parser code:
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
Test Harness:
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
()
Error messager. It is the same for both charsTillString and manyCharsTill
Error in Ln: 6 Col: 4
^
Note: The error occurred at the end of the input stream.
Could not find the string '*/'.
Comment and IgnoreU are both a discrimated type of string
答案1
得分: 5
问题在于您的 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
英文:
The problem is that the combinators in your comment
parser don't have the precedence/associativity that you want. You can fix this by grouping with parens:
let comment = (pstring "//" >>. restOfLine true)
<|> (openComment >>. (charsTillString "*/" true System.Int32.MaxValue)) |>> Comment
I find that choice
is often easier to read than <|>
for complex parsers:
let comment =
choice [
pstring "//" >>. restOfLine true
openComment >>. (charsTillString "*/" true System.Int32.MaxValue)
] |>> Comment
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论