关于haskell:Parsec中解析转义的分隔符

Parsing escaped separation character in Parsec

我刚开始使用 parsec,我正在尝试做一些简单的事情。

我想分隔键值字符串,如本解析教程中所示。

例如,字符串 FirstN=Tom&LastN=Brady 应该给出 [["FirstN","Tom"],["LastN","Brady"]].

这很容易,但我也想允许字符串中的 '=' 字符被转义。例如,字符串 Equation=1+1\\\\=2 应该给出 [["Equation","1+1\\\\=2"]] (或 [["Equation","1+1=2"]] 但我还没有决定哪个最好)。

对于简单的例子,解析代码如下:

1
2
3
4
5
kvParser :: String -> Either ParseError [[String]]
kvParser input = parse kvString"Error text?" input

kvString = sepBy kvVal (char '&')
kvVal = sepBy (many (noneOf"=&")) (char '=')

为了允许转义 = 我想我需要修改 (char '=') 值,但我不确定如何。有人有什么建议吗?

谢谢

编辑:最终的工作解析器是

1
2
3
4
5
6
kvParser :: String -> Either ParseError [[String]]
kvParser input = parse kvString"Error text?" input

kvString = sepBy kvVal (char '&')
kvVal = sepBy (many kvChar) (char '=')
kvChar = noneOf"\\\\&=" <|> (char '\\\' >> anyChar)

我还使用 try 组合器完成了以下工作。

1
2
3
4
5
6
kvParser :: String -> Either ParseError [[String]]
kvParser input = parse kvString"Error text?" input

kvString = sepBy kvVal (char '&')
kvVal = sepBy (many kvChar) (char '=')
kvChar = try (string"\\\\=">> return '=') <|> noneOf"&="

分隔符没问题;您想要接受 \\= 作为键或值的一部分。而不是

1
noneOf"=&"

你可以试试

1
(noneOf"\\\\&" <|> (char '\\\' >> anyChar))

也就是说,noneOf 将接受任何不是反斜杠的内容,否则右侧的解析器将接受(并跳过)反斜杠并保持字符跟随它。这应该可以防止它被检测为分隔符。