问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

你用过的所有前端编译工具,AST遍历思路就这一种

发布网友 发布时间:2024-10-14 09:47

我来回答

1个回答

热心网友 时间:2024-10-14 14:25

作为前端,我们会用很多编译工具:typescriptcompiler、babel、eslint、postcss等等,它们的AST不尽相同,但AST的遍历算法有且只有一种,不信我们慢慢来理一下。

AST的遍历思路

编译工具会把源码转成AST,从而把对字符串的操作转为对AST对象树的操作。

既然要操作AST,那就要找到对应的AST,这就需要遍历。

怎么遍历呢?

AST不就是树嘛,而树的遍历就深度优先和广度优先两种,而这里只能是深度优先。

那对于每个AST怎么遍历呢?

比如a+b这个BinaryExpression,需要遍历left、right属性

比如if(a===1){}这个IfStatement,需要遍历test、consequece属性:

这样,我们记录下每种AST怎么遍历,然后从根结点开始递归的遍历就可以了。

比如像这样:

因为是每种AST访问那些key,所以叫做visitorKeys。

遍历每种AST的时候,就从visitorKeys里面找,看看要遍历哪些属性,之后取出来递归遍历就行了。

这就是AST的遍历过程,有且只有这么一种。(你还能想出第二种么?)

当然,思路虽然只有一种,但还是有一些变形的:

比如把递归变成循环,因为AST如果过深,那递归层次就过深,可能栈溢出,所以可以加一个数组(作为栈)来记录接下来要遍历AST,这样就可以变成循环了。(reactfiber也是把递归变循环)

比如可以不把visitorKeys提出来,而是直接在代码里写死,这样虽然不如提出来更容易扩展,但是做一些针对部分AST的逻辑变更还是比较方便的。

说了这么多,但是你可能不信,那我们就上源码来看下babel、eslint、tsc、estraverse、postcss都是怎么遍历AST的。

各种编译工具的AST遍历的实现

源码里面有很多无关的信息,我们重点看遍历的部分就好了:

eslint

eslint的遍历过程比较标准,我们先来看下这个:

就是对每种AST都从visitorKeys中拿到遍历的属性keys,然后递归遍历每个key的值就行了,数组的话还要循环遍历每个元素。

和我们上面理清的思路一毛一样。

而且,在遍历之前可以调用enter回调函数,在遍历之后可以调用exit回调函数。

babel

babel也是一样的思路,通过visitorKeys记录每种AST怎么遍历,然后遍历的时候取出对应的keys来递归访问:

babel分为了两个方法,没啥实质区别,而且也有enter和exit两个阶段的回调。

estraverse

estraverse是专门用于遍历AST的库,一般和esprima的parser配合。它的AST遍历和上面两个不太一样,就是把递归变成了循环。

看到我标出来的地方了么,和上面的是一样的,只不过这里不是递归了,而是把要遍历的AST放入数组,之后继续循环。

递归改循环的思路都是这样,加个数组(作为栈)记录路径就可以了。

typescript

typescript的遍历和上面的也不太一样,它没有抽离出visitorKeys的数据,而是写死在代码里对什么AST访问什么属性:

这种方式比较命令式,要把所有AST枚举一遍,而上面那种把visitorKeys抽离出来的方式是声明式的思想,逻辑可以复用。不知道为什么ts是这样写遍历逻辑的,可能好处就是可以对某一些遍历逻辑做修改吧。

postcss

postcss也稍微有点不同,它的所有key都是可遍历的,也就不需要visitorKeys,直接遍历所有的key就行。

而且postcss的node是有方法的,通过面向对象的方式来组织遍历的过程。

写法上有点区别,但遍历的思路没有变。

总结

前端领域的编译工具有挺多的,它们都是基于AST,而操作AST就需要遍历来查找。

eslint、babel、estraverse、postcss、typescriptcompiler这些编译工具的遍历AST的实现我们都过了一遍,虽然有的用递归、有的用循环,有的是面向对象、有的是函数,有的是抽离visitorKeys、有的是写死在代码里,但思路都是一样的。

所以,我们来正式的下个结论:编译工具的遍历实现思路只有一种,就是找到每种AST的可遍历的keys,深度优先的遍历。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
arrive in和arrive at 有什么区别? 磁力泵为什么可空转? 为什么不让衬氟塑料磁力泵空转?怎样提升设备稳定性? 工业软管泵 塑料磁力泵为什么不能空转 求推荐男主和女配在一起的小说? 《红衣天下》txt全集下载 检测公司检测哪些 检测公司是怎么样的 检测公司属于什么企业 为什么 typescript-eslint 性能很慢 被刑拘后,交了7万非法所得暂扣款和保释金1万,现在不起诉我了,其他人起... ...生,我想自考本专业本科,我该怎么办啊。越详细越好 和昊昊聊前端转译器之parser综合篇 通关前端工程化(一)ESLint全方位解析,让你不再面向搜索引擎配置_百度... ...知道关于自考的信息,有谁能说说,越详细越好,谢谢! 取保候审已经解除了,保证金也退还了,被办案单位暂扣的款没有退还! ...设计专业整个流程是怎么样的?,描述得越详细越好? 请简述自考本科相关报名手续,与相关流程、越详细越好。谢谢!!! 双肺微小结节影严重吗 多囊卵巢综合征患者同房会怀孕吗 2023想了解国际学校,报名国际校园开放日怎么报名参加?广州加拿大国际学校... 什么叫番禺区公办教师? “销来肯信玉为魂”的出处是哪里 融创上城三期的付款方式有哪些? 融创上城三期是什么类型的物业? 住长春融创上城一期,想安宽带,只能是方正的,安的时候说找不到网线入户... 怎么下载土豆网的电影到手机? 北京交社保补缴了两年后满五年可以进行小汽车摇号吗 电站总装机容量是什么概念 tms320f28035编程器_tms320f28035_tms320f2809 【案例分享】TI的28035外部晶振在批量时不起振问题 TI DSP芯片TMS320F28035加密、解密、编程烧录解决方案 画画没感觉了 怎么办 杭州市诺基亚售后服务点在哪里电话是多少? 画画没感觉~痛啊~~ ...3万定期一年 3.2%利息 存3年 2. 3万定期三年 5.5%利息 哪个3年... 一万死期一年利息多少?两年的 三年的呢。如果我存一万5年的,两年后... 古代人传递信息的方法写一个小故事 古代人传递信息的小故事 产妇能不能吃虾子 产妇饮食注意事项 坐月子期间能虾吗 香菱咏月·其三作品鉴赏 win10进入启用或关闭系统图标界面 网络图标按钮不可操作为灰色 怎么弄... 赏析香菱做的第三首诗,和香菱赏析其他诗一样。抓住重点的字 2024广州考研初试考点在哪 高一物理公式总结,大神们看仔细,是高一上册。超出了的请别复制,谢谢 对于晕车的人来说、坐动车组会不会不晕啊、?最好是有经验的人来... 做普通火车不晕车的人,坐动车组会不会晕车? 2011年12月27日,中国自主建设、独立运行,并与世界其他卫星导航系统兼 ...