背景
过程:代码 -> 词法分析 -> 构成抽象语法树 -> 运行抽象语法树
词法分析
sum = 1 * 23 + 4 * 5
如何将里面的词缀提取出来,一般是有限状态机
比如:

当我们在遍历字符串sum = 1 * 23 + 4 * 5时,一开始我们处于状态机的初始状态,
当读取到s时,进入字符串状态
当读取到u时,保持在字符串状态
当读取到m时,保持在字符串状态
当读取到=时,将状态机的内容sum导出作为token,然后回归初始状态,然后进入操作符状态
当读取到1时,将状态机的内容=导出作为token,然后回归初始状态,然后进入数字状态
当读取到*时,token=1,进入操作符状态
当读取到2时,token=*,进入数字状态
当读取到3时,保持在数组状态
当读取到+时,token=23,进入操作符状态
当读取到4时,token=+,进入数字状态
当读取到*时,token=4,进入操作符状态
当读取到5时,token=*,进入数字状态
当读取到结束符时,token=5\
所以词缀获取:[sum,=,1,*,23,+,4,*,5]
问题:js的关键字和字符串状态似乎冲突了,比如let它该被解析成字符串还是关键字?
解决方法:给关键字赋予状态,比如let的状态,对于let sum = 1 * 23 + 4 * 5

在初始状态读取到l时,并不会进入字符串状态,而是let状态-l
继续读取到e时,进入let状态-le
继续读取到t时,进入let状态-let
如果继续读到字符的话,会进入字符串状态
这样就能实现关键字了。
逆波兰表达式,也叫后缀表达式
比如let sum = 1 * 23 + 4 * 5,操作符在操作数之间的表达方式是中缀表达式,而我们需要将它转化成后缀表达式:sum let 1 23 * 4 5 * + =
理论上,该表达式的操作符应该只有数字和+-*/,但是我们会更加的广义,即需要有操作对象的符号都能被称作操作符,比如let需要一个变量名,那它就能被当做操作符,而这个变量名就是操作数
所以词缀集合[let,sum,=,1,*,23,+,4,*,5]中的
操作符:let,=,*,+,*
操作数:sum,1,23,4,5
首先,我们需要一个栈放操作符,从左到右读取[let,sum,=,1,*,23,+,4,*,5],使用rsl储存结果\
读取到let,是操作符,压入栈中
读取到sum,是操作数,rsl=sum,栈顶是单元操作符let,操作符出栈,rsl=sum let
读取到=, 是操作符,压入栈中
读取到1, 是操作数,rsl = sum let 1
读取到*, 是操作符,优先级比栈顶元素=高,*压入栈中
读取到23, 是操作数,rsl = sum let 1 23,
读取到+, 是操作符,优先级比栈顶*低,栈顶*出栈,+压入栈中,rsl = sum let 1 23 *
读取到4, 是操作数,rsl = sum let 1 23 * 4
读取到*, 是操作符,优先级比栈顶+高,*压入栈中
读取到5, 是操作数,rsl = sum let 1 23 * 4 5
读取到结束符,栈内元素出栈,rsl = sum let 1 23 * 4 5 * + =
rsl就是后缀表达式
构造抽象语法树
对于后缀表达式:sum let 1 23 * 4 5 * + =
生成的抽象语法树如下:
{
"type": "Program",
"body": [{
"type": "VariableDeclaration",
"declarations": [{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "sum"
},
"init": {
"type": "BinaryExpression",
"left": {
"type": "BinaryExpression",
"left": {
"type": "Literal",
"value": 1,
"raw": "1"
},
"operator": "*",
"right": {
"type": "Literal",
"value": 23,
"raw": "23"
}
},
"operator": "+",
"right": {
"type": "BinaryExpression",
"left": {
"type": "Literal",
"value": 4,
"raw": "4"
},
"operator": "*",
"right": {
"type": "Literal",
"value": 5,
"raw": "5"
}
}
}
}],
"kind": "let"
}],
"sourceType": "module"
}
生成过程:从右往左读取
读取=,是双元操作符
读取+,是双元操作符,其本身作为=的右操作数
读取*,是双元操作符,其本身作为+的右操作数
读取5,是字面量,其本身作为*的右操作数
读取4,是字面量,其本身作为*的做操作数
读取*,是双元操作符,其本身作为+的左操作数
读取23,是字面量,其本身作为+的右操作数
读取1,是字面量,其本身作为+的左操作数
读取let,是关键字,也是单元操作符,其本身作为=的左操作数
读取sum,是字符串,其本身作为let的操作数
PS
字典树是一种很好的实现字符串型有限状态机的数据结构