Skip to content
Merged
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
9 changes: 8 additions & 1 deletion samples/SimpleMathParser/MathParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@ namespace SimpleMathParser;
/// </summary>
public class ArenaMathParser
{
private const int MaxExpressionLength = 100_000;

/// <summary>
/// Tokenizes the given math expression into a list of tokens allocated in the provided arena.
/// </summary>
/// <param name="input">The math expression as a span of characters.</param>
/// <param name="arena">The arena allocator to use for memory allocations.</param>
/// <returns>A list of <see cref="Token"/> structures.</returns>
/// <exception cref="SyntaxErrorException">Thrown when an unknown character is encountered.</exception>
/// <exception cref="SyntaxErrorException">Thrown when an unknown character is encountered or if the expression exceeds the maximum length.</exception>
public static ArenaList<Token> Tokenize(ReadOnlySpan<char> input, ArenaAllocator arena)
{
if (input.Length > MaxExpressionLength)
{
throw new SyntaxErrorException("Expression too long.");
}

var tokens = new ArenaList<Token>(arena);

int i = 0;
Expand Down
30 changes: 30 additions & 0 deletions tests/SimpleMathParser.Tests/SimpleMathParser.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.12.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\SharpArena\SharpArena.csproj" />
<ProjectReference Include="..\..\samples\SimpleMathParser\SimpleMathParser.csproj" />
</ItemGroup>

</Project>
44 changes: 44 additions & 0 deletions tests/SimpleMathParser.Tests/TokenizationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using SharpArena.Allocators;
using SimpleMathParser;
using Xunit;
using FluentAssertions;

namespace SimpleMathParser.Tests;

public class TokenizationTests : IDisposable
{
private readonly ArenaAllocator _arena = new(1024);

[Fact]
public void Tokenize_WhenInputExceedsMaxLength_ShouldThrowSyntaxErrorException()
{
// Arrange
// We'll use a large string to exceed the planned 100,000 character limit.
string input = new string('1', 100_001);

// Act
Action act = () => ArenaMathParser.Tokenize(input.AsSpan(), _arena);

// Assert
act.Should().Throw<SyntaxErrorException>()
.WithMessage("Expression too long.");
}

[Fact]
public void Tokenize_WhenInputIsWithinLimit_ShouldSucceed()
{
// Arrange
string input = "1 + 2";

// Act
var tokens = ArenaMathParser.Tokenize(input.AsSpan(), _arena);

// Assert
tokens.Length.Should().Be(3);
}

public void Dispose()
{
_arena.Dispose();
}
}
Loading