美文网首页
抽象语法树AST

抽象语法树AST

作者: 没了提心吊胆的稗子 | 来源:发表于2019-08-27 11:50 被阅读0次

    1、(Abstract Syntax Tree)

    定义

    这棵树定义了代码的结构,通过这棵树,我们可以精准地定位到声明语句,赋值语句,运算语句等等,实现对代码的分析,优化,变更等操作
    三个库:
    esprima:把js代码转化为语法树
    estraverse:可以遍历一棵语法树
    escodegen:修改完之后重新生成一个ast树

    let esprima = require('esprima');
    let code = 'function ast(){}';
    let ast = esprima.parse(code);
    console.log(ast);
    
    estraverse.traverse(ast, {
        enter(node){
            console.log('enter:' + node.type);
        },
        leave(node){
            console.log('leave:' + node.type);
        }
    });
    
    estraverse.traverse(ast, {
        enter(node){
            console.log('enter:' + node.type);
            if(node.type === 'Identifier'){
                node.name += 'enter';
            }
        },
        leave(node){
            console.log('leave:' + node.type);
            if(node.type === 'Identifier'){
                node.name += 'leave';
            }
        }
    });
    let result = escodegen.generate(ast);
    console.log(result.result); // 生成后的新树
    

    2、babel 转换箭头函数(ES6-ES5)

    babel-core:babel核心库,用来实现核心的转换引擎
    babel-types:可以实现类型判断 生成AST的零部件等

    // babel核心库,用来实现核心的转换引擎
    let babel = require('babel-core');
    /// 可以实现类型判断 生成AST的零部件等
    let types = require('babel-types');
    let code = 'let sum = (a,b) => a+b;';
    // 这个访问者可以对特定类型的节点进行处理
    let visitor = {
        // 有的就拿过来用 没有的就自己加 根据babel-types还有ast中的节点一一对应拼起来
        ArrowFunctionExpression(path){
            let  params = path.node.params;
            let blockStatement = types.blockStatement([
                types.returnStatement(path.node.body)
            ]);
            let func = types.functionExpression(null, params, blockStatement, false, false);
            path.replaceWith(func);
        }
    };
    let arrayPlugin = {visitor};
    // babel内部先把代码转化成AST,然后进行遍历
    let result = babel.transform(code, {
        plugins: [
            arrayPlugin
        ]
    });
    console.log(result.code);
    

    箭头函数的ast
    转化后的ast

    两者对比倒推就可以实现
    预计算表达式

    let babel = require('babel-core');
    let types = require('babel-types');
    let code = `const result = 1000 * 60 * 60 * 24 * 365`;
    // 预计算 名字必须是visitor
    let visitor = {
        BinaryExpression(path){
            let node = path.node;
            if(! isNaN(node.left.value) && ! isNaN(node.right.value)){
                let result = eval(node.left.value + node.operator + node.right.value);
                // 创建一个字面量
                result = types.numericLiteral(result);
                path.replaceWith(result);
                // 如果此表达式的父亲也是一个表达式的话需要递归计算
                if(path.parentPath.node.type === 'BinaryExpression'){
                    visitor.BinaryExpression.call(null, path.parentPath);
                }
            }
        }
    };
    let arrayPlugin = {visitor};
    
    let result = babel.transform(code, {
        plugins: [
            arrayPlugin
        ]
    });
    console.log(result.code);
    

    相关文章

      网友评论

          本文标题:抽象语法树AST

          本文链接:https://www.haomeiwen.com/subject/uejsectx.html