利用estools修改javascript源代碼

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

相關文章
相關標籤/搜索