babel 怎么把字符串解析成 AST,是怎么进行词法/语法分析的?#前端面试-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

babel 怎么把字符串解析成 AST,是怎么进行词法/语法分析的?#前端面试

2020-05-23 12:52:41 1295 1

babel 怎么把字符串解析成 AST,是怎么进行词法/语法分析的?#前端面试

取消 提交回答
全部回答(1)
  • 一月19
    2020-05-23 14:39:59

    Babel

    定义 - Babel 是我们知道的将 ES6、ES7等代码转译为 ES5 代码且能安全稳定运行最好的工具 - 同时它允许开发者开发插件,能够在编译时期转换 JavaScript 的结构。

    Babel概述 我们需要知道 3 个 Babel 处理流程中的重要工具; 1. 解析

    • Babylon是一个解析器,它可以将javascript字符串,转化为更加友好的表现形式,称之为抽象语法树; 在解析过程中有两个阶段:词法分析和语法分析,
    • 词法分析阶段:字符串形式的代码转换为令牌(tokens)流,令牌类似于AST中的节点;
    • 语法分析阶段:把一个令牌流转化为AST的形式,同时这个阶段会把令牌中的信息转化为AST的表述结构
    • 转换

    • babel-traverse 模块允许你浏览、分析和修改抽象语法树(AST Abstract Syntax Tree)

    • Babel接收解析得到的AST并通过babel-traverse对其进行深度优先遍历,在此过程中对节点进行添加、更新及移除操作。
    • 生成
    • babel-generator 模块用来将转换后的抽象语法树(AST Abstract Syntax Tree)转化为Javascript 字符串
    • 将经过转换的AST通过babel-generator再转换为js代码,过程及时深度遍历整个AST,然后构建转换后的代码字符串。

    ** Babel 中重要的对象Vistor** babel 在处理一个节点时,是以访问者的形式获取节点的信息,并进行相关的操作,这种操作是通过visitor对象实现的。 在 visitor 中定义了处理不同节点的函数。

    visitor: {
      Program: {
        enter(path, state) {
          console.log('start processing this module...');
        },
          exit(path, state) {
            console.log('end processing this module!');
          }
      },
        ImportDeclaration:{
          enter(path, state) {
            console.log('start processing ImportDeclaration...');
            // do something
          },
            exit(path, state) {
              console.log('end processing ImportDeclaration!');
              // do something
            }
        }
    }
    

    AST#

    定义 - AST (Abstract Syntax Tree)是抽象语法树英文的缩写,AST语法树每一层都拥有相同的结构,这样的每一层结构也被叫做节点(Node)。 - AST 是源代码的抽象语法结构树状表现形式,Webpack、ESLint、JSX、TypeScript 的编译和模块化规则之间的转化都是通过 AST 来实现对代码的检查、分析以及编译等操作。 - 一个 AST 可以由单一的节点或是成百上千个节点构成。 它们组合在一起可以描述用于静态分析的程序语法。 Javascript 语法的AST(抽象语法树) javascript 语句要想知道抽象语法树之后的代码是什么,里面的字段都代表什么含义以及遍历的规则,可以通过javascript语法转换AST工具来实现javascript语法的在线转换; 例如: image.png - esprima、estraverse 和 escodegen 模块是操作 AST 的三个重要模块,也是实现 babel 的核心依赖。

    例如:语法转换插件需要借助 babel-core 和 babel-types 两个模块,就是依赖 esprima、estraverse 和 escodegen 每一个含有type属性的对象,我们称之为节点,修改是指获取对应的类型并修改改节点的属性即可;

    {
    "type": "Program",
    "body": [
        {
            "type": "VariableDeclaration",
            "declarations": [
                {
                    "type": "VariableDeclarator",
                    "id": {
                        "type": "Identifier",
                        "name": "answer"
                    },
                    "init": {
                        "type": "BinaryExpression",
                        "operator": "*",
                        "left": {
                            "type": "Literal",
                            "value": 6,
                            "raw": "6"
                        },
                        "right": {
                            "type": "Literal",
                            "value": 7,
                            "raw": "7"
                        }
                    }
                }
            ],
            "kind": "var"
        }
      ],
      "sourceType": "script" 
    }```  
    
    **estraverse 遍历和修改AST**
    查看遍历过程:
    
    ![image.png](https://ucc.alicdn.com/pic/developer-ecology/f22149f4ce544f33a8c707b8b3e2443c.png)
    

    const esprima = require("esprima"); const estraverse = require("estraverse");

    let code = "var answer=6 * 7";

    // 遍历语法树 estraverse.traverse(esprima.parseScript(code), { enter(node) { console.log("enter", node.type); }, leave(node) { console.log("leave", node.type); } });

     - 打印结果如下:
    
    ![image.png](https://ucc.alicdn.com/pic/developer-ecology/ee3b38ff5e7f4679b14b7d29f9aef9b5.png)
    
    - 以上代码通过estraverse模块的traverse方法,将esprima模块装换的AST进行了遍历。
    - 通过打印type属性,可以知道深度遍历AST就是遍历每一层的type属性,所以遍历会分为两个阶段,进入阶段和离开阶段,在traverse方法中分别用参数enter和leave两个函数监听;
    **escodegen 将 AST 转换成 JS**
    ![image.png](https://ucc.alicdn.com/pic/developer-ecology/e303480d43374734aa893c135cfb27cc.png)
    ![image.png](https://ucc.alicdn.com/pic/developer-ecology/20ddfc433d134d20843b54bbec0b5258.png)
    
    0 0
相关问答

19

回答

【分享】如何提高网站的打开速度?

enj0y 2012-11-17 14:35:22 58062浏览量 回答数 19

22

回答

爬虫数据管理【问答合集】

我是管理员 2018-08-10 16:37:41 149061浏览量 回答数 22

43

回答

什么是云主机,云服务器与vps有什么区别?

zhuangdengyun 2011-11-01 04:21:50 51708浏览量 回答数 43

31

回答

[@倚贤][¥20]刚学完html/css/js的新手学习servlet、jsp需要注意哪些问题?

弗洛伊德6 2018-10-27 21:52:43 148243浏览量 回答数 31

15

回答

网页挂马及暗链检测

yundun1 2012-02-24 17:40:01 47935浏览量 回答数 15

251

回答

阿里云LNAMP(Linux + Nginx + Apache + MySQL + PHP)环境一键安装脚本

云代维 2014-02-14 15:26:06 310531浏览量 回答数 251

13

回答

【云服务器分享】如何节省网站流量

dreamdoo 2012-10-15 10:36:09 81863浏览量 回答数 13

21

回答

【Java学习全家桶】1460道Java热门问题,阿里百位技术专家答疑解惑

管理贝贝 2018-05-31 13:57:45 50019浏览量 回答数 21

46

回答

H5技术百问——不懂H5你就OUT啦

yq传送门 2017-09-09 11:03:04 48535浏览量 回答数 46

3

回答

Nginx—owncloud安装记事

寒喵 2014-06-07 23:24:41 49798浏览量 回答数 3
+关注
1
文章
47
问答
问答排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载