static void applyOperator(OpToken t, ref Stack <NumToken> nums) { if (t.type == OpType.LP || t.type == OpType.RP) { Console.WriteLine("Parenthesis mismatch"); return; } try { double op2 = nums.Pop().value; double op1 = nums.Pop().value; switch (t.type) { //last param of NumToken doesn't matter for any of them because they are not parsed from the string case OpType.ADD: nums.Push(new NumToken(op1 + op2, -1)); break; case OpType.SUB: nums.Push(new NumToken(op1 - op2, -1)); break; case OpType.MUL: nums.Push(new NumToken(op1 * op2, -1)); break; case OpType.DIV: nums.Push(new NumToken(op1 / op2, -1)); break; case OpType.EXP: nums.Push(new NumToken(Math.Pow(op1, op2), -1)); break; case OpType.MOD: nums.Push(new NumToken(op1 % op2, -1)); break; case OpType.LSHIFT: nums.Push(new NumToken((int)op1 << (int)op2, -1)); break; case OpType.RSHIFT: nums.Push(new NumToken((int)op1 >> (int)op2, -1)); break; } } catch (Exception) { Console.WriteLine("Encountered exception, please check your syntax"); } }
static void Main(string[] args) { Console.WriteLine("Input an expression. Note that _ is the negative sign. Use of >> << is rounded."); string exp = Console.ReadLine(); exp = exp.Replace(" ", ""); //strip spaces Stack <NumToken> nums = new Stack <NumToken>(); //number stack Stack <OpToken> ops = new Stack <OpToken>(); //operator stack for (int i = 0; i < exp.Length;) //increments of i will be determined based off whether it is a number or an operator { Token k = null; try { k = getNextToken(exp, i); } catch (Exception) { Console.WriteLine("Error parsing token."); break; } if (k is NumToken) { NumToken nt = (NumToken)k; nums.Push(nt); i += nt.length; } else if (k is OpToken) { OpToken x = (OpToken)k; OpToken y = ops.Count > 0 ? ops.Peek() : null; if (y == null || x.type == OpType.LP) //if stack has nothing in it yet, or if the token is a (, push it on stack, no evaluation { ops.Push(x); } else { if (x.type == OpType.RP) //if the current token is a ), unwind the stack until a ( is encountered { OpToken alpha = null; while ((alpha = ops.Pop()).type != OpType.LP) { applyOperator(alpha, ref nums); } } else { //apply operator if the current token is <= in precedence than the one on the top of the stack (< if right associative) //parenthesis must be the smallest number so no other token will cause it to be applied while ((x.leftasso && x.precedence <= y.precedence) || (!x.leftasso && x.precedence < y.precedence)) { ops.Pop(); //pop y off, we're applying it applyOperator(y, ref nums); if (ops.Count == 0) { break; } y = ops.Peek(); //look at the next operator on stack in case it can be applied as well } ops.Push(x); } } i += x.length; } } //unwind remaining operators while (ops.Count > 0) { OpToken y = ops.Pop(); applyOperator(y, ref nums); } if (nums.Count > 0) { Console.WriteLine(exp + " = " + nums.Pop().value); } else { Console.WriteLine("No result."); } Console.WriteLine("Press any key to exit."); Console.ReadKey(false); }
static void applyOperator(OpToken t, ref Stack<NumToken> nums) { if (t.type == OpType.LP || t.type == OpType.RP) { Console.WriteLine("Parenthesis mismatch"); return; } try { double op2 = nums.Pop().value; double op1 = nums.Pop().value; switch (t.type) { //last param of NumToken doesn't matter for any of them because they are not parsed from the string case OpType.ADD: nums.Push(new NumToken(op1 + op2, -1)); break; case OpType.SUB: nums.Push(new NumToken(op1 - op2, -1)); break; case OpType.MUL: nums.Push(new NumToken(op1 * op2, -1)); break; case OpType.DIV: nums.Push(new NumToken(op1 / op2, -1)); break; case OpType.EXP: nums.Push(new NumToken(Math.Pow(op1, op2), -1)); break; case OpType.MOD: nums.Push(new NumToken(op1 % op2, -1)); break; case OpType.LSHIFT: nums.Push(new NumToken((int)op1 << (int)op2, -1)); break; case OpType.RSHIFT: nums.Push(new NumToken((int)op1 >> (int)op2, -1)); break; } } catch (Exception) { Console.WriteLine("Encountered exception, please check your syntax"); } }