Как работает анализатор Crockfords JSON?

#javascript #json #parsing

#javascript #json #синтаксический анализ

Вопрос:

Я долгое время смотрел на код, найденный здесь. Это функция синтаксического анализа JSON Дугласа Крокфорда (называемая анализатором рекурсивного спуска). Кто-нибудь может подробнее рассказать о механизмах этого анализатора? Я действительно не могу разобраться в этом.

Ответ №1:

Логически вы можете начать с фактических функций синтаксического анализа, которые начинаются со строки 311 (для наглядности опущена часть приемника).

 function (source, reviver) {
    var resu<

    text = source;
    at = 0;
    ch = ' ';
    result = value();
    white();
    if (ch) {
        error("Syntax error");
    }

    return resu<
}
  

Инициализирует глобальные переменные функции text исходным текстом, position at позицией, а текущий символ ch — пробелом. После этого он анализирует значение путем вызова функции value .

Каждый объект, подлежащий анализу, инкапсулируется в саму функцию (в приведенном выше примере объект value). Их несколько: number , string , white , …). Каждый из них в основном работает одинаково. Сначала мы рассмотрим white в качестве базового примера:

 white = function () {

    // Skip whitespace.

    while (ch amp;amp; ch <= ' ') {
        next();
    }
}
  

Обратите внимание, что ch всегда содержит текущий символ. Эта переменная обновляется только при 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' amp;amp; ch <= '9' ? number() : word();
    }
};
  

Сначала он анализирует пробелы путем вызова white . Обратите внимание, что ch теперь содержит текущий символ, подлежащий анализу. Если это a, то '{' теперь мы узнаем, что следующим идет объект json, и вызываем соответствующую функцию object . Если вместо этого это '[' , мы ожидаем массив json и так далее.

Все остальные функции построены таким же образом: проверяют текущий символ, решают, что должно быть следующим, а затем анализируют этот объект.

Сам объект может содержать другие значения, и поэтому вы снова обнаружите непрямой рекурсивный вызов функции value в object . Таким образом, рекурсивный вызов всех объектных функций json фактически анализирует их из исходной строки.