为了完成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
本站文章未经文下加注授权不得拷贝发布。