作为尝试编写JSON Parser的一部分,我正在解析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
只消耗每个令牌,直到到达String的末尾。
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解决它有一个微弱的想法,但我不确定它们是否是必需的。
答案 0 :(得分:1)
notEndOfString
匹配并消费文本中的任何字符,包括"
直到结尾,因此它贪婪地使用所有字符,从不切换到{{ 1}}解析器。您需要匹配不是引用的引号内的任何字符,这意味着您需要否定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))
。