Skip to content

Commit

Permalink
Merge pull request #314 from mk3008/313-adding-the-tryreadword-function
Browse files Browse the repository at this point in the history
Revised text reading class
  • Loading branch information
mk3008 authored Jan 27, 2024
2 parents 728069d + d50a206 commit 7695f6d
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 88 deletions.
74 changes: 58 additions & 16 deletions src/Carbunql/Analysis/CharReader.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,93 @@
using Cysharp.Text;
using System.Diagnostics.CodeAnalysis;

namespace Carbunql.Analysis;

/// <summary>
/// Class that processes text character by character.
/// Reading can only be done in the forward direction, and it cannot be reversed.
/// </summary>
public class CharReader : IDisposable
{
private bool disposedValue;

/// <summary>
/// Constructor for the CharReader class. Initializes a StringReader using the specified text.
/// </summary>
/// <param name="text">The text to be processed</param>
public CharReader(string text)
{
Text = text;
Reader = new StringReader(Text);
Reader = new StringReader(text);
}

public string Text { get; init; }

private StringReader Reader { get; init; }

protected char? PeekOrDefaultChar()
private char? PeekOrDefault()
{
var i = Reader.Peek();
if (i < 0) return null;
return (char)i;
}

public char ReadChar()
private char Read()
{
var i = Reader.Read();
if (i < 0) throw new EndOfStreamException();
return (char)i;
}

public char? ReadCharOrDefault(char expect)
/// <summary>
/// Reads one character. Returns false if reading is not possible.
/// </summary>
/// <param name="c">The character that was read</param>
/// <returns>True if reading was successful, otherwise false.</returns>
public bool TryRead([MaybeNullWhen(false)] out char c)
{
c = default;

var i = Reader.Peek();
if (i < 0) return false;
c = Read();
return true;
}

/// <summary>
/// Reads one character. Reading is canceled and false is returned if the read character is different from the expected value.
/// </summary>
/// <param name="expect">The expected value</param>
/// <param name="c">The character that was read</param>
/// <returns>True if the read character matches the expected value, otherwise false</returns>
public bool TryRead(char expect, [MaybeNullWhen(false)] out char c)
{
var c = PeekOrDefaultChar();
if (c == expect) return ReadChar();
return null;
c = default;

var i = Reader.Peek();
if (i < 0) return false;
if ((char)i == expect)
{
c = Read();
return true;
}
return false;
}

public IEnumerable<char> ReadChars() => ReadChars((_) => true);
/// <summary>
/// Returns one character at a time until the end.
/// </summary>
/// <returns>The read character.</returns>
public IEnumerable<char> Reads() => Reads((_) => true);

public IEnumerable<char> ReadChars(Func<char, bool> whileFn)
/// <summary>
/// Returns one character at a time while the specified condition is met.
/// </summary>
/// <param name="whileFn">The condition to continue reading</param>
/// <returns>The read character.</returns>
public IEnumerable<char> Reads(Func<char, bool> whileFn)
{
var c = PeekOrDefaultChar();
var c = PeekOrDefault();
while (c != null && whileFn(c.Value))
{
yield return ReadChar();
c = PeekOrDefaultChar();
yield return Read();
c = PeekOrDefault();
}
}

Expand Down
Loading

0 comments on commit 7695f6d

Please sign in to comment.