0

一意の形式(ただし一貫性があります)の文字列が渡されます。これを解析して、その一部を変更してから元に戻し、文字列として返すことができるようにする必要があります。

これが渡される文字列imです。内容は定期的に変更されますが、各アイテムの構造は変わりません。

    View
{
    Name: View1;
    Image
    {
        BackgroundImage: Image.gif;
        Position: 0, 0;
        Width: 320;
        Height: 480;
    }

    Button
    {
        BackgroundImage: Button.gif;
        Transition: View2;
        Position: 49, 80;
        Width: 216;
        Height: 71;
    }

    Button
    {
        BackgroundImage: Button2.gif;
        Position: 65, 217;
        Width: 188;
        Height: 134;
    }

    Label
    {
        Position: 106, 91;
        Width: 96;
        Height: 34;
        Text: "Button";
        FontSize: 32;
        Color: 0.12549, 0.298039, 0.364706, 1;
    }
    Scroll
    {
        Position: 106, 91;
        Width: 96;
        Height: 34;
        Button{
            BackgroundImage: Button2.gif;
            Position: 65, 217;
            Width: 188;
            Height: 134;
        }
        Button{
            BackgroundImage: Button2.gif;
            Position: 65, 217;
            Width: 188;
            Height: 134;
        }

    }

}

各k、vを探し出し、それを適切なオブジェクトまたはJSONファイルに入れて変更できるようにする再帰関数が必要だと思います。私が得た最も遠いのは、単一のレベルを解析して、それをk、vオブジェクトに入れることができることです。これがコードとそれが解析する文字列です。

コードで機能するように文字列を変更しました(シングルレベルの深さ。View{}とScroll {}を削除しました):

var content='Image{BackgroundImage: Image.gif;Position: 0, 0;Width: 320;Height: 480;}Image{BackgroundImage: Image2.gif;Position: 0, 0;Width: 320;Height: 480;}Button{BackgroundImage: Button.gif;Position: 49, 80;Width: 216;Height: 71;}Button{BackgroundImage: Button.gif;Position: 49, 80;Width: 216;Height: 71;}Button{BackgroundImage: Button2.gif;Transition: View2;Position: 65, 217;Width: 188;Height: 134;}Button{BackgroundImage: Button3.gif;Transition: View2;Position: 65, 217;Width: 188;Height: 134;}Label{Position: 106, 91;Width: 96;Height: 34;Text: "Button";FontSize: 32;Color: 0.12549, 0.298039, 0.364706, 1;}Label{Position: 106, 91;Width: 96;Height: 34;Text: "Button";FontSize: 32;Color: 0.12549, 0.298039, 0.364706, 1;}';

        var result = content.split('}');
        result.pop();// removing the last empty element
        var obj = {Controls:{}};

        function nextProp(key) {
            /*if(obj.Controls.hasOwnProperty(key)) {
                var num = key.match(/\d+$/);
                if (num) {
                    return nextProp(key.replace(num[0], '') + (parseInt(num[0], 10) + 1));
                } else {
                    return nextProp(key + '1');
                }
            }*/

            return key;
        }

        for (var i = 0; i < result.length; i++) {
            var key = result[i].split('{');
            var value = result[i].replace(key[0], '') + '}';
            obj.Controls[nextProp(key[0])] = value;
        }

        var initObjectList = '<div id="prePop">';
        $.each(obj.Controls, function (k, v) {
        initObjectList += '<div class="inLineObjects">' + '<div class="key">' + k + '</div><br/>' + '<div  class="value">' + v + '</div>' +'</div>';

        });
    initObjectList += '</div>';
    $('#code').append(initObjectList)

戻り値:

{
    "Controls": {
        "Image": "{BackgroundImage: Image.gif;Position: 0, 0;Width: 320;Height: 480;}",
        "Image1": "{BackgroundImage: Image2.gif;Position: 0, 0;Width: 320;Height: 480;}",
        "Button": "{BackgroundImage: Button.gif;Position: 49, 80;Width: 216;Height: 71;}",
        "Button1": "{BackgroundImage: Button2.gif;Transition: View2;Position: 65, 217;Width: 188;Height: 134;}",
        "Button2": "{BackgroundImage: Button3.gif;Transition: View2;Position: 65, 217;Width: 188;Height: 134;}",
        "Label": "{Position: 106, 91;Width: 96;Height: 34;Text: \"Button\";FontSize: 32;Color: 0.12549, 0.298039, 0.364706, 1;}",
        "Label1": "{Position: 106, 91;Width: 96;Height: 34;Text: \"Button\";FontSize: 32;Color: 0.12549, 0.298039, 0.364706, 1;}"
    }
}

私の問題は、上記ではa)ができないことです。{}はすべて値であり、b)であるため、すべてをターゲットにします。複数のレベル、つまり[表示]>[ボタン]>[スクロールビュー]を処理する再帰機能はありません。

これに関する助けをいただければ幸いです。

4

3 に答える 3

1
function generalizeFunnyformat(raw) {
    "use strict";
    return ",;:{}".indexOf(raw) > -1? raw :
        " \t\r\n".indexOf(raw) > -1? " ": "a";
}

function infer(value) {
    "use strict";
    if (/^\d/.test(value)) {
        return parseFloat(value);
    } else if (/["']/.test(value)) {
        return value.substr(1, value.length - 2);
    } else {
        return value;
    }
}

function tokenEnd(state, first, second) {
    "use strict";
    state.token += first;
    if (!state.meta) {
        if (state.cursor &&
            state.cursor.hasOwnProperty(state.token)) {
            // This may be overly confident. What if primitives are also
            // allowed at the same nesting level?
            // Here we hope that coursor will be adjusted by bracket()
            // but if it doesn't happen, then we are lost.
            if (!(state.cursor[state.token] instanceof Array)) {
                state.cursor[state.token] = [state.cursor[state.token]];
            }
            state.extra = true;
            state.cursor = state.cursor[state.token];
            state.meta = state.cursor.length;
        } else {
            state.cursor[state.token] = null;
            state.meta = state.token;
        }
    } else if (state.appending) {
        if (state.cursor[state.meta] instanceof Array) {
            state.cursor[state.meta].push(state.token);
        } else {
            state.cursor[state.meta] =
                [state.cursor[state.meta], infer(state.token)];
        }
    } else {
        state.cursor[state.meta] = infer(state.token);
    }
    state.token = "";
}

function space(state, first, second) {
    "use strict";
    // noop
}

function token(state, first, secon) {
    "use strict";
    state.token += first;
}

function bracket(state, first, secon) {
    "use strict";
    var newCursor = { };
    state.cursor[state.meta] = newCursor;
    state.parents.unshift(state.cursor);
    state.cursor = newCursor;
    state.meta = "";
}

function close(state, first, second) {
    "use strict";
    state.cursor = state.parents[0];
    state.parents.shift();
    if (state.extra) {
        state.cursor = state.parents[0];
        state.parents.shift();
    }
    state.extra = false;
    state.appending = false;
}

function comma(state, first, second) {
    "use strict";
    state.appending = true;
}

function colon(state, first, second) {
    "use strict";
    state.appending = false;
}

function semi(state, first, second) {
    "use strict";
    if (state.token) {
        tokenEnd(state, "", second);
    }
    state.meta = "";
    state.appending = false;
}

function error(state, first, second) {
    "use strict";
    throw "Invalid character sequence: " + second +
        " cannot follow " + first;
}

function llparseFunnyFormat(source) {
    "use strict";
    var iterator, len = source.length - 1,
        first, second, genFirst, genSecond, handler,
        state = { result: null, cursor: { }, appending: false,
                  token: "", meta: null, parents: [], extra: false },
        parseTable = { "  ": space,
                       " :": space,
                       " a": space,
                       " ,": space,
                       " }": space,
                       " ;": space,
                       " {": space, // space
                       "aa": token,
                       "a ": tokenEnd,
                       "a:": tokenEnd,
                       "a;": tokenEnd,
                       "a{": tokenEnd,
                       "a,": tokenEnd,
                       "a}": error, // token
                       "{ ": bracket,
                       "{a": bracket,
                       "{}": bracket,
                       "{,": error,
                       "{:": error,
                       "{;": error,
                       "{{": error, // bracket
                       "} ": close,
                       "}}": close,
                       "}a": error,
                       "};": error,
                       "},": error,
                       "}:": error,
                       "}{": error, // close
                       ",,": error,
                       ",a": comma,
                       ", ": comma,
                       ",;": error,
                       ",:": error,
                       ",}": error,
                       ",{": error, // comma
                       "; ": semi,
                       ";a": semi,
                       ";}": semi,
                       ";,": error,
                       ";:": error,
                       ";;": error,
                       ";{": error, // semicolon
                       "::": error,
                       ":a": colon,
                       ": ": colon,
                       ":,": error,
                       ":;": error,
                       ":{": error,
                       ":}": error
                     };
    state.parents[0] = state.cursor;
    state.result = state.cursor;
    for (iterator = 0; iterator < len; iterator++) {
        first = source[iterator];
        second = source[iterator + 1];
        genFirst = generalizeFunnyformat(first);
        genSecond = generalizeFunnyformat(second);
        handler = parseTable[genFirst + genSecond];
        handler(state, first, second);
    }
    return state.result;
}

var test =
"View" +
"{" +
"    Name: View1;" +
"    Image" +
"    {" +
"        BackgroundImage: Image.gif;" +
"        Position: 0, 0;" +
"        Width: 320;" +
"        Height: 480;" +
"    }" +
"" +
"    Button" +
"    {" +
"        BackgroundImage: Button.gif;" +
"        Transition: View2;" +
"        Position: 49, 80;" +
"        Width: 216;" +
"        Height: 71;" +
"    }" +
"" +
"    Button" +
"    {" +
"        BackgroundImage: Button2.gif;" +
"        Position: 65, 217;" +
"        Width: 188;" +
"        Height: 134;" +
"    }" +
"" +
"    Label" +
"    {" +
"        Position: 106, 91;" +
"        Width: 96;" +
"        Height: 34;" +
"        Text: \"Button\";" +
"        FontSize: 32;" +
"        Color: 0.12549, 0.298039, 0.364706, 1;" +
"    }" +
"    Scroll" +
"    {" +
"        Position: 106, 91;" +
"        Width: 96;" +
"        Height: 34;" +
"        Button{" +
"            BackgroundImage: Button2.gif;" +
"            Position: 65, 217;" +
"            Width: 188;" +
"            Height: 134;" +
"        }" +
"        Button{" +
"            BackgroundImage: Button2.gif;" +
"            Position: 65, 217;" +
"            Width: 188;" +
"            Height: 134;" +
"        }" +
"" +
"    }" +
"" +
"}";

llparseFunnyFormat(test);

上記は、あなたの例から私が理解できることに対する公正なLL(1)パーサーです。それはあなたが必要とすることをするように見えます、しかしそれは端のまわりで荒いかもしれません。特に、infer()関数に含まれるデータ型をより適切に推測するために関数を操作することをお勧めします。

またeval()、RPCを介して取得したデータでは明らかに使用したくないものも使用しません。

また、を調べるとparseTable、この形式の文法がどれほどひどく設計されているかがわかります。無効な製品が多すぎます(JSONでさえ優れています!)。したがって、このデータを提供している人にJSONだけを使用するように依頼するのは完全に理にかなっています。なぜなら、彼らが作成したものは確かに悪いからです。

編集:同じ名前のキーを配列に集約するようにコードを更新しました。

于 2012-12-27T19:57:18.850 に答える
0

これは機能するはずです:

str = str.replace(/(\w+)\s*\{/g, "$1:{"); // add in colon after each named object
str = str.replace(/\}(\s*\w)/g, "},$1"); // add comma before each new named object
str = str.replace(/;/g, ","); // swap out semicolons with commas
str = str.replace(/,(\s+\})/g, "$1"); // get rid of trailing commas
str = str.replace(/([\d\.]+(, [\d\.]+)+)/g, "[$1]"); // create number arrays
str = str.replace(/"/g, ""); // get rid of all double quotes
str = str.replace(/:\s+([^\[\d\{][^,]+)/g, ':"$1"');  // create strings

var obj;
eval("obj={" + str + "};");

alert(obj.View.Scroll.Button.Width);

これに関する唯一の問題は、疑似JSONに一意のプロパティ名がないことです。たとえば、Buttonの下に2つのプロパティがありViewます。別の正規表現を使用して修正することはできますが、それを修正する方法がわかりません。しかし、これは少なくとも最初のオブジェクト作成の問題を解決するはずです。

このJSFiddleの動作を確認したい場合は、このJSFiddleを確認してください。

于 2012-12-27T19:34:13.693 に答える
-1

さて、これはうまくいくはずです。正確な手順に従ってください。

  1. 空白と改行を削除します。
  2. セミコロンを;""(semicolon、dblquote、dblquote)に置き換えます
  3. コロンを「:」に置き換えます(二重引用符のコロンdblquote)
  4. オープニングブレースを:{"に置き換えます
  5. 閉じ中括弧を}"に置き換えます

あなたはやるべきです。

于 2012-12-27T18:26:01.967 に答える