private RpnItem getToken() { if (!moveToNextNonWhiteSpace()) { return(null); } var opInxex = RpnItemOperator.OpIndex(Expression, _i); if (opInxex >= 0) { _i += RpnItemOperator.Operators[opInxex].Length; return(new RpnItemOperator((Operator)opInxex)); } var m = _legalOperand.Matches(Expression.Substring(_i)); if (m.Count == 1) { var x = m[0].Value; _i += x.Length; double num; if (double.TryParse(x, out num)) { return(new RpnItemOperandNumeric(num)); } if (!moveToNextNonWhiteSpace() || Expression[_i] != '(') { return(x != "null" ? (RpnItem) new RpnItemOperandVariable(x) : new RpnItemOperandString(null)); } _i++; return(new RpnItemFunction(x)); } switch (Expression[_i++]) { case '\"': case '\'': return(getString(Expression[_i - 1])); } return(null); }
private void handleItemOperator(RpnItemOperator op) { switch (op.Operator) { case Operator.Comma: while (!(_stack.Peek() is RpnItemFunction)) { Result.Add(_stack.Pop()); } ((RpnItemFunction)_stack.Peek()).ArgumentCount++; return; case Operator.LeftP: _stack.Push(op); return; case Operator.RightP: while (true) { var pop = _stack.Pop(); if (pop is RpnItemFunction) { Result.Add(pop); return; } if ((pop as RpnItemOperator)?.Operator == Operator.LeftP) { return; } Result.Add(pop); } } while (_stack.Any() && op.ShuntIt(_stack.Peek() as RpnItemOperator)) { Result.Add(_stack.Pop()); } _stack.Push(op); }
public Rpn(string expression) { Expression = expression; var expectedOperand = true; while (_i < Expression.Length) { var token = getToken(); if (token == null) { if (_i >= Expression.Length) { break; } else { throw new Exception(); } } if (token is RpnItemOperand && expectedOperand) { Result.Add(token); expectedOperand = false; } else if (token is RpnItemFunction && expectedOperand) { _stack.Push(token); } else if (token is RpnItemOperator) { var op = (RpnItemOperator)token; if (expectedOperand) { switch (op.Operator) { case Operator.LeftP: case Operator.Not: break; case Operator.Minus: op = new RpnItemOperator(Operator.Negation); break; case Operator.Addition: continue; default: throw new Exception($"Expected operand but found operator {op.Operator}"); } } expectedOperand = op.Operator != Operator.RightP; handleItemOperator(op); } } while (_stack.Any()) { var item = _stack.Pop(); if ((item as RpnItemOperator)?.Operator == Operator.LeftP) { throw new Exception("Open parenthisis"); } Result.Add(item); } for (var i = 1; i < Result.Count; i++) { if (Result[i - 1] is RpnItemOperandNumeric && (Result[i] as RpnItemOperator)?.Operator == Operator.Negation) { Result[i - 1] = new RpnItemOperandNumeric(-((RpnItemOperandNumeric)Result[i - 1]).Value); Result.RemoveAt(i--); } } }
private void typeEval() { var stack = new Stack <RpnItemOperand>(); for (var i = 0; i < _original.Count; i++) { var item = _original[i]; var operand = item as RpnItemOperand; if (operand != null) { stack.Push(operand); continue; } var variable = item as RpnIndexedVariable; if (variable != null) { stack.Push(variable.IsNumeric ? (RpnItemOperand) new RpnItemOperandNumeric(0) : new RpnItemOperandString("")); continue; } var itemOperator = item as RpnItemOperator; if (itemOperator != null) { switch (itemOperator.Operator) { case Operator.Addition: { var op2 = stack.Pop(); var op1 = stack.Pop(); if (op1 is RpnItemOperandString || op2 is RpnItemOperandString) { _original[i] = new RpnItemOperator(Operator.Concat); push(stack, ""); } else { push(stack, 0); } break; } case Operator.Negation: case Operator.Not: stack.Pop(); stack.Push(new RpnItemOperandNumeric(0)); break; case Operator.NullCoalescing: case Operator.Question: { var op2 = stack.Pop(); stack.Pop(); stack.Push(op2); break; } default: stack.Pop(); stack.Pop(); push(stack, 0); break; } continue; } var itemFunction = item as RpnItemFunction; if (itemFunction != null) { for (var j = 0; j < itemFunction.ArgumentCount; j++) { stack.Pop(); } if (_functions[itemFunction.Name].Type == typeof(string)) { push(stack, ""); } else { push(stack, 0); } continue; } throw new Exception("What the hell happened here?"); } ResultingType = stack.Single(); }