[Javascript]算数表达式计算

为了完成java的作业,先拿js写了一个。暂时只完成了一些简单的运算

效果:

expression.calcExpression('1%+1');//1.01
expression.calcExpression('.1%+1');//1.001
expression.calcExpression('(5-2)%/0');//Infinity
expression.calcExpression('(4+3)(4-3)');//7
expression.calcExpression('3(4+5)');//27
expression.calcExpression('-3(4+5)');//-27

 

/*
Copyright luojia@luojia.me (https://luojia.me)
*/

class expression{
	static throwError(index){
		throw(`expression error @${index}`);
	}
	static compItem(value,index){
		return [value,index];
	}
	static isNumber(item){
		return typeof item[0]==='number';
	}
	static calcExpression(exp){
		let rawcomps=[],
			comps=[];

		let signs=new RegExp(/[\(\)\-\+\*\/\%]/y),
			space=new RegExp(/\s+/y),
			number=new RegExp(/(\d+\.*\d*)|(\.\d+)/y);

		let lastIndex=0,match;
		do{
			if(((space.lastIndex=lastIndex),true)&&(match=space.exec(exp))){//spaces
				rawcomps.push(match[0]);
				lastIndex=space.lastIndex;
			}else if(((signs.lastIndex=lastIndex),true)&&(match=signs.exec(exp))){//signs
				rawcomps.push(match[0]);
				comps.push(expression.compItem(match[0],match.index));
				if(match[0]==='('){
					if(comps.length>1){
						let last=comps[comps.length-2][0];
						if(last===')'|| expression.isNumber(comps[comps.length-2])){
							comps.splice(comps.length-1,0,expression.compItem('*',-1));
						}
					}
				}
				lastIndex=signs.lastIndex;
			}else if(((number.lastIndex=lastIndex),true)&&(match=number.exec(exp))){//number
				rawcomps.push(match[0]);
				if(match[0][0]==='.')match[0]='0'+match[0];//添加0
				comps.push(expression.compItem(Number(match[0]),match.index));
				lastIndex=number.lastIndex;
			}else{
				expression.throwError(lastIndex);
			}
		}while(lastIndex!==exp.length);
		return expression.expressionParser(comps)[0];
	}
	static expressionParser(comps){//return a compItem
		let groupStack=[],lastWasNumber=false;
		for(let i=0;i<comps.length;i++){//()
			if(expression.isNumber(comps[i])){
				if(lastWasNumber)expression.throwError(comps[i][1]);
				lastWasNumber=true;
				continue;
			}
			lastWasNumber=false;
			if(comps[i][0]==='('){
				groupStack.push(i);
			}else if(comps[i][0]===')'){
				if(groupStack.length===0)
					expression.throwError(comps[i][1]);
				else if(groupStack.length===1){//use a new parser
					let newgroup=comps.splice(groupStack[0],i-groupStack[0]+1);
					newgroup.pop();newgroup.shift();
					comps.splice(groupStack[0],0,expression.expressionParser(newgroup));
					i=groupStack[0];
				}
				groupStack.pop();
			}
		}
		if(groupStack.length)expression.throwError(comps[groupStack[groupStack.length-1]][1]);

		for(let i=0;i<comps.length;i++){// n%
			if(expression.isNumber(comps[i])){continue;}
			let exp=comps[i][0];
			if(exp==='%'){
				if(!comps[i-1] || !expression.isNumber(comps[i-1]))expression.throwError(comps[i][1]);
				comps.splice(i-1,2,expression.compItem(comps[i-1][0]/100,comps[i-1][1]));
				i--;
			}
		}
		for(let i=0;i<comps.length;i++){// * /
			if(expression.isNumber(comps[i])){continue;}
			let exp=comps[i][0];
			if(exp==='*'||exp==='/'){
				if(i===comps.length || !comps[i-1] || !expression.isNumber(comps[i-1]) || !expression.isNumber(comps[i+1]))
					expression.throwError(comps[i][1]);
				//calc
				let result;
				if(exp==='*'){
					result=comps[i-1][0]*comps[i+1][0];
				}else{
					result=comps[i-1][0]/comps[i+1][0];
				}
				comps.splice(i-1,3,expression.compItem(result,comps[i-1][1]));
				i--;
			}
		}
		for(let i=0;i<comps.length;i++){// + -
			if(expression.isNumber(comps[i])){continue;}
			let exp=comps[i][0];
			if(exp==='+'||exp==='-'){
				if(i===comps.length || !expression.isNumber(comps[i+1]))
					expression.throwError(comps[i][1]);
				if(i===0||!expression.isNumber(comps[i-1])){//当做正负符号
					if(exp==='-')comps[i+1][0]=-comps[i+1][0];
					comps.splice(i,1);
					i--;
				}else{//计算表达式
					let result;
					if(exp==='+'){
						result=comps[i-1][0]+comps[i+1][0];
					}else{
						result=comps[i-1][0]-comps[i+1][0];
					}
					comps.splice(i-1,3,expression.compItem(result,comps[i-1][1]));
					i--;
				}
			}
		}
		if(comps.length!==1){
			console.error([...comps]);
			throw('something wrong');
		}
		return comps[0];//return the value
	}
}

 



本文发布于 https://luojia.me

本站文章未经文下加注授权不得拷贝发布。

0 0 投票数
打分
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论