工做中須要將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