using CanonSharp.Combinator.Abstractions; namespace CanonSharp.Pascal.Scanner; /// /// 字符串输入流状态 /// public sealed class StringReadState : IReadState { private readonly string _source; private readonly int _index; public char Current => _source[_index]; public bool HasValue => _index < _source.Length; public StringReadState Next => new(_source, _index + 1); private StringReadState(string source, int index) { _source = source; _index = index; } public StringReadState(string source) : this(source, 0) { } public bool Equals(StringReadState? other) { if (other is null) { return false; } return _source == other._source && _index == other._index; } public override bool Equals(object? obj) => obj is StringReadState other && Equals(other); public override int GetHashCode() => _source.GetHashCode() ^ _index; public override string ToString() { return HasValue ? $"{ToReadableString(Current)}<0x{(int)Current:X2}>" : "End of string."; } private static string ToReadableString(char token) => token switch { '\0' => "\\0", '\a' => "\\a", '\b' => "\\b", '\f' => "\\f", '\n' => "\\n", '\r' => "\\r", '\t' => "\\t", '\v' => "\\v", _ => token.ToString(), }; }