/// <summary> /// Parses the specified string to a sequence of cells /// that may contain a number or symbols or arithmetic operation. /// </summary> public InputCell[] Parse(string input) { var result = new LinkedList <InputCell>(); var numberBuffer = new NumberBuilder(); foreach (char ch in input) { if (ch.IsEmpty()) { continue; } if (ch.IsDigit() || ch.IsDot()) { numberBuffer.Append(ch); continue; } result.AddIfNotNull(CreateCell(numberBuffer)); if (ch.IsMinus() && IsMinusForNumber(result)) { numberBuffer.Append(ch); continue; } result.AddLast(InputCell.Symbol(ch)); } result.AddIfNotNull(CreateCell(numberBuffer)); return(result.ToArray()); }
private static void PurgeTopStack(Stack <InputCell> stack, LinkedList <InputCell> output, InputCell element) { while (stack.Count > 0 && element.Weight <= stack.Peek().Weight) { output.AddLast(stack.Pop()); } stack.Push(element); }
public static InputCell CreateCell(NumberBuilder builder) { if (builder.IsEmpty()) { return(null); } double number = builder.Build(); builder.Clear(); return(InputCell.Number(number)); }
/// <summary> /// Counts a result of expression that is represented as a sequence of input cells /// ordered according the order of the Reverse Polish notation (RPN). /// </summary> public double Count(InputCell[] input) { var stack = new Stack <InputCell>(); foreach (var cell in input) { if (cell.IsNumber()) { stack.Push(cell); } else if (cell.IsOperation()) { var operandRight = GetOperand(stack); var operandLeft = GetOperand(stack); var operation = cell.Expr(operandLeft, operandRight); var result = InvokeExpession(operation); stack.Push(InputCell.Number(result)); } } return((double)stack.Peek().Value); }
private static Expression GetOperand(Stack <InputCell> stack) { return(stack.PopOrValue(InputCell.Number(0)).Expr.Invoke(null, null)); }
private static bool IsMinusForNumber(IEnumerable <InputCell> cells) { InputCell lastCell = cells.LastOrDefault(); return(lastCell == null || lastCell.IsOperation() || lastCell.IsOpenBracket()); }