Par*_*ara 1 javascript parsing
我有一个字符串,其中包含许多以";"分隔的JavaScript语句.
我需要将其拆分为一个字符串数组,每个字符串包含一个单独的命令.
我不能简单地使用字符串拆分功能";" 作为分隔符,因为";" 也存在于字符串中的其他命令中.
如何将包含多个js语句的字符串包含在一个字符串数组中,每个字符串包含一个单独的命令?
例如,我可以有类似的东西:
$('_32123').innerHTML="<div style=\"font-size:11px;margin-right:15px;margin-
bottom:5px;text-align:right;\" id=\"_134607\" noprint='no' noprintoverflow='no'>
</div>";document.onkeydown = function(event) { if (event.ctrlKey &&
event.keyCode == 89) Event(3160,'Refresh',{ q:'' }); };
Run Code Online (Sandbox Code Playgroud)
是否有可以提供此功能的库或其他内容,或者我还能如何解决此问题?
正则表达式太简单了,无法将JavaScript代码拆分为语句.这可以用于简单的事情,但有JavaScript字符串,JavaScript正则表达式和注释使这更复杂.此外,JavaScript结构不一定以分号结尾.考虑一下:
if (foo) { throw "bar"; }
Run Code Online (Sandbox Code Playgroud)
虽然throw "bar";以分号结尾,但不清楚是否要捕获整个if语句的主体或只是throw部分.除此之外,JavaScript语句也可能以换行结束.以下是两个有效的JavaScript语句,但不以分号分隔:
a = 1
b = 2
Run Code Online (Sandbox Code Playgroud)
为了处理所有这些复杂的规则,您需要一个语言感知解析器.有几个JavaScript解析框架,您必须选择适合您的解析器框架.
以下是使用Acorn标记语句的示例.我在安装了acorn之后在nodejs中运行了以下代码npm install acorn:
var code = "$('_32123').innerHTML=\"<div style=\\\"font-size:11px;margin-right:15px;margin-bottom:5px;text-align:right;\\\" id=\\\"_134607\\\" noprint='no' noprintoverflow='no'></div>\";document.onkeydown = function(event) { if (event.ctrlKey && event.keyCode == 89) Event(3160,'Refresh',{ q:'' }); };";
var acorn = require("acorn");
var tokens = acorn.parse(code);
tokens.body.forEach(function(token) {
console.log("statement: ", code.substr(token.start, token.end - token.start));
});
Run Code Online (Sandbox Code Playgroud)
这将打印示例代码中的两个顶级语句.
请注意,您提供的示例JavaScript代码只有两个顶级语句(两个赋值表达式),但总共有两个以上的语句.例如,还有一个函数声明和一个if语句.这些语句是两个顶级语句的子语句.
如果要单独捕获所有这些语句(顶级语句和子语句),则需要遍历解析器生成的抽象语法树,并将其递归到子字符串中.进行递归也是必要的,因为JavaScript允许嵌套结构(控制结构,函数).
这很容易变得有点复杂,因为你必须处理不同的子语句类型.这是一个只处理几种类型的示例实现,演示了如何遍历AST:
var code = "$('_32123').innerHTML=\"<div style=\\\"font-size:11px;margin-right:15px;margin-bottom:5px;text-align:right;\\\" id=\\\"_134607\\\" noprint='no' noprintoverflow='no'></div>\";document.onkeydown = function(event) { if (event.ctrlKey && event.keyCode == 89) Event(3160,'Refresh',{ q:'' }); };";
var acorn = require("acorn");
var tokens = acorn.parse(code);
function recursiveDump(token, level) {
var pad = Array(level).join(" ");
console.log(pad + "- token");
console.log(pad + " - type: " + token.type);
console.log(pad + " - code: " + code.substr(token.start, token.end - token.start));
if (token.type === 'ExpressionStatement') {
if (token.expression.left) {
console.log(pad + " - children:");
recursiveDump(token.expression.left, level + 3);
recursiveDump(token.expression.right, level + 3);
console.log();
}
}
else if (token.type === 'IfStatement') {
console.log(pad + " - children:");
recursiveDump(token.test, level + 3);
recursiveDump(token.consequent, level + 3);
if (token.alternate !== null) {
recursiveDump(token.alternate, level + 3);
}
console.log();
}
else if (token.hasOwnProperty("body")) {
console.log(pad + " - children:");
var body = token.body;
if (! Array.isArray(body) && body.hasOwnProperty("body")) {
body = body.body;
}
body.forEach(function(token) {
recursiveDump(token, level + 3);
});
console.log();
}
}
tokens.body.forEach(function(token) {
recursiveDump(token, 0);
});
Run Code Online (Sandbox Code Playgroud)
这只是一般如何处理子字符的简单示例.如果您只需要处理顶级语句,则可以保存所有这些工作.