Vey*_*Vey 4 parsing haskell parsec megaparsec
这些要求来自DOT语言规范,更确切地说,我正在尝试解析[ID]属性,例如,
任何双引号字符串("...")可能包含转义引号(\")1;
以下应该是一个最小的例子.
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Text.Megaparsec
import Text.Megaparsec.Char
import Data.Void
import Data.Char
import Data.Text hiding ( map
, all
, concat
)
type Parser = Parsec Void Text
escape :: Parser String
escape = do
d <- char '\\'
c <- oneOf ['\\', '\"', '0', 'n', 'r', 'v', 't', 'b', 'f']
return [d, c]
nonEscape :: Parser Char
nonEscape = noneOf ['\\', '\"', '\0', '\n', '\r', '\v', '\t', '\b', '\f']
identPQuoted :: Parser String
identPQuoted =
let inner = fmap return (try nonEscape) <|> escape
in do
char '"'
strings <- many inner
char '"'
return $ concat strings
identP :: Parser Text
identP = identPQuoted >>= return . pack
main = parseTest identP "\"foo \"bar\""
Run Code Online (Sandbox Code Playgroud)
"foo "即使我想要,上面的代码在第二次失败时返回foo "bar
我不明白为什么.我认为这megaparsec会反复应用,inner直到它解析决赛".但它只是重复应用nonEscape解析器并且第一次失败并且它使用escape,然后它似乎跳过内部字符串的其余部分并且继续移动到最终引号.
您的输入文本是"foo "bar",不包含任何转义引号.它被解析为完整的ID "foo "(后跟bar",被忽略).
如果要确保解析器消耗所有可用输入,可以使用
parseTest (identP <* eof) "..."
Run Code Online (Sandbox Code Playgroud)
如果你想向解析器提供带有转义引用的ID,就像这样......
"foo \"bar"
Run Code Online (Sandbox Code Playgroud)
...然后你需要转义所有特殊字符以将它们嵌入Haskell源代码中:
main = parseTest identP "\"foo \\\"bar\""
Run Code Online (Sandbox Code Playgroud)
\"代表文字"并\\代表文字\.
| 归档时间: |
|
| 查看次数: |
222 次 |
| 最近记录: |