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; |