diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..e7e7cb3
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,6 @@
+image: Visual Studio 2019
+
+build_script:
+ - For /R %%I in (*.sln) do dotnet test %%I
+
+test: off
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree.Test/hw4ParseTree.Test.csproj b/hw4ParseTree/hw4ParseTree.Test/hw4ParseTree.Test.csproj
new file mode 100644
index 0000000..3c475f6
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree.Test/hw4ParseTree.Test.csproj
@@ -0,0 +1,19 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hw4ParseTree/hw4ParseTree.Test/hw4ParseTreeTest.cs b/hw4ParseTree/hw4ParseTree.Test/hw4ParseTreeTest.cs
new file mode 100644
index 0000000..9a56c96
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree.Test/hw4ParseTreeTest.cs
@@ -0,0 +1,87 @@
+using NUnit.Framework;
+using System;
+
+namespace Hw4ParseTree.Test
+{
+ public class Tests
+ {
+ private ParseTree tree;
+
+ [SetUp]
+ public void Setup()
+ {
+ tree = new ParseTree();
+ }
+
+ [TestCase]
+ public void TestAddition()
+ {
+ var str = "( + 2 3 )";
+ tree.BuildTree(str);
+ Assert.AreEqual(5, tree.Calculate());
+ }
+
+ [TestCase]
+ public void TestSubtraction()
+ {
+ var str = "( - 2 3 )";
+ tree.BuildTree(str);
+ Assert.AreEqual(-1, tree.Calculate());
+ }
+
+ [TestCase]
+ public void TestMultiplication()
+ {
+ var str = "( * 2 3 )";
+ tree.BuildTree(str);
+ Assert.AreEqual(6, tree.Calculate());
+ }
+
+ [TestCase]
+ public void TestDivision()
+ {
+ var str = "( / 8 4 )";
+ tree.BuildTree(str);
+ Assert.AreEqual(2, tree.Calculate());
+ }
+
+ [TestCase]
+ public void TestDoubleDivision()
+ {
+ var str = "( / 3 2 )";
+ tree.BuildTree(str);
+ Assert.AreEqual(1.5, tree.Calculate(), 0.000001);
+ }
+
+ [TestCase]
+ public void TestWithNegativeNumber()
+ {
+ var str = "( + 3 -2 )";
+ tree.BuildTree(str);
+ Assert.AreEqual(1, tree.Calculate());
+ }
+
+ [TestCase]
+ public void TestDivisionByZero()
+ {
+ var str = "( / 8 0 )";
+ tree.BuildTree(str);
+ Assert.Throws(() => tree.Calculate());
+ }
+
+ [TestCase]
+ public void TestNotCorrectExpression()
+ {
+ var str = "( / 8 )";
+ Assert.Throws(() => tree.BuildTree(str));
+ }
+
+ [TestCase]
+ public void TestTaskExpression()
+ {
+ var str = "( * ( + 1 1 ) 2 )";
+ tree.BuildTree(str);
+ Assert.AreEqual(4, tree.Calculate());
+ }
+ }
+}
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree.sln b/hw4ParseTree/hw4ParseTree.sln
new file mode 100644
index 0000000..adf64c1
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31005.135
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hw4ParseTree", "hw4ParseTree\Hw4ParseTree.csproj", "{70C27B8B-C63D-4F52-B8C7-B9561C911D17}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "hw4ParseTree.Test", "hw4ParseTree.Test\hw4ParseTree.Test.csproj", "{E5953ED4-DAAC-461D-AF86-3DE600136A14}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {70C27B8B-C63D-4F52-B8C7-B9561C911D17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {70C27B8B-C63D-4F52-B8C7-B9561C911D17}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {70C27B8B-C63D-4F52-B8C7-B9561C911D17}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {70C27B8B-C63D-4F52-B8C7-B9561C911D17}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E5953ED4-DAAC-461D-AF86-3DE600136A14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E5953ED4-DAAC-461D-AF86-3DE600136A14}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E5953ED4-DAAC-461D-AF86-3DE600136A14}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E5953ED4-DAAC-461D-AF86-3DE600136A14}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {E315057C-F86D-4CC5-95B3-11FF0F5A2F77}
+ EndGlobalSection
+EndGlobal
diff --git a/hw4ParseTree/hw4ParseTree/Addition.cs b/hw4ParseTree/hw4ParseTree/Addition.cs
new file mode 100644
index 0000000..6d51dce
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/Addition.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Hw4ParseTree
+{
+ ///
+ /// класс для сложения
+ ///
+ public class Addition : Operator
+ {
+ public override char Sign => '+';
+
+ public Addition(INode leftChild, INode rightChild)
+ {
+ LeftChild = leftChild;
+ RightChild = rightChild;
+ }
+
+ public override double Calculate()
+ => LeftChild.Calculate() + RightChild.Calculate();
+ }
+}
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree/Division.cs b/hw4ParseTree/hw4ParseTree/Division.cs
new file mode 100644
index 0000000..78239d9
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/Division.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Hw4ParseTree
+{
+ ///
+ /// класс для деления
+ ///
+ public class Division : Operator
+ {
+ public override char Sign => '/';
+
+ public Division(INode leftChild, INode rightChild)
+ {
+ LeftChild = leftChild;
+ RightChild = rightChild;
+ }
+
+ public override double Calculate()
+ {
+ if (Math.Abs(RightChild.Calculate()) < 0.000001)
+ {
+ throw new DivideByZeroException();
+ }
+ return LeftChild.Calculate() / RightChild.Calculate();
+ }
+ }
+}
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree/Expression.txt b/hw4ParseTree/hw4ParseTree/Expression.txt
new file mode 100644
index 0000000..c45d6d9
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/Expression.txt
@@ -0,0 +1 @@
+(* (+ 1 1) 2)
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree/INode.cs b/hw4ParseTree/hw4ParseTree/INode.cs
new file mode 100644
index 0000000..c766d19
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/INode.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Hw4ParseTree
+{
+ ///
+ /// интерфейс узла в дереве разбора
+ ///
+ public interface INode
+ {
+ ///
+ /// печатает, что находится в узле
+ ///
+ public void Print();
+
+ ///
+ /// возвращает значение элемента, лежащего в узле
+ ///
+ public double Calculate();
+ }
+}
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree/InvalidExpressionException.cs b/hw4ParseTree/hw4ParseTree/InvalidExpressionException.cs
new file mode 100644
index 0000000..4007e9c
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/InvalidExpressionException.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Hw4ParseTree
+{
+ ///
+ /// исключение для неправильных выражений.
+ ///
+ public class InvalidExpressionException : Exception
+ {
+ public InvalidExpressionException()
+ {
+ }
+
+ public InvalidExpressionException(string message)
+ : base(message)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree/Multiplication.cs b/hw4ParseTree/hw4ParseTree/Multiplication.cs
new file mode 100644
index 0000000..2a80ced
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/Multiplication.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Hw4ParseTree
+{
+ ///
+ /// класс для умножения
+ ///
+ public class Multiplication : Operator
+ {
+ public override char Sign => '*';
+
+ public Multiplication(INode leftChild, INode rightChild)
+ {
+ LeftChild = leftChild;
+ RightChild = rightChild;
+ }
+
+ public override double Calculate()
+ => LeftChild.Calculate() * RightChild.Calculate();
+ }
+}
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree/Operand.cs b/hw4ParseTree/hw4ParseTree/Operand.cs
new file mode 100644
index 0000000..0d54399
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/Operand.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Hw4ParseTree
+{
+ ///
+ /// класс синтаксического дерева, который представляет число
+ ///
+ class Operand : INode
+ {
+ private double Number;
+
+ public Operand(double number)
+ => Number = number;
+
+ ///
+ /// выводит число
+ ///
+ public void Print()
+ => Console.Write($" {Number} ");
+
+ ///
+ /// считает значение
+ ///
+ public double Calculate()
+ => Number;
+ }
+}
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree/Operator.cs b/hw4ParseTree/hw4ParseTree/Operator.cs
new file mode 100644
index 0000000..643611a
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/Operator.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Hw4ParseTree
+{
+ ///
+ /// Класс синтаксического дерва который представляет оператор
+ ///
+ public abstract class Operator : INode
+ {
+ public INode LeftChild { get; set; }
+
+ public INode RightChild { get; set; }
+
+ public virtual char Sign { get; }
+
+ ///
+ /// выводит участок выражения
+ ///
+ public void Print()
+ {
+ Console.Write("(");
+ LeftChild.Print();
+ Console.Write(Sign);
+ RightChild.Print();
+ Console.Write(")");
+ }
+
+ ///
+ /// считает значение
+ ///
+ public abstract double Calculate();
+ }
+}
diff --git a/hw4ParseTree/hw4ParseTree/ParseTree.cs b/hw4ParseTree/hw4ParseTree/ParseTree.cs
new file mode 100644
index 0000000..09e324d
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/ParseTree.cs
@@ -0,0 +1,148 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Hw4ParseTree
+{
+ ///
+ /// дерево разбора
+ ///
+ public class ParseTree
+ {
+ private INode root;
+
+ ///
+ /// Функция построения дерева разбора
+ ///
+ public void BuildTree(string expression)
+ {
+ var index = 0;
+ if (CheckExpression(expression))
+ {
+ root = Build(expression, ref index);
+ }
+ else
+ {
+ throw new InvalidExpressionException();
+ }
+ }
+
+ private bool IsCorrectSymbol(char symbol)
+ => symbol == '(' || symbol == ')';
+
+ private bool IsCorrect(char symbol)
+ => symbol == '(' || IsOperator(symbol);
+
+ private bool IsOperator(char symbol)
+ => symbol == '+' || symbol == '-' || symbol == '*' || symbol == '/';
+
+ private double ReadNumber(string line, ref int index)
+ {
+ var number = "";
+ if (line[index] == '-')
+ {
+ number += line[index];
+ index++;
+ }
+ while (char.IsDigit(line[index]))
+ {
+ number += line[index];
+ index++;
+ }
+ if (!double.TryParse(number, out var value))
+ {
+ throw new InvalidExpressionException();
+ }
+ return value;
+ }
+
+ private bool CheckExpression(string line)
+ {
+ int index = 0;
+ int countNumber = 0;
+ int countBrackets = 0;
+ while (index != line.Length)
+ {
+ if (line[index] == '(')
+ {
+ countBrackets++;
+ }
+ else if (line[index] == ' ')
+ {
+ index++;
+ continue;
+ }
+ else if (line[index] == ')')
+ {
+ countBrackets--;
+ if (countBrackets < 0)
+ {
+ return false;
+ }
+ }
+ else if (line[index] == '-' && char.IsDigit(line[index + 1]) || char.IsDigit(line[index]))
+ {
+ var value = ReadNumber(line, ref index);
+ countNumber++;
+ continue;
+ }
+ else if (IsOperator(line[index]))
+ {
+ countNumber--;
+ }
+ else
+ {
+ return false;
+ }
+ index++;
+ }
+ return countBrackets == 0 && countNumber == 1;
+ }
+
+ private INode Build(string line, ref int index)
+ {
+ for (; index < line.Length; ++index)
+ {
+ if (line[index] == ' ')
+ {
+ continue;
+ }
+ if (line[index] == '-' && char.IsDigit(line[index + 1]) || char.IsDigit(line[index]))
+ {
+ var value = ReadNumber(line, ref index);
+ return new Operand(value);
+ }
+ else if (IsOperator(line[index]))
+ {
+ index++;
+ return line[index - 1] switch
+ {
+ '+' => new Addition(Build(line, ref index), Build(line, ref index)),
+ '-' => new Subtraction(Build(line, ref index), Build(line, ref index)),
+ '/' => new Division(Build(line, ref index), Build(line, ref index)),
+ '*' => new Multiplication(Build(line, ref index), Build(line, ref index)),
+ _ => throw new InvalidExpressionException(),
+ };
+ }
+ else if (!IsCorrectSymbol(line[index]))
+ {
+ throw new InvalidExpressionException();
+ }
+ }
+ return root;
+ }
+
+ ///
+ /// функция печати дерева
+ ///
+ public void PrintTree()
+ => root.Print();
+
+ ///
+ /// Считает значение выражения
+ ///
+ /// возвращает ответ
+ public double Calculate()
+ => root.Calculate();
+ }
+}
\ No newline at end of file
diff --git a/hw4ParseTree/hw4ParseTree/Program.cs b/hw4ParseTree/hw4ParseTree/Program.cs
new file mode 100644
index 0000000..b19ba91
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/Program.cs
@@ -0,0 +1,29 @@
+using System;
+using System.IO;
+
+namespace Hw4ParseTree
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ var tree = new ParseTree();
+ var file = new StreamReader("..\\..\\..\\Expression.txt");
+ var expression = file.ReadLine();
+ Console.WriteLine($"Выражение - {expression}");
+ try
+ {
+ tree.BuildTree(expression);
+ }
+ catch (InvalidExpressionException)
+ {
+ Console.WriteLine("Ошибка! Некоректный ввод выражения!");
+ return;
+ }
+
+ Console.Write("Печать выражения: ");
+ tree.PrintTree();
+ Console.WriteLine($"\nОтвет = {tree.Calculate()}");
+ }
+ }
+}
diff --git a/hw4ParseTree/hw4ParseTree/Subtraction.cs b/hw4ParseTree/hw4ParseTree/Subtraction.cs
new file mode 100644
index 0000000..329f910
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/Subtraction.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Hw4ParseTree
+{
+ ///
+ /// класс для вычитания
+ ///
+ public class Subtraction : Operator
+ {
+ public override char Sign => '-';
+
+ public Subtraction(INode leftChild, INode rightChild)
+ {
+ LeftChild = leftChild;
+ RightChild = rightChild;
+ }
+
+ public override double Calculate()
+ => LeftChild.Calculate() - RightChild.Calculate();
+ }
+}
diff --git a/hw4ParseTree/hw4ParseTree/hw4ParseTree.csproj b/hw4ParseTree/hw4ParseTree/hw4ParseTree.csproj
new file mode 100644
index 0000000..c73e0d1
--- /dev/null
+++ b/hw4ParseTree/hw4ParseTree/hw4ParseTree.csproj
@@ -0,0 +1,8 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+