namespace DevDisciples.Parsing; public class Source : ParsableStream, ISourceLocation { private readonly string _source; public string File { get; } public int Start { get; set; } public int Line { get; set; } = 1; public int Column { get; set; } = 1; public char Last => Tokens[^1]; public Source(string file, string source) : base(source.AsMemory()) { File = file; _source = source; } public override char Advance() { Column++; return base.Advance(); } public override bool Ended() { return Current == '\0' || base.Ended(); } public string Extract() { var position = (Start, Length: Position - Start); Start = Position; return _source.Substring(position.Start, position.Length); } public void Ignore() { Start = Position; } public bool Match(char expected) { if (Tokens[Position] != expected) return false; Position += 1; return true; } public bool Match(ReadOnlySpan expected) { if (Position + expected.Length > Tokens.Length) return false; for (var index = 0; index < expected.Length; index++) { if (Tokens[Position + index] != expected[index]) { return false; } } Position += expected.Length; return true; } }