Skip to content

Commit

Permalink
add postfix notation
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexey-Sagaydak committed Apr 1, 2024
1 parent 1bef877 commit a4f77f4
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 8 deletions.
151 changes: 151 additions & 0 deletions Compiler/Models/Lab5/PolishNotationCalculator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lab5;

public class PolishNotationCalculator
{
public string infixExpr { get; private set; }
public string postfixExpr { get; private set; }

private Dictionary<char, int> operationPriority = new() {
{'(', 0},
{'+', 1},
{'-', 1},
{'*', 2},
{'/', 2},
{'^', 3},
{'~', 4}
};

public PolishNotationCalculator(string expression)
{
infixExpr = expression;
postfixExpr = ToPostfix(infixExpr + "\r");
}

private string GetStringNumber(string expr, ref int pos)
{
string strNumber = "";

for (; pos < expr.Length; pos++)
{
char num = expr[pos];

if (Char.IsDigit(num))
strNumber += num;
else
{
pos--;
break;
}
}

return strNumber;
}

private string ToPostfix(string infixExpr)
{
string postfixExpr = "";
Stack<char> stack = new();

for (int i = 0; i < infixExpr.Length; i++)
{
char c = infixExpr[i];

if (Char.IsDigit(c))
{
postfixExpr += GetStringNumber(infixExpr, ref i) + " ";
}
else if (c == '(')
{
stack.Push(c);
}
else if (c == ')')
{
while (stack.Count > 0 && stack.Peek() != '(')
postfixExpr += stack.Pop() + " ";
stack.Pop();
}
else if (operationPriority.ContainsKey(c))
{
char op = c;
if (op == '-' && (i == 0 || (i > 1 && operationPriority.ContainsKey(infixExpr[i - 1]))))
op = '~';

while (stack.Count > 0 && (operationPriority[stack.Peek()] >= operationPriority[op]))
postfixExpr += stack.Pop() + " ";
stack.Push(op);
}
else if (c != '\r' && c != '\n')
{
throw new ArgumentException($"Обнаружен недопустимый символ в выражении: \"{c}\"");
}
}
foreach (char op in stack)
postfixExpr += op + " ";

return postfixExpr;
}

private double Execute(char op, double first, double second)
{
switch (op)
{
case '+':
return first + second;
case '-':
return first - second;
case '*':
return first * second;
case '/':
if (second == 0)
{
throw new DivideByZeroException("Невозможно выполнить деление на ноль");
}
return first / second;
case '^':
return Math.Pow(first, second);
default:
throw new ArgumentException("Недопустимая операция: " + op);
}
}

public double Calc()
{
Stack<double> locals = new();
int counter = 0;

for (int i = 0; i < postfixExpr.Length; i++)
{
char c = postfixExpr[i];

if (Char.IsDigit(c))
{
string number = GetStringNumber(postfixExpr, ref i);
locals.Push(Convert.ToDouble(number));
}
else if (operationPriority.ContainsKey(c))
{
counter += 1;
if (c == '~')
{
double last = locals.Count > 0 ? locals.Pop() : 0;

locals.Push(Execute('-', 0, last));
continue;
}

double second = locals.Count > 0 ? locals.Pop() : 0,
first = locals.Count > 0 ? locals.Pop() : 0;

locals.Push(Execute(c, first, second));
}
}

return locals.Pop();
}
}
21 changes: 21 additions & 0 deletions Compiler/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Microsoft.Win32;
using System.Collections.ObjectModel;
using System.Windows;
using Lab5;
using Lab7;
using System.Linq.Expressions;

namespace Compiler;

Expand Down Expand Up @@ -49,6 +51,7 @@ public class MainWindowViewModel : ViewModelBase
private RelayCommand _viewSourceCodeCommand;
private RelayCommand _removeErrorsCommand;
private RelayCommand _parseWhileCommand;
private RelayCommand _calculateExprCommand;

public event EventHandler<StringEventArgs> StringSent;
public event EventHandler<Lexeme> LexemeSent;
Expand Down Expand Up @@ -211,6 +214,11 @@ public RelayCommand ParseWhileCommand
{
get => _parseWhileCommand ??= new RelayCommand(ParseWhile);
}

public RelayCommand CalculateExprCommand
{
get => _calculateExprCommand ??= new RelayCommand(CalculateExpr);
}

public RelayCommand OpenFileCommand
{
Expand Down Expand Up @@ -266,6 +274,19 @@ public void ParseWhile(object obj)
{
VMText = _whileParser.Parse(_whileLexer.Analyze(_fileContent));
}

public void CalculateExpr(object obj)
{
try
{
PolishNotationCalculator polishNotationCalculator = new(_fileContent.Replace("\n", "").Replace("\r", "").Replace(" ", ""));
VMText = $"Исходное арифметическое выражение:\n{polishNotationCalculator.infixExpr}\n\nВыражение в ПОЛИЗ:\n{string.Join(" ", polishNotationCalculator.postfixExpr)}\n\nОтвет: {polishNotationCalculator.Calc()}.";
}
catch (Exception ex)
{
VMText = ex.Message;
}
}

public void RemoveErrors(object obj)
{
Expand Down
58 changes: 50 additions & 8 deletions Compiler/Views/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -226,32 +226,74 @@
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>

<Button Grid.Column="0" Grid.Row="0" Padding="5" Background="WhiteSmoke" Foreground="Black" Content="ЛР №5"/>
<Button Grid.Column="2" Grid.Row="0" Padding="5">

<Button Grid.Column="0" Grid.Row="0" Margin="2" Padding="5" Command="{Binding CalculateExprCommand}" Background="WhiteSmoke" Foreground="Black" Content="ЛР №5: перевод в ПОЛИЗ и вычисление арифм. выражения"/>
<Button Grid.Column="1" Grid.Row="0" Margin="2" Padding="5" Click="Button_Click_4">
<Button.ToolTip>
<ToolTip Content="Тестовый пример" />
</Button.ToolTip>
<materialDesign:PackIcon Kind="Code" />
</Button>
<Button Grid.Column="2" Grid.Row="0" Margin="2" Padding="5" Click="Button_Click_3">
<Button.ToolTip>
<ToolTip Content="Задание" />
</Button.ToolTip>
<materialDesign:PackIcon Kind="AboutCircleOutline" />
</Button>

<Button Grid.Column="0" Grid.Row="1" Padding="5" Background="WhiteSmoke" Foreground="Black" Content="ЛР №6"/>
<Button Grid.Column="2" Grid.Row="1" Padding="5">
<Button Grid.Column="0" Grid.Row="1" Margin="2 15 2 2" Grid.ColumnSpan="3" materialDesign:ElevationAssist.Elevation="Dp0" Focusable="False" Padding="5" Background="WhiteSmoke" Foreground="Black" Content="ЛР №6: поиск подстрок с помощью регулярных выражений" Cursor="Arrow"/>
<Button Grid.Column="0" Grid.Row="2" Margin="2" Padding="5" Background="WhiteSmoke" Foreground="Black" Content="Задание №1"/>
<Button Grid.Column="1" Grid.Row="2" Margin="2" Padding="5">
<Button.ToolTip>
<ToolTip Content="Тестовый пример" />
</Button.ToolTip>
<materialDesign:PackIcon Kind="Code" />
</Button>
<Button Grid.Column="2" Grid.Row="2" Margin="2" Padding="5">
<Button.ToolTip>
<ToolTip Content="Задание" />
</Button.ToolTip>
<materialDesign:PackIcon Kind="AboutCircleOutline" />
</Button>
<Button Grid.Column="0" Grid.Row="3" Margin="2" Padding="5" Background="WhiteSmoke" Foreground="Black" Content="Задание №2"/>
<Button Grid.Column="1" Grid.Row="3" Margin="2" Padding="5">
<Button.ToolTip>
<ToolTip Content="Тестовый пример" />
</Button.ToolTip>
<materialDesign:PackIcon Kind="Code" />
</Button>
<Button Grid.Column="2" Grid.Row="3" Margin="2" Padding="5">
<Button.ToolTip>
<ToolTip Content="Задание" />
</Button.ToolTip>
<materialDesign:PackIcon Kind="AboutCircleOutline" />
</Button>
<Button Grid.Column="0" Grid.Row="4" Margin="2" Padding="5" Background="WhiteSmoke" Foreground="Black" Content="Задание №3"/>
<Button Grid.Column="1" Grid.Row="4" Margin="2" Padding="5">
<Button.ToolTip>
<ToolTip Content="Тестовый пример" />
</Button.ToolTip>
<materialDesign:PackIcon Kind="Code" />
</Button>
<Button Grid.Column="2" Grid.Row="4" Margin="2" Padding="5">
<Button.ToolTip>
<ToolTip Content="Задание" />
</Button.ToolTip>
<materialDesign:PackIcon Kind="AboutCircleOutline" />
</Button>

<Button Grid.Column="0" Grid.Row="2" Padding="5" Command="{Binding ParseWhileCommand}" Background="WhiteSmoke" Foreground="Black" Content="ЛР №7: парсинг цикла while методом рекурсивного спуска"/>
<Button Grid.Column="1" Grid.Row="2" Padding="5" Click="Button_Click_2">
<Button Grid.Column="0" Grid.Row="5" Margin="2 15 2 2" Padding="5" Command="{Binding ParseWhileCommand}" Background="WhiteSmoke" Foreground="Black" Content="ЛР №7: парсинг цикла while методом рекурсивного спуска"/>
<Button Grid.Column="1" Grid.Row="5" Margin="2 15 2 2" Padding="5" Click="Button_Click_2">
<Button.ToolTip>
<ToolTip Content="Тестовый пример" />
</Button.ToolTip>
<materialDesign:PackIcon Kind="Code" />
</Button>
<Button Grid.Column="2" Grid.Row="2" Padding="5" Click="Button_Click_1">
<Button Grid.Column="2" Grid.Row="5" Margin="2 15 2 2" Padding="5" Click="Button_Click_1">
<Button.ToolTip>
<ToolTip Content="Задание" />
</Button.ToolTip>
Expand Down
26 changes: 26 additions & 0 deletions Compiler/Views/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,5 +231,31 @@ private void Button_Click_2(object sender, RoutedEventArgs e)
while a < b do b = a + ? end;
""";
}

private void Button_Click_3(object sender, RoutedEventArgs e)
{
MessageBox.Show("""
Цель работы: дополнить анализатор, разработанный в рамках лабораторных работ, этапом формирования внутренней формы представления программы.
Задание: реализовать алгоритм записи арифметического выражения в ПОЛИЗ и алгоритм вычисления выражения в ПОЛИЗ.
Поддерживаемые операции:
1. "(" — открывающаяся скобка;
2. ")" — закрывающаяся скобка;
3. "+" — оператор сложения;
4. "-" — оператор унарного минуса;
5. "-" — оператор бинарного минуса;
6. "*" — оператор умножения;
7. "/" — оператор деления;
8. "^" — оператор возведения в степень.
""", "Задание", MessageBoxButton.OK, MessageBoxImage.Information);
}

private void Button_Click_4(object sender, RoutedEventArgs e)
{
textEditor.Text = """
5 + 3 * 8 / -40
""";
}
}
}
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,18 @@ P = {

**Цель работы:** дополнить анализатор, разработанный в рамках лабораторных работ, этапом формирования внутренней формы представления программы.

### Тестовые примеры

1. **Тест №1.** Вычисление значения арифметического выражения.

![Тест 1](/README_images/postfix_test_1.png)
2. **Тест №2.** Обработка деления на 0.

![Тест 2](/README_images/postfix_test_2.png)
3. **Тест №3.** Обработка недопустимых символов.

![Тест 3](/README_images/postfix_test_3.png)

## Лабораторная работа №6: Реализация алгоритма поиска подстрок с помощью регулярных выражений

**Тема:** реализация алгоритма поиска подстрок с помощью регулярных выражений.
Expand Down
Binary file added README_images/postfix_test_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added README_images/postfix_test_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added README_images/postfix_test_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a4f77f4

Please sign in to comment.