| Index: lib/snippets.js |
| =================================================================== |
| --- a/lib/snippets.js |
| +++ b/lib/snippets.js |
| @@ -74,8 +74,86 @@ |
| result.push(filter); |
| } |
| } |
| return result; |
| } |
| }; |
| exports.Snippets = Snippets; |
| + |
| +/** |
| + * Parses a script and returns a list of all its commands and their arguments |
| + * @param {string} script |
| + * @return {Array.<string[]>} |
| + */ |
| +function parseScript(script) |
| +{ |
| + const singleCharacterEscapes = new Map([ |
| + ["n", "\n"], ["r", "\r"], ["t", "\t"] |
| + ]); |
| + |
| + let tree = []; |
| + |
| + let escape = false; |
| + let literal = false; |
| + |
| + let unicodeEscape = null; |
| + |
| + let call = []; |
| + let argument = ""; |
| + |
| + for (let character of [...script.trim(), ";"]) |
| + { |
| + if (unicodeEscape != null) |
| + { |
| + unicodeEscape += character; |
| + |
| + if (unicodeEscape.length == 4) |
| + { |
| + let codePoint = parseInt(unicodeEscape, 16); |
| + if (!isNaN(codePoint)) |
| + argument += String.fromCodePoint(codePoint); |
| + |
| + unicodeEscape = null; |
| + } |
| + } |
| + else if (escape) |
| + { |
| + escape = false; |
| + |
| + if (character == "u") |
| + unicodeEscape = ""; |
| + else |
| + argument += singleCharacterEscapes.get(character) || character; |
| + } |
| + else if (character == "\\") |
| + { |
| + escape = true; |
| + } |
| + else if (character == "'") |
| + { |
| + literal = !literal; |
| + } |
| + else if (literal || character != ";" && !/\s/u.test(character)) |
| + { |
| + argument += character; |
| + } |
| + else |
| + { |
| + if (argument) |
| + { |
| + call.push(argument); |
| + argument = ""; |
| + } |
| + |
| + if (character == ";" && call.length > 0) |
| + { |
| + tree.push(call); |
| + call = []; |
| + } |
| + } |
| + } |
| + |
| + return tree; |
| +} |
| + |
| +exports.parseScript = parseScript; |