Skip to content

Instantly share code, notes, and snippets.

@ikasoba
Last active February 7, 2022 14:41
Show Gist options
  • Save ikasoba/7aee6109f37482d1bd91820a237dedfb to your computer and use it in GitHub Desktop.
Save ikasoba/7aee6109f37482d1bd91820a237dedfb to your computer and use it in GitHub Desktop.
順序なし、整数のみの計算式の文字列を実行します(evalの計算だけ版のようなもの)。実数はフリーズします
const calc=((raw)=>{
let s=[]
const sw = (addIndex,v,f)=>new class {
cases=new Map();
def=null;
c(v,f){
this.cases.set(v,f)
return this
}
d(f){
this.def=f
return this
}
eval(_f=()=>{}){
_f(this,v)
for (const [k,f] of this.cases.entries()){
let r;
if ((typeof k == "string" && v.startsWith(k)) || (k instanceof RegExp && (r=v.match(k)))){
addIndex(k.length!=null ? k.length : r[0]?.length)
return f(r)
}
}
if (this.def)return this.def()
}
}().eval(f);
for (let i=0;i<raw.length;){
const t=sw((v)=>i+=v,raw.slice(i),(s)=>
s.c(/^[0-9]+/,(v)=>parseInt(v[0])).c(/^[+\-*/]/,(v)=>v[0])
)
if (t)s.push(t)
}
let stack=[]
for (let i=0;i<s.length;i++){
if (typeof s[i] == "number")stack.push(s[i]);
if (s[i]=="*")stack.push(stack.pop()*s[i+=1]);
else if (s[i]=="/")stack.push(stack.pop()/s[i+=1]);
else if (s[i]=="+")stack.push(stack.pop()+s[i+=1]);
else if (s[i]=="-")stack.push(stack.pop()-s[i+=1]);
}
return stack.pop()
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment