Skip to content

Instantly share code, notes, and snippets.

@crongro
Last active November 28, 2018 07:57
Show Gist options
  • Save crongro/bc0eaab01eade4ea2bd164c5fb826760 to your computer and use it in GitHub Desktop.
Save crongro/bc0eaab01eade4ea2bd164c5fb826760 to your computer and use it in GitHub Desktop.
before_after
class Data {
constructor(type, value, child) {
this.type = type;
this.value = value;
this.child = child;
}
}
function scan(str) {
let tokens = [];
let stack = "";
for (let token of str) {
if (token === '[' || token === '{') {
stack === "" ? tokens.push(token) : tokens.push(stack);
stack = "";
} else if(token === ','){
if(stack !== "") {tokens.push(stack)};
stack = "";
} else if (token === ']' || token === '}' || token === ':') {
if(stack !== ""){tokens.push(stack)};
tokens.push(token);
stack = "";
} else if (token === ' ') {
continue;
} else {
stack += token;
}
}
return tokens;
}
//token map
const tm = {
others : { ":":"objectKey", "null":"null", "true":"boolean", "false":"boolean", "'":"string" },
start : { "[":"array", "{":"object"},
end : { "]":"array", "}":"object"}
}
//token checker
const tc = {
isStartToken(s) {
if(Object.keys(tm.start).includes(s)) return tm.start[s];
},
isEndToken(s, result) {
if(Object.keys(tm.end).includes(s) && result.length > 1) return tm.end[s];
},
isOtherToken(s) {
if(Object.keys(tm.others).includes(s)) return tm.others[s];
if(s[0] === "'") return tm.others[s[0]];
if(!isNaN(Number(s))) return "number";
},
isCloseToken(s, result) {
if(s === ']' && result.length === 1) return true;
}
}
//Global status >.<
let objectStatus = false;
//parsing by token type
const parseToken = {
executeStartToken(result, tType) {
result.push(new Data(tType, "", []));
if(tType === "object") objectStatus = true;
},
executeOtherToken(result, tType,token, temp) {
const lastChild = result[result.length - 1].child;
if(tType === "objectKey") lastChild.push(new Data(tType, temp));
else lastChild.push(new Data(tType, token));
},
executeEndToken(result, tType) {
const lastData = result.pop();
const lastChild = result[result.length - 1].child;
lastChild.push(lastData);
if(tType === "object") objectStatus = false;
}
}
//수정한 parse
function parse(str) {
const tokens = scan(str);
let result = [];
let temp = ""; //objectKeyName
let tType;
for (let token of tokens) {
if (tc.isCloseToken(token, result)) return result;
if (tType = tc.isStartToken(token)) parseToken.executeStartToken(result, tType);
else if (tType = tc.isOtherToken(token)) parseToken.executeOtherToken(result, tType, token, temp);
else if (tType = tc.isEndToken(token, result)) parseToken.executeEndToken(result, tType);
else if (objectStatus && token !== ':') temp = token;
else { console.log(`${token}은 올바른 문자열이 아닙니다.`);return;}
}
}
function countApostrophe(token) {
let count = 0;
for (let letter of token) {
if (letter === "'") count++;
}
if (count === 2) return true;
return false;
}
//test
//var str = "['1a3',{key : [null,false]}, true]";
var str = "['1a3',[null,false,['11',[112233],{easy : ['hello', {a: 'a' }, 'world']},112],55, '99'],{a:'str', b:[912,[5656,33],{key : 'innervalue', newkeys: [1,2,3,4,5]}]}, true]";
console.log(JSON.stringify(parse(str), null, 2));
class Data {
constructor(type, value, child) {
this.type = type;
this.value = value;
this.child = child;
}
}
function scan(str) {
let tokens = [];
let stack = "";
for (let token of str) {
if (token === '[' || token === '{') {
stack === "" ? tokens.push(token) : tokens.push(stack);
stack = "";
} else if(token === ','){
if(stack !== "") {tokens.push(stack)};
stack = "";
} else if (token === ']' || token === '}' || token === ':') {
if(stack !== ""){tokens.push(stack)};
tokens.push(token);
stack = "";
} else if (token === ' ') {
continue;
} else {
stack += token;
}
}
return tokens;
}
function parse(str) {
const tokens = scan(str);
let result = [];
let temp = "", objectStatus = false;
for (let token of tokens){
if (token === '[') {
result.push(new Data('array', "", []));
} else if (token === '{') {
result.push(new Data('object', "", []));
objectStatus = true;
} else if (token === ':'){
const lastChild = result[result.length - 1].child;
lastChild.push(new Data('objectKey', temp));
} else if (!isNaN(Number(token))) {
const lastChild = result[result.length - 1].child;
lastChild.push(new Data('number', token));
} else if (token === 'null') {
const lastChild = result[result.length - 1].child;
lastChild.push(new Data('null', token));
} else if (token === 'true' || token === 'false') {
const lastChild = result[result.length - 1].child;
lastChild.push(new Data('boolean', token));
} else if (token[0] === "'") {
if (!countApostrophe(token)) {
console.log(`${token}은 올바른 문자열이 아닙니다.`);
return;
}
const lastChild = result[result.length - 1].child;
lastChild.push(new Data('string', token));
} else if (token === ']' && result.length > 1) {
const lastData = result.pop();
const lastChild = result[result.length - 1].child;
lastChild.push(lastData);
} else if (token === '}' && result.length > 1) {
const lastData = result.pop();
const lastChild = result[result.length - 1].child;
lastChild.push(lastData);
objectStatus = false;
} else if (token === ']' && result.length === 1) {
return result;
} else if (objectStatus === true && token !== ':'){
temp = token;
} else {
console.log(`${token}은 올바른 문자열이 아닙니다.`);
return;
}
}
}
function countApostrophe(token) {
let count = 0;
for (let letter of token) {
if (letter === "'") count++;
}
if (count === 2) return true;
return false;
}
//test
var str = "['1a3',[null,false,['11',[112233],{easy : ['hello', {a: 'a' }, 'world']},112],55, '99'],{a:'str', b:[912,[5656,33],{key : 'innervalue', newkeys: [1,2,3,4,5]}]}, true]";
console.log(JSON.stringify(parse(str), null, 2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment