diff --git a/samples/SimpleMathParser/MathParser.cs b/samples/SimpleMathParser/MathParser.cs index adb347b..10a93ab 100644 --- a/samples/SimpleMathParser/MathParser.cs +++ b/samples/SimpleMathParser/MathParser.cs @@ -9,15 +9,22 @@ namespace SimpleMathParser; /// public class ArenaMathParser { + private const int MaxExpressionLength = 100_000; + /// /// Tokenizes the given math expression into a list of tokens allocated in the provided arena. /// /// The math expression as a span of characters. /// The arena allocator to use for memory allocations. /// A list of structures. - /// Thrown when an unknown character is encountered. + /// Thrown when an unknown character is encountered or if the expression exceeds the maximum length. public static ArenaList Tokenize(ReadOnlySpan input, ArenaAllocator arena) { + if (input.Length > MaxExpressionLength) + { + throw new SyntaxErrorException("Expression too long."); + } + var tokens = new ArenaList(arena); int i = 0; diff --git a/tests/SimpleMathParser.Tests/SimpleMathParser.Tests.csproj b/tests/SimpleMathParser.Tests/SimpleMathParser.Tests.csproj new file mode 100644 index 0000000..7dd86d9 --- /dev/null +++ b/tests/SimpleMathParser.Tests/SimpleMathParser.Tests.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + enable + enable + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + diff --git a/tests/SimpleMathParser.Tests/TokenizationTests.cs b/tests/SimpleMathParser.Tests/TokenizationTests.cs new file mode 100644 index 0000000..ea461da --- /dev/null +++ b/tests/SimpleMathParser.Tests/TokenizationTests.cs @@ -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() + .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(); + } +}