为 JSON 字符串编写解析器
Writing Parser for JSON String
作为尝试编写 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
以实际工作的提示。
注意 - 我对如何使用 Monad 解决它有一个模糊的想法,但我不确定是否需要它们。
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 <$> inside '"' '"'
.
作为尝试编写 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
以实际工作的提示。
注意 - 我对如何使用 Monad 解决它有一个模糊的想法,但我不确定是否需要它们。
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 <$> inside '"' '"'
.