json_parse Douglas Crockford

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス avaScriptをやり始めた人が理解したほうが良いJSONパーサのコード

by s_hiroshi

JavaScript

// JavaScriptをやり始めた人が理解したほうが良いJSONパーサのコード
// http://d.hatena.ne.jp/sifue/20120218/1329588477

// JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
// 作者: Douglas Crockford,水野貴明
// 出版社/メーカー: オライリージャパン




var json_parse = function () {
    // JSONをパースして、JavaScriptのデータ構造を生成する関数
    // シンプルな再帰下降パーサで実装されています
    //
    // 実行例:
    // var obj = json_parse("{\"first\": \"Jerome\"}");
    //
    // 実行例(全ての値に操作を行うreviver関数ありの場合):
    // var obj =  json_parse("{\"first\": \"Jerome\"}",
    // function(key, value){if(key==='first') return 'hoge'; return value;});
    //
    // Chromeの方は、ツール > JavaScriptコンソールに、このソースを全て貼り付けて、
    // 実行例を実行して、すぐに動作確認できます。

    // グローバル変数を生成することを避けるため、以下の変数及び関数は、
    // 関数の中で定義されます

    var at,     // 現在の文字のインデックス値
        ch,     // 現在の文字
        escapee = {
            '"':  '"',
            '\\': '\\',
            '/':  '/',
            b:    'b',
            f:    '\f',
            n:    '\n',
            r:    '\r',
            t:    '\t'
        },
        text,


        error = function (m) {
            // 何か問題が発生した場合に、errorが呼び出す関数
            throw {
                name:    'SyntaxError',
                message: m,
                at:      at,
                text:    text
            };
        },


        next = function (c) {
            // 一文字次に進める関数
            // もしパラメーターcが指定されていたら、
            // それが現在の文字にマッチするのかを調べ、矛盾がありそうならエラーで終わらせます
            if (c && c !== ch) {
                error("Expected '" + c + "' instead of '" + ch + "'");
            }
            // 次の文字を取得します。もしそれ以上がなかったら、
            // 空文字を返します

             ch = text.charAt(at);
             at += 1;
             return ch;
         },


        number = function () {
            // 数値を解析する関数
            var number,
                string = '';

            // もしマイナスが来たら、マイナスをstringに取りおいて次へ
            if (ch === '-') {
                string = '-';
                next('-');
            }

            // 0~9までの間の文字コードならば、stringに連結させては次へ
            while...