我得到一个传递一个独特格式的字符串(虽然是一致的),我需要能够解析它,以便我可以修改它的一部分,然后将它重新组合在一起并作为一个传回字符串。
这是传递给我的字符串。它的内容会定期更改,但每个项目结构将保持不变。
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并将其放入适当的Object或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)。它没有任何类型的递归能力来处理多个级别,即查看&gt;按钮&gt; scrollview
对此的任何帮助将不胜感激!
答案 0 :(得分: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是完全有道理的,因为他们所做的肯定更糟。
编辑:更新了代码以将具有相同名称的密钥聚合到数组中。
答案 1 :(得分: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
下有两个View
个属性。虽然你可以使用另一个正则表达式,但我不确定你是如何处理修复的。但这至少应该解决你的初始对象创建问题。
如果您想查看它,请查看this JSFiddle。
答案 2 :(得分:-1)
好的,这应该有效。按照确切的步骤。
- 删除空格和换行符。
- 用分号替换分号;“”(分号,dblquote,dblquote)
- 用“:”替换冒号(双引号冒号dblquote)
- 将开口支架替换为:{“
- 用}“
替换右括号 醇>
你应该完成。