Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 16 additions & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Build
on: [push]

jobs:
build:
build-Windows:

runs-on: windows-latest

Expand All @@ -20,4 +20,19 @@ jobs:
- name: Test
run: $slnList = Get-ChildItem $foo.FullName -Recurse -Filter '*.sln'; foreach ($file in $slnList) {dotnet test $file.FullName}

build-Ubuntu:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Build
uses: actions/setup-dotnet@v1
with:
dotnet-version: '6.x'
- name: Restore
run: for f in $(find . -name "*.sln"); do dotnet restore $f; done
- name: Build
run: for f in $(find . -name "*.sln"); do dotnet build $f; done
- name: Test
run: for f in $(find . -name "*.sln"); do dotnet test $f; done
31 changes: 31 additions & 0 deletions Homework4/ParsingTree/ParsingTree.sln
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
306 changes: 306 additions & 0 deletions Homework4/ParsingTree/ParsingTree/ParsingTree.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
namespace ParsingTree;

using System;

/// <summary>
/// Class representing the parse tree
/// </summary>
public class ParsingTree
{
private abstract class Node
{
/// <summary>
/// Abstract method for counting each operator or operand
/// </summary>
/// <returns>Operator or operand value</returns>
public abstract float Count();

/// <summary>
/// Abstract method for printing each operator or operand
/// </summary>
public abstract void Print();
}

/// <summary>
/// A class representing operands
/// </summary>
private class Operand : Node
{
private readonly string Value;

public Operand(string element)
{
Value = element;
}

/// <summary>
/// The operand class calculates the value for them and returns it
/// </summary>
/// <returns>Operand value</returns>
public override float Count() => float.Parse(Value);

/// <summary>
/// The operand class can print the values of operands
/// </summary>
public override void Print()
{
Console.Write(Value);
Console.Write(" ");
}
}

/// <summary>
/// A class representing operators
/// </summary>
private abstract class Operator : Node
{
public Node? LeftSon;
public Node? RightSon;


public abstract char Symbol { get; set; }

public override void Print()
{
Console.Write("(");
Console.Write(Symbol);
LeftSon?.Print();
RightSon?.Print();
Console.Write(")");
}
}

/// <summary>
/// A class representing the operator +
/// </summary>
private class Plus : Operator
{
public Plus()
{
Symbol = '+';
}

public override float Count()
{
if (LeftSon == null || RightSon == null)
{
throw new InvalidOperationException();
}

return LeftSon.Count() + RightSon.Count();
}

public override char Symbol { get; set; }
}

/// <summary>
/// A class representing the operator -
/// </summary>
private class Minus : Operator
{
public Minus()
{
Symbol = '-';
}

public override float Count()
{
// But if we consider the input file to be correct, then such a situation should not arise
if (LeftSon == null || RightSon == null)
{
throw new InvalidOperationException();
}

return LeftSon.Count() - RightSon.Count();
}

public override char Symbol { get; set; }
}

/// <summary>
/// A class representing the operator /
/// </summary>
private class Divide : Operator
{
public Divide()
{
Symbol = '/';
}

public override float Count()
{
if (LeftSon == null || RightSon == null)
{
throw new InvalidOperationException();
}

float rightSonValue = RightSon.Count();
if (Math.Abs(rightSonValue - 0) < 0.0000000000000000000000000001)
{
throw new DivideByZeroException();
}

return LeftSon.Count() / rightSonValue;
}

public override char Symbol { get; set; }
}

/// <summary>
/// A class representing the operator *
/// </summary>
private class Multiplication : Operator
{
public Multiplication()
{
Symbol = '*';
}

public override float Count()
{
if (LeftSon == null || RightSon == null)
{
throw new InvalidOperationException();
}
return LeftSon.Count() * RightSon.Count();
}

public override char Symbol { get; set; }
}

private Node? treeRoot;

/// <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);
}

/// <summary>
/// Auxiliary function for building a tree
/// </summary>
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
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;
}

/// <summary>
/// A function for initializing nodes depending on which operator or operator is a string
/// </summary>
private void InitializeNode(string expression, ref int index, ref Node? node)
{
switch (expression[index])
{
case '+':
{
node = new Plus();
index++;
((Plus)node).LeftSon = PrivateBuildTree(expression, ref index, ((Plus)node).LeftSon);
((Plus)node).RightSon = PrivateBuildTree(expression, ref index, ((Plus)node).RightSon);
return;
}
case '-':
{
node = new Minus();
index++;
((Minus)node).LeftSon = PrivateBuildTree(expression, ref index, ((Minus)node).LeftSon);
((Minus)node).RightSon = PrivateBuildTree(expression, ref index, ((Minus)node).RightSon);
return;
}
case '*':
{
node = new Multiplication();
index++;
((Multiplication)node).LeftSon = PrivateBuildTree(expression, ref index, ((Multiplication)node).LeftSon);
((Multiplication)node).RightSon = PrivateBuildTree(expression, ref index, ((Multiplication)node).RightSon);
return;
}
case '/':
{
node = new Divide();
index++;
((Divide)node).LeftSon = PrivateBuildTree(expression, ref index, ((Divide)node).LeftSon);
((Divide)node).RightSon = PrivateBuildTree(expression, ref index, ((Divide)node).RightSon);
return;
}
default:
{
node = new 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 InvalidOperationException();
}

return treeRoot.Count();
}

private static bool IsOperator(char element) => element == '+' || element == '-' || element == '*' || element == '/';

private static bool IsOperand(char element) => element <= '9' && element >= '0';
}
10 changes: 10 additions & 0 deletions Homework4/ParsingTree/ParsingTree/ParsingTree.csproj
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>
1 change: 1 addition & 0 deletions Homework4/ParsingTree/TestParsingTree/FirstTest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(* (+ 1 1) 2)
Loading