Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ParseTree #7

Merged
merged 2 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ParseTree;

public class IncorrectExpressionException: Exception
{
public IncorrectExpressionException() : base() { }
public IncorrectExpressionException(string message) : base(message) { }
}
7 changes: 7 additions & 0 deletions ParseTree/ParseTree.Src/Exceptions/IncorrectTreeException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ParseTree;

public class IncorrectTreeException: Exception
{
public IncorrectTreeException() : base() { }
public IncorrectTreeException(string message) : base(message) { }
}
12 changes: 12 additions & 0 deletions ParseTree/ParseTree.Src/Nodes/INode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Data;

namespace ParseTree.Dependencies;

internal interface INode
{
double Eval();
string ToString();

INode? LeftChild { get; set; }
INode? RightChild { get; set; }
}
24 changes: 24 additions & 0 deletions ParseTree/ParseTree.Src/Nodes/NumberNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace ParseTree.Dependencies;

internal class NumberNode : INode
{
public double Eval()
{
return Value;
}

public override string ToString()
{
return Value.ToString();
}

public NumberNode(int value)
{
Value = value;
LeftChild = null;
}

public INode? LeftChild { get; set; }
public INode? RightChild { get; set; }
public double Value;
}
31 changes: 31 additions & 0 deletions ParseTree/ParseTree.Src/Nodes/OperationNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace ParseTree.Dependencies;

internal class OperationNode : INode
{
public INode? LeftChild { get; set; }
public INode? RightChild { get; set; }
public char operation;

public OperationNode(char operationChar)
{
operation = operationChar;
}

public double Eval()
{
if (LeftChild is not null && RightChild is not null)
{
return Operation.Calculate(operation, LeftChild.Eval(), RightChild.Eval());
}
throw new IncorrectTreeException();
}

public override string ToString()
{
if (LeftChild is not null && RightChild is not null)
{
return $"( {operation} {LeftChild.ToString()} {RightChild.ToString()})";
}
throw new IncorrectTreeException();
}
}
37 changes: 37 additions & 0 deletions ParseTree/ParseTree.Src/Operation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Runtime.InteropServices;

namespace ParseTree.Dependencies;

class Operation
{
public static double Calculate(char operation, double operandLeft, double operandRight)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нет документации к публичному методу

{
switch (operation)
{
case '+':
{
return operandLeft + operandRight;
}
case '-':
{
return operandLeft - operandRight;
}
case '*':
{
return operandLeft * operandRight;
}
case '/':
{
if (operandRight == 0)
{
throw new DivideByZeroException();
}
return operandLeft / operandRight;
}
default:
{
throw new IncorrectExpressionException();
}
}
}
}
10 changes: 10 additions & 0 deletions ParseTree/ParseTree.Src/ParseTree.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
132 changes: 132 additions & 0 deletions ParseTree/ParseTree.Src/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using System.Linq.Expressions;
using ParseTree;

string options = """
0 - Exit
1 - Create tree
2 - Evaluate tree
3 - Save tree to file
4 - Print expression
Write number to console to choose option:
""";
bool running = true;
Tree? currentTree = null;
while (running)
{
Console.WriteLine(options);
int userInput;
while (!int.TryParse(Console.ReadLine(), out userInput) || userInput > 4 || userInput < 0)
{
Console.WriteLine("Incorrect input");
Console.WriteLine(options);
}

switch (userInput)
{
case 0:
{
Console.Write("Exit");
running = false;
break;
}
case 1:
{
Console.WriteLine("Write your ariphmetical expression in postfix form to console");
string? expression = Console.ReadLine();
try
{
if (expression is not null)
{
currentTree = new(expression);
}
}
catch (IncorrectExpressionException)
{
Console.WriteLine("Incorrect input\nYour expression must fit the template (<operation> <operand1> <operand2>) where operands may be expressions themselves");
}
break;
}
case 2:
{
try
{
if (currentTree is not null)
{
var answer = currentTree.Evaluate();
Console.WriteLine($"Answer to your expression is {answer}");
}
else
{
Console.WriteLine("You haven't added an expression yet");
}
}
catch (IncorrectExpressionException)
{
Console.WriteLine("Seems like your expression was incorrect. Please write another one");
}
catch (IncorrectTreeException)
{
Console.WriteLine("Seems like there is a problem with your tree");
}
break;
}
case 3:
{
Console.WriteLine("Write name for the file where you want to save your expression");
if (currentTree is not null)
{
string? filename = Console.ReadLine();
if (filename is not null && filename != string.Empty)
{
if (filename[0] != '/' || filename[0] != '~' || filename[0] != '.')
{
filename = "./" + filename;
}
try
{
string? expression = currentTree.ToString();
File.WriteAllText(filename, expression);
Console.Write("Your expression was saved at ");
Console.WriteLine(filename);
}
catch (IncorrectTreeException)
{
Console.WriteLine("Seems like there is a problem with your tree");
}

}
else
{
Console.WriteLine("You should write a filename for your file");
}
}
else
{
Console.WriteLine("You haven't added an expression yet");
}
break;
}
case 4:
{
if (currentTree is not null)
{
try
{
string? expression = currentTree.ToString();
Console.Write("Your expression: ");
Console.WriteLine(expression);
}
catch (IncorrectTreeException)
{
Console.WriteLine("Seems like there is a problem with your tree");
}
}
else
{
Console.WriteLine("You haven't added an expression yet");
}
break;
}
}
Console.WriteLine();
}
117 changes: 117 additions & 0 deletions ParseTree/ParseTree.Src/Tree.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System.ComponentModel;
using System.Globalization;
using System.Linq.Expressions;
using ParseTree.Dependencies;

namespace ParseTree;

/// <summary>
/// Data structure for storing ariphmetical expressions
/// </summary>
public class Tree
{
private INode root;

public Tree(string expression)
{
if (expression is null || expression == string.Empty)
{
throw new IncorrectExpressionException("Empty expression");
}

int index = 0;
SkipSpaces(expression, ref index);
if (expression[index] >= '0' && expression[index] <= '9')
{
int number = ParseNumber(expression, ref index);
if (index != expression.Length)
{
throw new IncorrectExpressionException();
}
root = new NumberNode(number);
}
else
{
root = Parse(expression, ref index);
}
}

private static INode Parse(string expression, ref int index)
{
INode newNode;
SkipSpaces(expression, ref index);
char currentChar = expression[index];
if (currentChar == '(')
{
++index;
newNode = new OperationNode(expression[index]);
++index;
newNode.LeftChild = Parse(expression, ref index);
newNode.RightChild = Parse(expression, ref index);
SkipSpaces(expression, ref index);
if (expression[index] == ')')
{
++index;
}
else
{
throw new IncorrectExpressionException();
}
}
else if (currentChar >= '0' && currentChar <= '9')
{
int number = ParseNumber(expression, ref index);
newNode = new NumberNode(number);
}
else
{
throw new IncorrectExpressionException();
}

return newNode;
}

private static void SkipSpaces(string expression, ref int index)
{
while (expression[index] == ' ')
{
++index;
}
}

private static int ParseNumber(string expression, ref int index)
{
int currentNumber = 0;
char currentChar = expression[index];
while (currentChar >= '0' && currentChar <= '9')
{
currentNumber *= 10;
currentNumber += expression[index] - '0';
++index;
if (currentChar >= expression.Length)
{
break;
}
currentChar = expression[index];
}
return currentNumber;
}

/// <summary>
/// Evaluate the expression stored in the tree
/// </summary>
/// <returns>Answer to expression</returns>
public double Evaluate()
{
return root.Eval();
}

/// <summary>
/// Write the expression in postfix form to string
/// </summary>
/// <returns></returns>
public override string ToString()
{
return root.ToString();
}
}
Loading