最近在学编译原理,讲完了递归下降法,老师就布置了一个作业,使用递归下降法实现一个简易计算器。
需求:实现简单的四则运算功能,有简单界面
实现:制作一个网页版的简单计算器用于输入输出
工具:webstorm,浏览器:谷歌(没做兼容,就别太老版本就行)
过程分析:
首先还是来复习一下递归下降法吧;
递归下降法是一种简单的将自顶向下分析算法,他的概念非常简单:讲一个非终结符A的文法规则看作将识别A的一个过程定义,A的文法规则的右边指出这个过程的代码结构:一个选择中的终结符与非终结符序列与相匹配的输入以及其他过程的调用相对应,而选择与在代码中的替代情况(case语句和if语句)相对应。
emm,这一段可以说非常的抽象了。不管他,接下来我们看看这个过程具体是怎么操作的,看完之后,再回过头看看这个定义就会清晰很多。
为了消除左递归和回溯,我们使用更加适合递归下降法的EBNF(扩展的巴科斯范式)来改写我们的文法规则。
最后我们得到的文法规则就是:
接下来我们就用代码来实现它:
//这里的token比较简单,但是我还是写了一个简单的词法分析扫描器
const digitArray = ['0','1','2','3','4','5','6','7','8','9'];
//判断是否是数字
function isDigit(x) {
return digitArray.indexOf(x)!==-1
}
//简单的词法分析,获得token;
function getToken(str){
var nextIndex=0;
var prevIndex=0;
var len = str.length;
var state2 = 1;
var tokens = [];
for (nextIndex=0;nextIndex<len;){
while( (state2 === 1 ||state2 === 2)&&(nextIndex<=len) ){
switch (state2){
case 1:
prevIndex = nextIndex;
if( isDigit(str.charAt(nextIndex)) ){
nextIndex += 1;2
state2 = 2;
}else{
nextIndex += 1;
state2 = 4;
}
break;
case 2:
if( isDigit(str.charAt(nextIndex)) ){
nextIndex += 1;
state2 = 2;
}else{
nextIndex += 1;
state2 = 3;
}
break;
}
}
if(state2 === 3){
nextIndex = nextIn