test: 针对string的ISourceReader (#37)

Reviewed-on: PostGuard/Canon#37
This commit is contained in:
jackfiled 2024-04-15 18:02:11 +08:00
parent 792c1d44f1
commit d631a28703
3 changed files with 132 additions and 16 deletions

View File

@ -1,16 +0,0 @@
namespace Canon.Tests;
public static class Utils
{
public static LinkedList<char> GetLinkedList(string content)
{
LinkedList<char> list = [];
foreach(char c in content)
{
list.AddLast(c);
}
return list;
}
}

View File

@ -0,0 +1,47 @@
using System.Diagnostics.CodeAnalysis;
using Canon.Core.Abstractions;
namespace Canon.Tests.Utils;
/// <summary>
/// 从字符串中读取源代码
/// </summary>
public sealed class StringSourceReader(string source) : ISourceReader, IDisposable
{
private readonly IEnumerator<char> _enumerator =
source.GetEnumerator();
public uint Line { get; private set; } = 1;
public uint Pos { get; private set; }
public string FileName => "string";
public bool TryReadChar([NotNullWhen(true)] out char? c)
{
if (Pos != 0 || Line != 1)
{
// 不是第一次读取
if (_enumerator.Current == '\n')
{
Pos = 0;
Line += 1;
}
}
if (!_enumerator.MoveNext())
{
c = null;
return false;
}
Pos += 1;
c = _enumerator.Current;
return true;
}
public void Dispose()
{
_enumerator.Dispose();
}
}

View File

@ -0,0 +1,85 @@
using Canon.Core.Abstractions;
namespace Canon.Tests.Utils;
public class StringSourceReaderTests
{
[Fact]
public void LineFeedTest()
{
ISourceReader reader = new StringSourceReader("program Main;\nbegin\nend.\n");
Assert.Equal(0u, reader.Pos);
Assert.Equal(1u, reader.Line);
// program
Assert.True(reader.TryReadChar(out char? c));
Assert.Equal('p', c);
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out c));
Assert.Equal(' ', c);
// main;
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out char? _));
Assert.True(reader.TryReadChar(out c));
Assert.Equal('\n', c);
// begin
for (uint i = 1; i <= 5; i++)
{
Assert.True(reader.TryReadChar(out char? _));
Assert.Equal(i, reader.Pos);
Assert.Equal(2u, reader.Line);
}
// \n
Assert.True(reader.TryReadChar(out c));
Assert.Equal('\n', c);
// end.
foreach (char i in "end.")
{
Assert.True(reader.TryReadChar(out c));
Assert.Equal(i, c);
}
}
[Fact]
public void CarriageReturnLineFeedTest()
{
ISourceReader reader = new StringSourceReader("program Main;\r\nbegin\r\nend.\r\n");
// program Main;
foreach ((char value, uint index) in
"program Main;".Select((value, index) => (value, (uint)index)))
{
Assert.True(reader.TryReadChar(out char? c));
Assert.Equal(value, c);
Assert.Equal(index + 1, reader.Pos);
Assert.Equal(1u, reader.Line);
}
Assert.True(reader.TryReadChar(out _));
Assert.True(reader.TryReadChar(out _));
// begin
foreach ((char value, uint index) in
"begin".Select((value, index) => (value, (uint)index)))
{
Assert.True(reader.TryReadChar(out char? c));
Assert.Equal(value, c);
Assert.Equal(index + 1, reader.Pos);
Assert.Equal(2u, reader.Line);
}
}
}