【问题标题】:Writing Parser for JSON String为 JSON 字符串编写解析器
【发布时间】:2015-04-16 14:42:41
【问题描述】:

作为尝试编写 JSON 解析器的一部分,我正在解析 JSON 字符串值。

鉴于 Brent Yorgey 教授的 Haskell course 的以下定义:

-- A parser for a value of type a is a function which takes a String
-- represnting the input to be parsed, and succeeds or fails; if it
-- succeeds, it returns the parsed value along with the remainder of
-- the input.
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }

我遇到了麻烦,因为据我了解,我的第二个解析器 zeroOrMore notEndOfString 只是消耗每个 token 直到到达字符串的末尾。

data JValue = S String | ...

parseStringJValue :: Parser JValue
parseStringJValue = S <$> ((char '"') *> (zeroOrMore notEndOfString) <* (char '"'))

notEndOfString :: Parser Char
notEndOfString = Parser f
  where 
    f []     = Nothing
    f (x:xs) = Just (x, xs)

使用这种应用方法,请给我一个提示,以修改我上面的parseStringJValue 以实际工作。

注意 - 我对如何使用 Monads 解决它有一个模糊的想法,但我不确定是否需要它们。

【问题讨论】:

  • 提示:notEndOfString 中的字符串是您解析的结果,而不是要解析的输入。
  • 你可能想要zeroOrMore notEndOfStringOrQuote。例如,在秒差距中,我可能只会写 many (noneOf "\"")

标签: parsing haskell monads


【解决方案1】:

notEndOfString 正在匹配并消耗文本中的任何字符,包括" 直到最后,因此它会贪婪地消耗所有字符并且永远不会移交给char '"' 解析器。您需要匹配引号内不是引号的任何字符,这意味着您需要对char 取反。

如果你有char,那么大概是你从satisfy构建的,这意味着你也可以定义notChar

notChar c = satisfy (/= c)

(注意,顺便说一下,notEndOfString 就是 satisfy id)。否则,你可以像char一样写。

然后您可以通过构建一些其他有用的组合器来定义字符串解析器:

bracket l r p = l *> p <* r
quotes = bracket (char '"') (char '"')

parseStringJValue = S <$> quotes (zeroOrMore (notChar '"'))

请注意,这不会处理引号内的转义 ("\"")。


编辑:为了强制执行上面隐含的不变量,最好定义

inside l r = bracket (char l) (char r) (zeroOrMore (notChar r))

然后parseStringJValue = S &lt;$&gt; inside '"' '"'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多