工做中须要将javascript的if语句描述进行一些规范化,将相似javascript
if(test) value0 else value1
的语句的所有统一成:java
if (test) result = value0; else result = value1;
格式的,便于后续处理。node
方法之一使用AST替换来完成,主要用到estools提供的javascript解析和代码生成工具。express
主要操做以下npm
1) 安装node.js工具
2) mkdir convertui
cd convert npm install esprima npm install estraverse npm install escodegen
3) 编写AST解析代码,而且查看生成的AST树spa
var ast = esprima.parse(code); console.log(JSON.stringify(ast,null,4));
4)编写遍历if语句的代码,若是不符合格式,就改变AST的节点。code
ast = estraverse.replace(ast, { leave: function(node, parent) { modifiedNode = node; if (node.type === 'IfStatement') { if (node.consequent.type === 'ExpressionStatement') { if (node.consequent.expression.type === 'Literal'){ modifiedNode['consequent'] = { "type": "ExpressionStatement", "expression": { "type": "AssignmentExpression", "operator": "=", "left": { "type": "Identifier", "name": "result" }, "right": node.consequent.expression } } }; if (node.alternate != null && node.alternate.expression.type === 'Literal'){ modifiedNode['alternate'] = { "type": "ExpressionStatement", "expression": { "type": "AssignmentExpression", "operator": "=", "left": { "type": "Identifier", "name": "result" }, "right": node.alternate.expression } } }; } }; return modifiedNode; } });
5)修改好后的ast,生成源代码ip
var modifiedCode = escodegen.generate(ast);
6)运行
得到结果
$ node exc1.js test1.js Reading test1.js ============= if (var1 > 2) result = 3; else result = 0; if(var2 < 3) 0 else 1 if (var3 === 9) 1; ============= if (var1 > 2) result = 3; else result = 0; if (var2 < 3) result = 0; else result = 1; if (var3 === 9) result = 1;
7) 完整代码
exc1.js ----------- /* */ var fs = require('fs'), esprima = require('esprima'), estraverse = require('estraverse'), escodegen = require('escodegen'); function analyzeCode(code) { var ast = esprima.parse(code); //console.log(JSON.stringify(ast,null,4)); ast = estraverse.replace(ast, { leave: function(node, parent) { modifiedNode = node; if (node.type === 'IfStatement') { if (node.consequent != null && node.consequent.type === 'ExpressionStatement') { if (node.consequent.expression.type === 'Literal'){ modifiedNode['consequent'] = { "type": "ExpressionStatement", "expression": { "type": "AssignmentExpression", "operator": "=", "left": { "type": "Identifier", "name": "result" }, "right": node.consequent.expression } } }; if (node.alternate != null && node.alternate.expression.type === 'Literal'){ modifiedNode['alternate'] = { "type": "ExpressionStatement", "expression": { "type": "AssignmentExpression", "operator": "=", "left": { "type": "Identifier", "name": "result" }, "right": node.alternate.expression } } }; } }; return modifiedNode; } }); var modifiedCode = escodegen.generate(ast); console.log('============='); console.log(modifiedCode); //console.log(JSON.stringify(ast,null,4)); } if (process.argv.length < 3) { console.log('Usage: zz.js file.js'); process.exit(1); } var filename = process.argv[2]; console.log('Reading ' + filename); var code = fs.readFileSync(filename); console.log('============='); console.log(''+code); analyzeCode(code); console.log('Done'); --------------
test1.js if (var1 > 2) result = 3; else result = 0; if(var2 < 3) 0 else 1 if (var3 === 9) 1
8)
各类语言用来修改ast语法树的一些方法收集见:
http://adamrehn.com/articles/ast-instrumentation-examples-by-language#sec___javascript