I have one plain string including some conditions like this.
const optionString = '{2109} AND ({2370} OR {1701} OR {2702}) AND {1234} AND ({2245} OR {2339})';
I need to get object like the following structure from above.
const output = {
and: [
2109,
{ or: [2370, 1071, 2702] },
1234,
{ or: [2245, 2339] },
];
Currently, I have tried to do like following
function parseFormat(strArg) {
var
category,
output = [], // Output
str = strArg.trim(); // Remove unwanted space before processing
str.split('AND').forEach(function(line) {
var removedString = line.replace(/[\])}[{(]/g, '');
var item = removedString.split('OR');
item = item.map(it => {
return Number(it.replace(/ /g, ''))
})
if(item.length > 0) {
output.push(item)
} else {
output.push(item[0])
}
});
return output;
}
And its output is like here.
[
[
1069
],
[
1070,
1071,
1072
],
[
1244
],
[
1245,
1339
]
]
I have one question first
- How to add key AND and OR in the current result?
If you know a good solution on the performance side, please update me. Thanks for taking the time.
CodePudding user response:
const optionString = '{2109} AND ({2370} OR {1701} OR {2702}) AND {1234} AND ({2245} OR {2339})';
const parseExpr = s => {
let op, m, a = [];
while(s?.length) {
if(m = /^{(?<num>[0-9] )}( (?<rest>.*))?/.exec(s)) {
a.push( m.groups.num);
s = m.groups.rest;
}
else if(m = /^(?<op>[A-Z] )( (?<rest>.*))?/.exec(s)) {
let t = m.groups.op.toLowerCase();
if(op && op!==t) throw new Error('Multiple operators cannot exist at same level in syntax tree')
else op = t;
s = m.groups.rest;
}
else if(s.startsWith('(')) {
for(let i=0, level=0; i<s.length; i ) {
if(s.charAt(i)==='(') level ;
if(s.charAt(i)===')') level--;
if(!level) {
a.push(parseExpr(s.substring(1, i)));
s = s.substring(i 2);
break;
}
if(i===s.length-1) throw new Error('Mismatched brackets')
}
}
else throw new Error(`Unparseable expression: ${s}`);
}
return { [op]: a };
}
const result = parseExpr(optionString)
console.log(result)