我正在尝试为JSON字符串编写解析器。
根据我的解析器,一个有效的示例是:"\"foobar\""
或"\"foo\"bar\""
。
这是我尝试过的,但它没有终止:
parseEscapedQuotes :: Parser String
parseEscapedQuotes = Parser f
where
f ('"':xs) = Just ("\"", xs)
f _ = Nothing
parseStringJValue :: Parser JValue
parseStringJValue = (\x -> S (concat x)) <$>
((char '"') *>
(zeroOrMore (alt parseEscapedQuotes (oneOrMore (notChar '"'))))
<* (char '"'))
我的理由是,我可以重复使用转义引号"\""
或不等于"
的字符。
但它没有像我预期的那样工作:
ghci> runParser parseStringJValue "\"foobar\""
Nothing
答案 0 :(得分:1)
我不知道你正在使用什么解析器组合器库,但这是一个使用Parsec的工作示例。我使用monadic风格使它更清晰,但它很容易转化为应用风格。
import Text.Parsec
import Text.Parsec.String
jchar :: Parser Char
jchar = escaped <|> anyChar
escaped :: Parser Char
escaped = do
char '\\'
c <- oneOf ['"', '\\', 'r', 't' ] -- etc.
return $ case c of
'r' -> '\r'
't' -> '\t'
_ -> c
jstringLiteral :: Parser String
jstringLiteral = do
char '"'
cs <- manyTill jchar (char '"')
return cs
test1 = parse jstringLiteral "" "\"This is a test\""
test2 = parse jstringLiteral "" "\"This is an embedded quote: \\\" after quote\""
test3 = parse jstringLiteral "" "\"Embedded return: \\r\""
注意将解析器输入表示为Haskell字符串文字所需的额外反斜杠级别。从文件中读取输入将使创建解析器输入更加方便。
manyTill
组合子的定义是:
manyTill p end = scan
where
scan = do{ end; return [] }
<|>
do{ x <- p; xs <- scan; return (x:xs) }
这可能会帮助您找出定义无效的原因。