我已经在代码found here上盯了很久。这是Douglas Crockfords JSON解析函数(称为递归下降解析器)。任何人都可以详细说明这个解析器的机制吗?我真的无法理解它。
答案 0 :(得分:9)
逻辑上,您可以从第311行开始的实际解析函数开始(为清晰起见,省略了接收器部分)。
function (source, reviver) {
var result;
text = source;
at = 0;
ch = ' ';
result = value();
white();
if (ch) {
error("Syntax error");
}
return result;
}
使用源文本初始化函数全局变量text
,将位置at
与位置和当前字符ch
一起初始化为空格。之后,它通过调用函数value
解析一个值。
每个要解析的对象都封装在一个函数本身中(在上面的例子中是值对象)。其中有几个:number
,string
,white
,...)。每个人基本上都以相同的方式工作。首先,我们将white
作为基本示例:
white = function () {
// Skip whitespace.
while (ch && ch <= ' ') {
next();
}
}
请注意,ch
constains始终是当前字符。此变量仅由next
更新,后者读入下一个变量。这可以在white
内看到,其中每个空格都是通过调用next
来吃掉的。因此,在调用此函数后,第一个非空格字符将位于变量ch
中。
让我们来寻找一个更复杂的例子value
:
value = function () {
// Parse a JSON value. It could be an object, an array, a string, a number,
// or a word.
white();
switch (ch) {
case '{':
return object();
case '[':
return array();
case '"':
return string();
case '-':
return number();
default:
return ch >= '0' && ch <= '9' ? number() : word();
}
};
它首先通过调用white
来解析空格。请注意,ch
现在包含要解析的当前字符。如果它是'{'
我们现在将接下来的json对象并调用相应的函数object
。如果它是'['
,我们期望一个json数组,依此类推。
所有其他函数的构建方式相同:检查当前字符,确定接下来要做什么,然后解析此对象。
对象本身可能包含其他值,因此您将再次在value
中找到函数object
的间接递归调用。因此,通过递归调用所有json对象函数,它们实际上是从源字符串中解析的。