文章目录
前言
前些年的不计其数的插件诞生。我们归纳一下有:javascript转译、代码压缩、css预处理器、elint、pretiier,等。有很多js模块我们不会在生产环境用到,但是它们在我们的开发过程中充当着重要的角色。所有的上述工具,不管怎样,都建立在了AST这个巨人的肩膀上。
提示:以下是本篇文章正文内容,下面案例可供参考
一、AST是什么?
什么是AST(抽象语法树)?
It is a hierarchical program representation that presents source code structure according to the grammar of a programming language, each AST node corresponds to an item of a source code.
AST是怎么生成的?
第一步,词法分析,也叫做扫描scanner。它读取我们的代码,然后把它们按照预定的规则合并成一个个的标识tokens。同时,它会移除空白符,注释,等。最后,整个代码将被分割进一个tokens列表(或者说一维数组)。
第二步,语法分析,也解析器。它会将词法分析出来的数组转化成树形的表达形式。同时,验证语法,语法如果有错的话,抛出语法错误。当生成树的时候,解析器会删除一些没必要的标识tokens(比如不完整的括号),因此AST不是100%与源码匹配的,但是已经能让我们知道如何处理了。说个题外话,解析器100%覆盖所有代码结构生成树叫做CST(具体语法树)。
二、github一个AST生成器的案例
1.主要流程
通过tokenizer进行词法分析,形成token列表,再将token进行分解,变成了AST树型结构,再将AST通过transformer转换成一个newAst,最后将newAst通过生成器变成了最后的output。
* 1. input => tokenizer => tokens
* 2. tokens => parser => ast
* 3. ast => transformer => newAst
* 4. newAst => generator => output
let tokens = tokenizer(input);
let ast = parser(tokens);
let newAst = transformer(ast);
let output = codeGenerator(newAst);
2.tokenizer的实现
tokenizer适用于将输入解析成一个一个token(标识),包括type和value的属性,可以称为词法分析,最后返回一个token数组。
function tokenizer(input) {
//current指向现在需要分析的字符
let current = 0;
let tokens = [];
//while循环控制在current循环中
while (current < input.length) {
//用char变量保存当前的字符
let char = input[current];
//先判断括号开闭,之后会在callfunction类型中用到
if (char === '(') {
tokens.push({
type: 'paren',//将类型值设置为括号
value: '(',
});
current++;
continue;
}
if (char === ')') {
tokens.push({
type: 'paren',
value: ')',
});
current++;
continue;
}
//检查空格,用正则判断是否出现空格,如果是则跳过
let WHITESPACE = /\s/;
if (WHITESPACE.test(char)) {
current++;
continue;
}
//检查数字,用正则判断是不是0~9之间的数字
let NUMBERS = /[0-9]/;
if (<