private void HandleConditional(PolishNotation element) { EnsureStackHeadNotIdentifier(); decimal operand1 = Convert.ToDecimal(_stack.Pop()); EnsureStackHeadNotIdentifier(); decimal operand2 = Convert.ToDecimal(_stack.Pop()); bool result; switch (element.Token) { case "equals": result = decimal.Equals(operand2, operand1); break; case "greaterthn": result = operand2 > operand1; break; case "lessthn": result = operand2 < operand1; break; default: throw new ArgumentOutOfRangeException(nameof(element.Token), element.Token, "Unknown conditional operator"); } _stack.Push(result.ToString()); }
private void button1_Click(object sender, EventArgs e) { notation = new PolishNotation(txtExpresion.Text); notation.generateTree(); preOrder = notation.getPreOrder(); lblPreOrder.Text = "PreOrder: " + preOrder; lblPostOrder.Text = notation.getPostOrder(); lblInOrder.Text = notation.getInOrder(); }
public void AnswerClick() { PolishNotation ob = new PolishNotation(); string polska = ob.Transform(inPut.text); polish.text = polska; Calculator ob2 = new Calculator(); int res = ob2.Result(polska); answer.text = res.ToString(); }
private void HandleArithmeticUnary(PolishNotation element) { if (element.Token == "@+") { return; } // "-" EnsureStackHeadNotIdentifier(); decimal operand1 = Convert.ToDecimal(_stack.Pop()); _stack.Push((-operand1).ToString(CultureInfo.InvariantCulture)); }
private void AddOperatorToStack(string @operator) { // Відкриваюча дужка "(" повинна мати найнижчий пріоритет, але записуватися в стек, нічого не виштовхуючи if (@operator == "(") { Stack.Push(new PolishNotation { Token = @operator, Type = PolishNotationTokenType.Operator }); return; } // 3. Якщо стек порожній, то поточна операція заноситься в стек if (Stack.Count == 0) { Stack.Push(new PolishNotation { Token = @operator, Type = PolishNotationTokenType.Operator }); return; } PolishNotation head = Stack.Peek(); string headToken = head.Token.StartsWith("if") ? "if" : head.Token.StartsWith("while") ? "while" : head.Token; // 2. Якщо пріоритет операції, що знаходиться в стеку, // не менший за пріоритет поточної вхідної операції, // то операція зі стека подається на вихід і п.2 повторюється, if (_operatorsPriorities[headToken] >= _operatorsPriorities[@operator]) { PolishNotation notation = Stack.Pop(); if (notation.Token != "(") // Причому "(" ніколи не передається на вихід { ReversePolishNotation.Add(notation); // операція зі стека подається на вихід } AddOperatorToStack(@operator); // п.2 повторюється return; } // інакше поточна операція заноситься в стек. if (@operator != ")") // Причому ")" ніколи не заноситься в стек { Stack.Push(new PolishNotation { Token = @operator, Type = PolishNotationTokenType.Operator }); } }
private String change(List <String> symbols, String idName, String conValue) { String result = builder.findAndChange(symbols); if (!result.Equals(" ")) { if (compare(symbols, new Sentence("", "@выражение + @терм1").Tail)) { PolishNotation.Add(new PolishNotationElement("+", true)); } else if (compare(symbols, new Sentence("", "@выражение - @терм1").Tail)) { PolishNotation.Add(new PolishNotationElement("-", true)); } else if (compare(symbols, new Sentence("", "@терм * @множитель").Tail)) { PolishNotation.Add(new PolishNotationElement("*", true)); } else if (compare(symbols, new Sentence("", "@терм / @множитель").Tail)) { PolishNotation.Add(new PolishNotationElement("/", true)); } else if (compare(symbols, new Sentence("", "- @терм1").Tail)) { PolishNotation.Add(new PolishNotationElement("@", true)); } else if (compare(symbols, new Sentence("", "id").Tail)) { PolishNotation.Add(new PolishNotationElement(idName, false, true)); } else if (compare(symbols, new Sentence("", "const").Tail)) { PolishNotation.Add(new PolishNotationElement(conValue, false, false)); } } return(result); }
private void HandleArithmeticBinary(PolishNotation element) { EnsureStackHeadNotIdentifier(); decimal operand1 = Convert.ToDecimal(_stack.Pop()); EnsureStackHeadNotIdentifier(); decimal operand2 = Convert.ToDecimal(_stack.Pop()); decimal result; switch (element.Token) { case "+": result = operand2 + operand1; break; case "-": result = operand2 - operand1; break; case "*": result = operand2 * operand1; break; case "/": if (operand1 == 0) { throw new RuntimeException("Division by 0"); } result = operand2 / operand1; break; default: throw new ArgumentOutOfRangeException(nameof(element.Token), element.Token, "Unknown binary arithmetic operator"); } _stack.Push(result.ToString(CultureInfo.InvariantCulture)); }
public void PolishNotationTests(string str, double expected) { Assert.AreEqual(PolishNotation.Calc(str), expected); }
public ExecutionResult Run( PolishResult polishResult, ExecutionPoint executionPoint = default, decimal input = default) { var outputBuilder = new StringBuilder(); _stack.Clear(); _declaredIdentifiers.Clear(); _identifiersValues.Clear(); int i = 0; if (executionPoint != default) { _stack = executionPoint.Stack; _declaredIdentifiers = executionPoint.DeclaredIdentifiers; _identifiersValues = executionPoint.IdentifiersValues; i = executionPoint.PolishNotationIndex; _stack.Push(input.ToString(CultureInfo.InvariantCulture)); HandleSet(); } try { while (i < polishResult.ReversePolishNotation.Count) { PolishNotation element = polishResult.ReversePolishNotation[i]; switch (element.Type) { case PolishNotationTokenType.Identifier: _stack.Push(_identifiersValues.ContainsKey(element.Token) && !element.IsAssignmentToThisIdentifier ? _identifiersValues[element.Token].ToString(CultureInfo.InvariantCulture) : element.Token); // only for declaration or assignment break; case PolishNotationTokenType.Literal: _stack.Push(element.Token); break; case PolishNotationTokenType.Operator: switch (element.Token) { case "@+": case "@-": HandleArithmeticUnary(element); break; case "+": case "-": case "*": case "/": HandleArithmeticBinary(element); break; case "var": HandleVar(); break; case "set": HandleSet(); break; case "write": string head = _stack.Pop(); if (head.StartsWith("@")) { throw new RuntimeException($"{head} is not declared"); } outputBuilder.AppendLine(head.ToString(CultureInfo.InvariantCulture)); break; case "read": return(new ExecutionResult { Type = ExecutionResultType.InputRequired, Output = outputBuilder.ToString(), ExecutionPoint = new ExecutionPoint { PolishNotationIndex = i + 1, Stack = _stack, DeclaredIdentifiers = _declaredIdentifiers, IdentifiersValues = _identifiersValues, PolishResult = polishResult } }); case "equals": case "greaterthn": case "lessthn": HandleConditional(element); break; } break; case PolishNotationTokenType.Delimiter: break; case PolishNotationTokenType.If: break; case PolishNotationTokenType.Then: break; case PolishNotationTokenType.Fi: break; case PolishNotationTokenType.While: break; case PolishNotationTokenType.TechnicalDo: break; case PolishNotationTokenType.Enddo: break; case PolishNotationTokenType.Label: PolishNotation nextElement = polishResult.ReversePolishNotation[i + 1]; switch (nextElement.Token) { case "УПХ": bool operand = Convert.ToBoolean(_stack.Pop()); if (!operand) { i = polishResult.LabelAddresses[element.Token]; continue; } break; case "БП": i = polishResult.LabelAddresses[element.Token]; continue; } break; default: throw new ArgumentOutOfRangeException(); } i++; } } catch (RuntimeException e) { outputBuilder.AppendLine(e.Message); } return(new ExecutionResult { Type = ExecutionResultType.Completed, Output = outputBuilder.ToString() }); }
private void DijkstraStep(string input, PolishNotationTokenType type, bool isAssignmentToThisIdentifier = false) { switch (type) { // 1. Ідентифікатори та константи проходять від входу прямо до виходу case PolishNotationTokenType.Identifier: case PolishNotationTokenType.Literal: ReversePolishNotation.Add(new PolishNotation { Token = input, Type = type, IsAssignmentToThisIdentifier = isAssignmentToThisIdentifier }); break; // Операції звичайно потрапляють на вихід через магазин case PolishNotationTokenType.Operator: AddOperatorToStack(input); break; // 4. Якщо вхідний ланцюжок порожній, всі операції зі стека по черзі передаються на вихід // за ознакою кінця виразу (наприклад, ";"). case PolishNotationTokenType.Delimiter: { while (Stack.Count != 0 && !Stack.Peek().Token.StartsWith("if") && !Stack.Peek().Token.StartsWith("while")) { ReversePolishNotation.Add(Stack.Pop()); } // ReversePolishNotation.Add(new PolishNotation {Token = input, Type = type}); } break; case PolishNotationTokenType.If: Stack.Push(new PolishNotation { Token = input, Type = type }); break; // Символ then з пріоритетом 1 виштовхує зі стека всі знаки до першого // if виключно. При цьому генерується нова мітка mi й у вихідний рядок // заноситься mi УПХ. Потім мітка mi заноситься в таблицю міток і дописується у вершину стека, // таким чином, запис if у вершині стека перетворюється на запис if mi case PolishNotationTokenType.Then: { PolishNotation head = Stack.Peek(); while (!head.Token.StartsWith("if")) { ReversePolishNotation.Add(Stack.Pop()); head = Stack.Peek(); } string label = GenerateLabel(); head.Token = $"{head.Token} {label}"; ReversePolishNotation.Add(new PolishNotation { Token = $"{label}", Type = PolishNotationTokenType.Label }); ReversePolishNotation.Add(new PolishNotation { Token = "УПХ", Type = type }); } break; // Символ кінця умовного оператора (наприклад, ; або end) виштовхує зі // стека все до найближчого if. Це може бути if mi mi+1 (або if mi у разі // конструкції if <вираз> then <оператор>;). Запис видаляється зі стека, // а у вихідний рядок додається mi+1: (або mi: у випадку неповного оператора умовного переходу). case PolishNotationTokenType.Fi: { PolishNotation head = Stack.Peek(); while (!head.Token.StartsWith("if")) { ReversePolishNotation.Add(Stack.Pop()); head = Stack.Peek(); } head = Stack.Pop(); string label = head.Token.Split(" ").Last(); ReversePolishNotation.Add(new PolishNotation { Token = $"{label}", Type = PolishNotationTokenType.Label }); ReversePolishNotation.Add(new PolishNotation { Token = ":", Type = type }); _labelAddresses[label] = ReversePolishNotation.Count; } break; case PolishNotationTokenType.While: { string label = GenerateLabel(); Stack.Push(new PolishNotation { Token = $"{input} {label}", Type = type }); ReversePolishNotation.Add(new PolishNotation { Token = $"{label}", Type = PolishNotationTokenType.Label }); ReversePolishNotation.Add(new PolishNotation { Token = $":", Type = type }); _labelAddresses[label] = ReversePolishNotation.Count; } break; case PolishNotationTokenType.TechnicalDo: { PolishNotation head = Stack.Peek(); while (!head.Token.StartsWith("while")) { ReversePolishNotation.Add(Stack.Pop()); head = Stack.Peek(); } string label = GenerateLabel(); head.Token = $"{head.Token} {label}"; ReversePolishNotation.Add(new PolishNotation { Token = $"{label}", Type = PolishNotationTokenType.Label }); ReversePolishNotation.Add(new PolishNotation { Token = "УПХ", Type = type }); } break; case PolishNotationTokenType.Enddo: { PolishNotation head = Stack.Peek(); while (!head.Token.StartsWith("while")) { ReversePolishNotation.Add(Stack.Pop()); head = Stack.Peek(); } head = Stack.Pop(); string[] labels = head.Token.Split(" "); ReversePolishNotation.Add(new PolishNotation { Token = $"{labels[1]}", Type = PolishNotationTokenType.Label }); ReversePolishNotation.Add(new PolishNotation { Token = "БП", Type = type }); ReversePolishNotation.Add(new PolishNotation { Token = $"{labels.Last()}", Type = PolishNotationTokenType.Label }); ReversePolishNotation.Add(new PolishNotation { Token = $":", Type = type }); _labelAddresses[labels.Last()] = ReversePolishNotation.Count; } break; default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } Trace.Add(new PolishTrace { Input = input, // Stack = new Stack<PolishNotation>(Stack), Stack = Stack.Clone(), ReversePolishNotation = new List <PolishNotation>(ReversePolishNotation) }); MoveNext(); }