JSON字符串的解析器

时间:2015-02-18 03:39:49

标签: haskell

我正在尝试为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

1 个答案:

答案 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) }

这可能会帮助您找出定义无效的原因。