前言
这个系列是关于CodeWars上的一条1Kyu题:Simple Interactive Interpreter。也就是实现一个简单的交互式解释器。
题目地址:http://www.codewars.com/kata/52ffcfa4aff455b3c2000750/train/javascript
github地址:https://github.com/woodensail/SimpleInteractiveInterpreter
本文地址:http://segmentfault.com/a/1190000004044789
补充
11月26日更新:
增加了对左结合运算符的支持。
增加了变量统计功能,用于支持下一步的函数parser
当表达式不符合语法要求时,抛出异常
实现要求
具体的细节可以参见上面的原题网站,大概的要求如下:
1:支持变量赋值语句
x = 7
2:支持四则运算,表达式中可以使用变量
x = (1 + 2) * y
3:函数声明:
fn add x y => x + y
4:函数调用
z = add a b
5:其他
也就是命名冲突检测,作用域链等,大家自己看吧。
语法树
这一章主要是完成语法树的生成。其中由于函数声明部分过于简单,没必要生成语法树,打算留到下一章一起处理。所以只做了表达式的语法树生成。
首先,题目所给的语言结构基本上是前缀表达式和中缀表达式的混杂。所以只需要将语句里面中缀的部分转化为前缀即可得到波兰式。
当然,我为了方便下一步处理还是选择将其进一步转化为语法树的结构。但是实现思路依旧可以参考波兰式生成。
准备工作
var SPACE = {}, params = [], operatorStack = [], dataStack = [SPACE], expressionFlag = true, lValue, rValue, operator, vars = {};
声明变量:
params 用于存储函数调用的参数,其实这里不需要初始化,但我懒得改了。
operatorStack 运算符栈,用于存储各种操作符
dataStack 存储数据。包括数值,变量以及语法树的节点
expressionFlag 由于改语言中没有逗号,所以没有显式的标志来分割相邻的两个表达式。因此需要自行判断前一个表达式是否结束。
lValue,rValue 类似params, 只不过是给运算符用的,其实可以去掉,但我懒得改。
operator 一个用于存储当前运算符的临时变量
tokens = tokens.slice();
tokens.push(')');
tokens.unshift('(');
while (tokens.length) {
……
}
var varList = [];
for (va