let openers = { '{': '}', '[': ']', '(': ')' }; let specialOpeners = { ':': 'wildcard' }; function parser(str, context = '{') { str = str.replaceAll(/^\s+([^\s]+)/gm,'$1') str = str.replaceAll(/([^\s]+)\s+$/gm,'$1') let nextI = str.search(/[^A-Za-z0-9\s]/); if (context == '[') { nextI = str.search(/[\]]/); } if (nextI == -1) nextI = 0; let nextChar = str[nextI]; let special = specialOpeners[context] || ''; let sp = (special == 'wildcard'); if (nextChar == openers[context]) { return { context, str: str.slice(0, nextI), next: str.slice(nextI + 1), end: true}; } else if (openers[context] || sp) { let args = []; let nextStr = str.slice(nextI + 1); while (nextStr && nextStr.length > 0) { args.push(parser(nextStr, nextChar)); let a = args[args.length - 1]; nextStr = a.next; if (a.str == '') { args.pop(); } if (a.end) break; } let o = { context: str.slice(0, nextI), args, next: nextStr, op: context }; return o; } else { return { context, str: str.slice(0, nextI), next: str.slice(nextI + 1)}; } } let data = parser(` on:start { echo[Hello World!] echo[Hello World!] } `); console.log(JSON.stringify(data, undefined, 1));