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
22 changes: 22 additions & 0 deletions HW2/HW2.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTree", "SyntaxTree\SyntaxTree.csproj", "{6C1B7790-DBF9-4146-A87B-83D95A0D5C54}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTree.Tests", "SyntaxTree.Tests\SyntaxTree.Tests.csproj", "{29D5F19D-35BC-49BE-8724-369258B5717D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6C1B7790-DBF9-4146-A87B-83D95A0D5C54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6C1B7790-DBF9-4146-A87B-83D95A0D5C54}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6C1B7790-DBF9-4146-A87B-83D95A0D5C54}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6C1B7790-DBF9-4146-A87B-83D95A0D5C54}.Release|Any CPU.Build.0 = Release|Any CPU
{29D5F19D-35BC-49BE-8724-369258B5717D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29D5F19D-35BC-49BE-8724-369258B5717D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29D5F19D-35BC-49BE-8724-369258B5717D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29D5F19D-35BC-49BE-8724-369258B5717D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
44 changes: 44 additions & 0 deletions HW2/SyntaxTree.Tests/SyntaxTree.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="NUnit" Version="3.14.0"/>
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
</ItemGroup>

<ItemGroup>
<Using Include="NUnit.Framework"/>
</ItemGroup>

<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<AdditionalFiles Include="stylecop.json" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SyntaxTree\SyntaxTree.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="testFile.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
155 changes: 155 additions & 0 deletions HW2/SyntaxTree.Tests/SyntaxTreeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// <copyright file="SyntaxTreeTests.cs" company="khusainovilas">
// Copyright (c) khusainovilas. All rights reserved.
// </copyright>

namespace SyntaxTree.Tests;

/// <summary>
/// tests for syntax tree.
/// </summary>
public class SyntaxTreeTests
{
private StringWriter consoleOutput;

[SetUp]
public void SetUp()
{
this.consoleOutput = new StringWriter();
Console.SetOut(this.consoleOutput);
}

[TearDown]
public void TearDown()
{
this.consoleOutput.Dispose();
Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true });
}

/// <summary>
/// Test parsing a valid expression with multiplication and addition.
/// </summary>
[Test]
public void Parser_Parse_ValidExpression_ReturnsCorrectTreeAndResult()
{
const string input = "(* (+ 1 1) 2)";
var tree = Parser.Parse(input);
Assert.Multiple(() =>
{
Assert.That(tree.ToStringRepresentation(), Is.EqualTo("(* (+ 1 1) 2)"));
Assert.That(tree.Calculate(), Is.EqualTo(4));
});
}

/// <summary>
/// Test parsing an expression with negative numbers.
/// </summary>
[Test]
public void Parser_Parse_NegativeNumber_ReturnsCorrectResult()
{
const string input = "(+ -5 3)";
var tree = Parser.Parse(input);
Assert.Multiple(() =>
{
Assert.That(tree.ToStringRepresentation(), Is.EqualTo("(+ -5 3)"));
Assert.That(tree.Calculate(), Is.EqualTo(-2));
});
}

/// <summary>
/// Test parsing an empty input throws ArgumentException.
/// </summary>
[Test]
public void Parser_Parse_EmptyInput_ThrowsArgumentException()
{
Assert.Throws<ArgumentException>(() => Parser.Parse(string.Empty));
}

/// <summary>
/// Test parsing an invalid token throws ArgumentException.
/// </summary>
[Test]
public void Parser_Parse_InvalidToken_ThrowsArgumentException()
{
Assert.Throws<ArgumentException>(() => Parser.Parse("(+ 1 a)"));
}

/// <summary>
/// Test parsing unbalanced parentheses throws ArgumentException.
/// </summary>
[Test]
public void Parser_Parse_UnbalancedParentheses_ThrowsArgumentException()
{
Assert.Throws<ArgumentException>(() => Parser.Parse("(( 1 2)"));
}

/// <summary>
/// Test parsing division by zero throws DivideByZeroException in Calculate.
/// </summary>
[Test]
public void Parser_Parse_DivisionByZero_ThrowsDivideByZeroException()
{
const string input = "(/ 10 0)";
var tree = Parser.Parse(input);
Assert.That(tree.ToStringRepresentation(), Is.EqualTo("(/ 10 0)"));
Assert.Throws<DivideByZeroException>(() => tree.Calculate());
}

/// <summary>
/// Test NumberNode calculation and string representation.
/// </summary>
[Test]
public void NumberNode_CalculateAndToString_ReturnsCorrectValues()
{
var node = new NumberNode(-5);
Assert.Multiple(() =>
{
Assert.That(node.Calculate(), Is.EqualTo(-5));
Assert.That(node.ToStringRepresentation(), Is.EqualTo("-5"));
});
}

/// <summary>
/// Test that Add node calculates and prints correctly.
/// </summary>
[Test]
public void Add_CalculateAndToString_ReturnsCorrectValues()
{
var node = new Add(new NumberNode(1), new NumberNode(2));

Check warning on line 118 in HW2/SyntaxTree.Tests/SyntaxTreeTests.cs

View workflow job for this annotation

GitHub Actions / build-windows

Check warning on line 118 in HW2/SyntaxTree.Tests/SyntaxTreeTests.cs

View workflow job for this annotation

GitHub Actions / build-windows

Check warning on line 118 in HW2/SyntaxTree.Tests/SyntaxTreeTests.cs

View workflow job for this annotation

GitHub Actions / build-ubuntu

Check warning on line 118 in HW2/SyntaxTree.Tests/SyntaxTreeTests.cs

View workflow job for this annotation

GitHub Actions / build-ubuntu

Check warning on line 118 in HW2/SyntaxTree.Tests/SyntaxTreeTests.cs

View workflow job for this annotation

GitHub Actions / build-windows

Check warning on line 118 in HW2/SyntaxTree.Tests/SyntaxTreeTests.cs

View workflow job for this annotation

GitHub Actions / build-windows

Check warning on line 118 in HW2/SyntaxTree.Tests/SyntaxTreeTests.cs

View workflow job for this annotation

GitHub Actions / build-ubuntu

Check warning on line 118 in HW2/SyntaxTree.Tests/SyntaxTreeTests.cs

View workflow job for this annotation

GitHub Actions / build-ubuntu

Assert.Multiple(() =>
{
Assert.That(node.Calculate(), Is.EqualTo(3));
Assert.That(node.ToStringRepresentation(), Is.EqualTo("(+ 1 2)"));
});
}

/// <summary>
/// Test subtraction (non-commutative operation) works correctly.
/// </summary>
[Test]
public void Parser_Parse_Subtraction_ReturnsCorrectResult()
{
const string input = "(- 10 4)";
var tree = Parser.Parse(input);
Assert.Multiple(() =>
{
Assert.That(tree.ToStringRepresentation(), Is.EqualTo("(- 10 4)"));
Assert.That(tree.Calculate(), Is.EqualTo(6));
});
}

/// <summary>
/// Test division (non-commutative operation) works correctly and doesn't swap operands.
/// </summary>
[Test]
public void Parser_Parse_Division_ReturnsCorrectResult()
{
const string input = "(/ 10 2)";
var tree = Parser.Parse(input);
Assert.Multiple(() =>
{
Assert.That(tree.ToStringRepresentation(), Is.EqualTo("(/ 10 2)"));
Assert.That(tree.Calculate(), Is.EqualTo(5));
});
}
}
9 changes: 9 additions & 0 deletions HW2/SyntaxTree.Tests/stylecop.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
"settings": {
"documentationRules": {
"companyName": "khusainovilas",
"copyrightText": "Copyright (c) {companyName}. All rights reserved."
}
}
}
1 change: 1 addition & 0 deletions HW2/SyntaxTree.Tests/testFile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(+ 1 2)
27 changes: 27 additions & 0 deletions HW2/SyntaxTree/Add.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// <copyright file="Add.cs" company="khusainovilas">
// Copyright (c) khusainovilas. All rights reserved.
// </copyright>

namespace SyntaxTree;

/// <summary>
/// Add operation.
/// </summary>
public class Add : Operation
{
/// <summary>
/// Initializes a new instance of the <see cref="Add"/> class.
/// </summary>
/// <param name="left">Left operand of the operation.</param>
/// <param name="right">Right operand of the operation.</param>
public Add(IAbstractNode left, IAbstractNode right)
: base(left, right)
{
}

/// <inheritdoc/>
protected override char Symbol => '+';

/// <inheritdoc/>
public override int Calculate() => this.Left.Calculate() + this.Right.Calculate();
}
36 changes: 36 additions & 0 deletions HW2/SyntaxTree/Divide.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// <copyright file="Divide.cs" company="khusainovilas">
// Copyright (c) khusainovilas. All rights reserved.
// </copyright>

namespace SyntaxTree;

/// <summary>
/// Divide operation.
/// </summary>
public class Divide : Operation
{
/// <summary>
/// Initializes a new instance of the <see cref="Divide"/> class.
/// </summary>
/// <param name="left">Left operand of the operation.</param>
/// <param name="right">Right operand of the operation.</param>
public Divide(IAbstractNode left, IAbstractNode right)
: base(left, right)
{
}

/// <inheritdoc/>
protected override char Symbol => '/';

/// <inheritdoc/>
public override int Calculate()
{
var divisor = this.Right.Calculate();
if (divisor == 0)
{
throw new DivideByZeroException("Division by zero.");
}

return this.Left.Calculate() / divisor;
}
}
23 changes: 23 additions & 0 deletions HW2/SyntaxTree/IAbstractNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// <copyright file="IAbstractNode.cs" company="khusainovilas">
// Copyright (c) khusainovilas. All rights reserved.
// </copyright>

namespace SyntaxTree;

/// <summary>
/// Represents a node in the syntax tree.
/// </summary>
public interface IAbstractNode
{
/// <summary>
/// Calculates the value of the node.
/// </summary>
/// <returns>The calculated result.</returns>
int Calculate();

/// <summary>
/// Returns the string representation of the node.
/// </summary>
/// <returns>String representation of the node.</returns>
string ToStringRepresentation();
}
27 changes: 27 additions & 0 deletions HW2/SyntaxTree/Multiply.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// <copyright file="Multiply.cs" company="khusainovilas">
// Copyright (c) khusainovilas. All rights reserved.
// </copyright>

namespace SyntaxTree;

/// <summary>
/// Multiply operation.
/// </summary>
public class Multiply : Operation
{
/// <summary>
/// Initializes a new instance of the <see cref="Multiply"/> class.
/// </summary>
/// <param name="left">Left operand of the operation.</param>
/// <param name="right">Right operand of the operation.</param>
public Multiply(IAbstractNode left, IAbstractNode right)
: base(left, right)
{
}

/// <inheritdoc/>
protected override char Symbol => '*';

/// <inheritdoc/>
public override int Calculate() => this.Left.Calculate() * this.Right.Calculate();
}
17 changes: 17 additions & 0 deletions HW2/SyntaxTree/NumberNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// <copyright file="NumberNode.cs" company="khusainovilas">
// Copyright (c) khusainovilas. All rights reserved.
// </copyright>

namespace SyntaxTree;

/// <summary>
/// Represents a number node in the syntax tree.
/// </summary>
public class NumberNode(int value) : IAbstractNode
{
/// <inheritdoc/>
public int Calculate() => value;

/// <inheritdoc/>
public string ToStringRepresentation() => value.ToString();
}
Loading