我刚刚开始学习解析,并且我在Haskell中编写了this simple parser(使用parsec)来读取JSON并为其构造一个简单的树。我在RFC 4627中使用语法。
但是,当我尝试解析字符串{"x":1 }
时,我得到了输出:
解析错误(第1行,第8列):
意外的“}”
期待空格字符或“,”
仅当我在右大括号(])或mustachio(})前有空格时,才出现这种情况。
我做错了什么?如果我在结束符号前避免使用空格,则效果很好。
最佳答案
Parsec不会自动回绕和回溯。当您编写sepBy member valueSeparator
时,valueSeparator
会占用空白,因此解析器将按如下方式解析您的值:
{"x":1 }
[------- object
% beginObject
[-] name
% nameSeparator
% jvalue
[- valueSeparator
X In valueSeparator: unexpected "}"
Legend:
[--] full match
% full char match
[-- incomplete match
X incomplete char match
当
valueSeparator
失败时,Parsec将不会返回并尝试不同的解析组合,因为valueSeparator
中已经有一个字符匹配。您有两种选择可以解决您的问题:
由于在JSON中空格是微不足道的,因此请始终在有效令牌之后而不是之前消耗空格。因此,
tok
仅应在char后面占用空白,因此其定义为tok c = char c *> ws
(来自(*>)
的Control.Applicative
);将相同的规则应用于所有其他解析器。由于您以这种方式输入“错误的解析器”之后再也不会占用空白空间,因此您最终不必回溯。在Parsec中使用回溯功能,方法是在可能消耗多个字符的解析器之前添加
try
,如果解析器失败,则应回退其输入。编辑:更新了ASCII图形,使其更具意义。