-
Notifications
You must be signed in to change notification settings - Fork 0
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
Calculation expression #9
base: main
Are you sure you want to change the base?
Changes from 5 commits
3455909
11d835b
1a6b78b
1871fcb
19a2d46
ce0ebcf
e0ea5c9
c87b52f
9676910
0870523
47eb28e
d4f226d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
| ||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.1.32228.430 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ParsingTree", "ParsingTree\ParsingTree.csproj", "{3A685608-3E27-4534-942C-AE951EF76977}" | ||
EndProject | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestParsingTree", "TestParsingTree\TestParsingTree.csproj", "{921D199E-504F-47CD-AC97-9C93A98C8B0D}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{3A685608-3E27-4534-942C-AE951EF76977}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{3A685608-3E27-4534-942C-AE951EF76977}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{3A685608-3E27-4534-942C-AE951EF76977}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{3A685608-3E27-4534-942C-AE951EF76977}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{921D199E-504F-47CD-AC97-9C93A98C8B0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{921D199E-504F-47CD-AC97-9C93A98C8B0D}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{921D199E-504F-47CD-AC97-9C93A98C8B0D}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{921D199E-504F-47CD-AC97-9C93A98C8B0D}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {DD0BE32A-1D93-45E3-ACD3-92A75D23D824} | ||
EndGlobalSection | ||
EndGlobal |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,296 @@ | ||||||||||||||
namespace ParsingTree; | ||||||||||||||
|
||||||||||||||
using System; | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// Class representing the parse tree | ||||||||||||||
/// </summary> | ||||||||||||||
public class ParsingTree | ||||||||||||||
{ | ||||||||||||||
/// <summary> | ||||||||||||||
/// abstract nested class for dividing node into operators and operands for building a parse tree | ||||||||||||||
/// </summary> | ||||||||||||||
private abstract class Node | ||||||||||||||
{ | ||||||||||||||
// Abstract method for counting each operator or operand | ||||||||||||||
public abstract float Count(); | ||||||||||||||
|
||||||||||||||
// Abstract method for printing each operator or operand | ||||||||||||||
public abstract void Print(); | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// A class representing operands | ||||||||||||||
/// </summary> | ||||||||||||||
public class Operand : Node | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Operand не должен быть по идее вложенным в Node, потому что а зачем :) Пусть он будет вложенным в ParsingTree |
||||||||||||||
{ | ||||||||||||||
private readonly string Value; | ||||||||||||||
public Operand(string element) | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
{ | ||||||||||||||
Value = element; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// The operand class calculates the value for them and returns it | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Комментарии с // используются только для комментариев внутри методов, тут бы /// |
||||||||||||||
public override float Count() | ||||||||||||||
{ | ||||||||||||||
return float.Parse(Value); | ||||||||||||||
} | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
|
||||||||||||||
// The operand class can print the values of operands | ||||||||||||||
public override void Print() | ||||||||||||||
{ | ||||||||||||||
Console.Write(Value); | ||||||||||||||
Console.Write(" "); | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// A class representing operators | ||||||||||||||
/// </summary> | ||||||||||||||
public abstract class Operator : Node | ||||||||||||||
{ | ||||||||||||||
// Each operator , unlike an operand, has a right and a left son | ||||||||||||||
public Node? LeftSon; | ||||||||||||||
public Node? RightSon; | ||||||||||||||
|
||||||||||||||
// There will be only 4 operators, so the value field does not make sense | ||||||||||||||
|
||||||||||||||
// Template for printing operators | ||||||||||||||
public void OperatorPrintTemplate(string symbol) | ||||||||||||||
{ | ||||||||||||||
Console.Write("("); | ||||||||||||||
Console.Write(symbol); | ||||||||||||||
LeftSon?.Print(); | ||||||||||||||
RightSon?.Print(); | ||||||||||||||
Console.Write(")"); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// A class representing the operator + | ||||||||||||||
public class Plus : Operator | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Три уровня вложенности, ужас. Нет, надо, чтобы они все были на одном уровне и вложенными в ParseTree сам. |
||||||||||||||
{ | ||||||||||||||
public override float Count() | ||||||||||||||
{ | ||||||||||||||
if (LeftSon == null || RightSon == null) | ||||||||||||||
{ | ||||||||||||||
throw new NullReferenceException(); | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нельзя NullReferenceException кидать, оно кидается .NET-машиной |
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return LeftSon.Count() + RightSon.Count(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
public override void Print() | ||||||||||||||
{ | ||||||||||||||
if (LeftSon == null || RightSon == null) | ||||||||||||||
{ | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
OperatorPrintTemplate("+"); | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это известный антипаттерн "Вызов предка" (Call super). Лучше было наоборот, Print перегрузить в Operator, и чтобы он дёргал, например, свойство Symbol, которое было бы разным у каждого оператора. Иначе где-то забудете вызвать OperatorPrintTemplate, и будет беда |
||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// A class representing the operator - | ||||||||||||||
public class Minus : Operator | ||||||||||||||
{ | ||||||||||||||
public override float Count() | ||||||||||||||
{ | ||||||||||||||
if (LeftSon == null || RightSon == null) | ||||||||||||||
{ | ||||||||||||||
throw new NullReferenceException(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return LeftSon.Count() - RightSon.Count(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
public override void Print() | ||||||||||||||
{ | ||||||||||||||
if (LeftSon == null || RightSon == null) | ||||||||||||||
{ | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
OperatorPrintTemplate("-"); | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// A class representing the operator / | ||||||||||||||
public class Divide : Operator | ||||||||||||||
{ | ||||||||||||||
public override float Count() | ||||||||||||||
{ | ||||||||||||||
if (LeftSon == null || RightSon == null) | ||||||||||||||
{ | ||||||||||||||
throw new NullReferenceException(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
float rightSonValue = RightSon.Count(); | ||||||||||||||
if (Math.Abs(rightSonValue - 0) < 0.0000000000000000000000000001) | ||||||||||||||
{ | ||||||||||||||
throw new DivideByZeroException(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return LeftSon.Count() / rightSonValue; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
public override void Print() | ||||||||||||||
{ | ||||||||||||||
if (LeftSon == null || RightSon == null) | ||||||||||||||
{ | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
OperatorPrintTemplate("/"); | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// A class representing the operator * | ||||||||||||||
public class Multiplication : Operator | ||||||||||||||
{ | ||||||||||||||
public override float Count() | ||||||||||||||
{ | ||||||||||||||
if (LeftSon == null || RightSon == null) | ||||||||||||||
{ | ||||||||||||||
throw new NullReferenceException(); | ||||||||||||||
} | ||||||||||||||
return LeftSon.Count() * RightSon.Count(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
public override void Print() | ||||||||||||||
{ | ||||||||||||||
if (LeftSon == null || RightSon == null) | ||||||||||||||
{ | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
OperatorPrintTemplate("*"); | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
Node? treeRoot; | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// Function for building a tree | ||||||||||||||
/// </summary> | ||||||||||||||
/// <param name="expression">The expression that needs to be calculated</param> | ||||||||||||||
public void BuildTree(string expression) | ||||||||||||||
{ | ||||||||||||||
int index = 0; | ||||||||||||||
Node? node = null; | ||||||||||||||
treeRoot = PrivateBuildTree(expression, ref index, node); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// Auxiliary function for building a tree | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. /// |
||||||||||||||
private Node? PrivateBuildTree(string expression, ref int index, Node? node) | ||||||||||||||
{ | ||||||||||||||
if (index >= expression.Length) | ||||||||||||||
{ | ||||||||||||||
return node; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// Skip the characters we don't need | ||||||||||||||
while (expression[index] == '(' || expression[index] == ')' || expression[index] == ' ' && index < expression.Length) | ||||||||||||||
{ | ||||||||||||||
index++; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// The condition in order to avoid confusion, for example, with 4 -5 and 4 - 5 | ||||||||||||||
if (index < expression.Length - 1 && !IsOperand(expression[index + 1]) && IsOperator(expression[index])) | ||||||||||||||
{ | ||||||||||||||
InitializeNode(expression, ref index, ref node); | ||||||||||||||
return node; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// The number could be negative | ||||||||||||||
int newIndex = expression[index] == '-' ? index + 1 : index; | ||||||||||||||
string nodeValue = ""; | ||||||||||||||
while (newIndex < expression.Length && IsOperand(expression[newIndex])) | ||||||||||||||
{ | ||||||||||||||
nodeValue += expression[newIndex]; | ||||||||||||||
newIndex++; | ||||||||||||||
} | ||||||||||||||
Node? newNode = null; | ||||||||||||||
|
||||||||||||||
//This unused variable x is needed in order to call the function, | ||||||||||||||
//and it is the operand that is initialized, | ||||||||||||||
//because the last character of the number cannot be an operator (the file is considered correct | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
int x = nodeValue.Length - 1; | ||||||||||||||
if (expression[index] == '-') | ||||||||||||||
{ | ||||||||||||||
InitializeNode("-" + nodeValue, ref x, ref newNode); | ||||||||||||||
} | ||||||||||||||
else | ||||||||||||||
{ | ||||||||||||||
InitializeNode(nodeValue, ref x, ref newNode); | ||||||||||||||
} | ||||||||||||||
index = newIndex; | ||||||||||||||
return newNode; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// A function for initializing nodes depending on which operator or operator is a string | ||||||||||||||
private void InitializeNode(string expression, ref int index, ref Node? node) | ||||||||||||||
{ | ||||||||||||||
switch (expression[index]) | ||||||||||||||
{ | ||||||||||||||
case '+': | ||||||||||||||
{ | ||||||||||||||
node = new Node.Operator.Plus(); | ||||||||||||||
index++; | ||||||||||||||
((Node.Operator.Plus)node).LeftSon = PrivateBuildTree(expression, ref index, ((Node.Operator.Plus)node).LeftSon); | ||||||||||||||
((Node.Operator.Plus)node).RightSon = PrivateBuildTree(expression, ref index, ((Node.Operator.Plus)node).RightSon); | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
case '-': | ||||||||||||||
{ | ||||||||||||||
node = new Node.Operator.Minus(); | ||||||||||||||
index++; | ||||||||||||||
((Node.Operator.Minus)node).LeftSon = PrivateBuildTree(expression, ref index, ((Node.Operator.Minus)node).LeftSon); | ||||||||||||||
((Node.Operator.Minus)node).RightSon = PrivateBuildTree(expression, ref index, ((Node.Operator.Minus)node).RightSon); | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
case '*': | ||||||||||||||
{ | ||||||||||||||
node = new Node.Operator.Multiplication(); | ||||||||||||||
index++; | ||||||||||||||
((Node.Operator.Multiplication)node).LeftSon = PrivateBuildTree(expression, ref index, ((Node.Operator.Multiplication)node).LeftSon); | ||||||||||||||
((Node.Operator.Multiplication)node).RightSon = PrivateBuildTree(expression, ref index, ((Node.Operator.Multiplication)node).RightSon); | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
case '/': | ||||||||||||||
{ | ||||||||||||||
node = new Node.Operator.Divide(); | ||||||||||||||
index++; | ||||||||||||||
((Node.Operator.Divide)node).LeftSon = PrivateBuildTree(expression, ref index, ((Node.Operator.Divide)node).LeftSon); | ||||||||||||||
((Node.Operator.Divide)node).RightSon = PrivateBuildTree(expression, ref index, ((Node.Operator.Divide)node).RightSon); | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
default: | ||||||||||||||
{ | ||||||||||||||
node = new Node.Operand(expression); | ||||||||||||||
index++; | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// Function for printing a tree | ||||||||||||||
/// </summary> | ||||||||||||||
public void Print() => treeRoot?.Print(); | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// Function for calculating the value of an expression | ||||||||||||||
/// </summary> | ||||||||||||||
/// <returns>value of an expression</returns> | ||||||||||||||
public float Count() | ||||||||||||||
{ | ||||||||||||||
if (treeRoot == null) | ||||||||||||||
{ | ||||||||||||||
throw new NullReferenceException(); | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :( |
||||||||||||||
} | ||||||||||||||
return treeRoot.Count(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
private static bool IsOperator(char element) => element == '+' || element == '-' || element == '*' || element == '/'; | ||||||||||||||
|
||||||||||||||
private static bool IsOperand(char element) => element <= '9' && element >= '0'; | ||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Library</OutputType> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,25 @@ | ||||||||||||
namespace ParsingTree; | ||||||||||||
|
||||||||||||
/// <summary> | ||||||||||||
/// Parse Tree Interface | ||||||||||||
/// </summary> | ||||||||||||
public interface IParsingTree | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Он у Вас нигде не используется, следовательно не нужен |
||||||||||||
{ | ||||||||||||
|
||||||||||||
/// <summary> | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
/// Function for printing a tree | ||||||||||||
/// </summary> | ||||||||||||
public void Print(); | ||||||||||||
|
||||||||||||
/// <summary> | ||||||||||||
/// Function for building a tree | ||||||||||||
/// </summary> | ||||||||||||
/// <param name="expression">The expression on the basis of which the tree is built</param> | ||||||||||||
public void BuildTree(string expression); | ||||||||||||
|
||||||||||||
/// <summary> | ||||||||||||
/// Function for calculating the value of an expression | ||||||||||||
/// </summary> | ||||||||||||
/// <returns>value of an expression</returns> | ||||||||||||
public float Count(); | ||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
(* (+ 1 1) 2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Везде с заглавной, а тут со строчной, неконсистентно