webpack ast 语法分析
什么是ast ?
abstract syntax tree,抽象语法树,
ast使用场景:
- 语法解析,检查
- 代码格式化,高亮,错误提示,自动补全;
- Babel -> Es6
- 代码压缩,混淆代码
- 可以编写那些具体有独特语法特征的高级框架,Vue React
graph LR
A[源代码] --> B[抽象语法树]
B --> C[遍历语法树上的各个节点]
C --> D[对语法树进行修改转换]
D --> E[新的语法树]
E --> F[根据新的语法树生成的源代码]
classDef default fill: #fff, stroke: #333, stroke-width: 4px;
分词(tokenize)
将一行行的代码,变成一个个的token,然后构建抽象语法树,所谓的token,是指在语法上不可能再分,最小的单个字符或者字符串 esprima官网 在线拆分 1+2=3
将function的驼峰命名转换成下下划线命名
需要使用到的库
- esprima : 解析器,将源代码转换成ast
- estraverse : 遍历器,用来遍历ast
- escodegen : 生成器,将ast转换成源代码
正则方法
str.replace(/([A-Z])/g, (a) => `_${a.toLowerCase()}`)
源代码
function weWantMoney() {
}
npm init -y
npm i esprima estraverse escodegen -D
// input.js
function weWantMoney() {
console.log('$$$')
}
// index.js
const esprima = require('esprima');
const estraverse = require('estraverse');
const escodegen = require('escodegen');
const fs = require('fs');
const inputSource = fs.readFileSync('./input.js', 'utf-8').toString();
// 生成ast
const astTree = esprima.parseModule(inputSource);
console.log('** print astTree **', astTree)
// 遍历ast
estraverse.tranverse(astTree, {
enter(node) {
if (node.type === 'FunctionDeclaration') {
node.id.name = node.id.name.replace(/([A-Z])/g, (a) => `_${a.toLowerCase()}`)
console.log('** enter **', node.id.name)
}
},
leave(node) {
console.log('** leave **')
}
})
// 生成源代码
const outputSource = escodegen.generate(astTree);
fs.writeFileSync('./output.js', outputSource)
console.log('** outputSource **', outputSource)
API摘要:
esprima.parseModule将源代码解析成astestraverse.tranverse遍历astenter进入节点node.type参数nodeFunctionDeclarationnode.id.name节点名称
leave离开节点
escodegen.generate
总结: 抽象语法树(AST)在代码处理中的应用
在软件开发中,抽象语法树(AST)就像是编程语言的蓝图,帮助我们深入理解代码的结构和逻辑。 AST将源代码转换为一种树状结构,每个节点代表代码中的一个语法元素,如变量、函数、表达式等。 这种结构使得我们可以像建筑师一样,精确地分析、修改和生成代码。
解析与构建
首先,esprima作为解析器,将源代码解析成AST。这类似于将一幢建筑物分解成砖块和构件,使得我们可以逐个检查和分析每个部分。例如,将源代码
function weWantMoney() { console.log('$$$') }解析为AST,我们可以清晰地看到函数声明、函数体等结构。遍历与修改
接下来,
estraverse作为遍历器,帮助我们遍历AST的每个节点。这就像在建筑工地中,逐一检查每个构件的质量和位置。 在遍历过程中,我们可以对特定类型的节点进行修改。例如,将函数名从驼峰命名转换为下划线命名。 通过正则表达式str.replace(/([A-Z])/g, (a) =>_${a.toLowerCase()}),我们可以轻松地将weWantMoney转换为we_want_money。生成与输出
最后,
escodegen作为生成器,将修改后的AST重新生成为源代码。这类似于将分解后的构件重新组装成一幢完整的建筑物。通过escodegen.generate(astTree),我们可以得到修改后的源代码function we_want_money() { console.log('$$$')},并将其保存到文件中。实际应用
这种技术不仅适用于简单的语法转换,还能用于复杂的代码优化和框架开发。 例如,Babel通过
AST将ES6代码转换为ES5代码,确保代码在旧版浏览器中的兼容性。 Vue和React等高级框架也利用AST来解析和生成模板代码,提升开发效率和代码质量。 通过AST,我们可以像外科医生一样精确地操作代码,确保每个部分都符合预期。这种强大的工具不仅提升了代码的可读性和一致性,还为自动化代码重构和优化提供了坚实的基础