diff --git a/Upsilon/Diagnostics.cs b/Upsilon/Diagnostics.cs index 8d75348..86b785a 100644 --- a/Upsilon/Diagnostics.cs +++ b/Upsilon/Diagnostics.cs @@ -83,7 +83,14 @@ namespace Upsilon public override string ToString() { - return $"{Message} at {Span.Start}\n{Diagnostics.ScriptString.GetSpan(Span)}"; + var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start); + return $"{Message} at ({linePos.Line}, {linePos.Pos})\n{Diagnostics.ScriptString.GetSpan(Span)}"; + } + + public string GetDiagnosticPosition() + { + var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start); + return $"({linePos.Line},{linePos.Pos})"; } public string BeforeError(int i = 5) diff --git a/Upsilon/Text/SourceText.cs b/Upsilon/Text/SourceText.cs index e6dfef6..9b15de0 100644 --- a/Upsilon/Text/SourceText.cs +++ b/Upsilon/Text/SourceText.cs @@ -5,10 +5,20 @@ namespace Upsilon.Text public class SourceText { private readonly string _text; + private readonly SourceTextLine[] _lines; public SourceText(string text) { _text = text; + var lines = text.Split('\n'); + _lines = new SourceTextLine[lines.Length]; + var linePos = 0; + for (var index = 0; index < lines.Length; index++) + { + var line = lines[index]; + _lines[index] = new SourceTextLine(linePos, line.Length); + linePos += line.Length; + } } public string GetSpan(int start, int length) @@ -24,6 +34,32 @@ namespace Upsilon.Text return _text.Substring(start, length); } + public (int Line, int Pos) GetLinePosition(int spanPos) + { + var min = 0; + var max = _lines.Length - 1; + while (min <= max) + { + var mid = (min + max) / 2 ; + var midLine = _lines[mid]; + if (midLine.Start <= spanPos && midLine.End > spanPos) + { + var pos = spanPos - midLine.Start; + return (mid, pos); + } + if (spanPos >= midLine.End) + { + min = mid + 1; + } + else if (spanPos < midLine.Start) + { + max = mid - 1; + } + } + var newPos = spanPos - _lines[min].Start; + return (min, newPos); + } + public string GetSpan(TextSpan span) { return GetSpan(span.Start, span.Length); diff --git a/Upsilon/Text/SourceTextLine.cs b/Upsilon/Text/SourceTextLine.cs new file mode 100644 index 0000000..b85f17c --- /dev/null +++ b/Upsilon/Text/SourceTextLine.cs @@ -0,0 +1,15 @@ +namespace Upsilon.Text +{ + public struct SourceTextLine + { + public SourceTextLine(int start, int lineLength) + { + Start = start; + LineLength = lineLength; + } + + public int Start { get; } + public int LineLength { get; } + public int End => Start + LineLength; + } +} \ No newline at end of file diff --git a/Ycicle/Program.cs b/Ycicle/Program.cs index 9564f81..1c65f66 100644 --- a/Ycicle/Program.cs +++ b/Ycicle/Program.cs @@ -65,6 +65,7 @@ namespace Ycicle Console.WriteLine(message.Message); Console.ForegroundColor = ConsoleColor.Gray; + Console.Write(message.GetDiagnosticPosition() + " "); Console.Write(message.BeforeError()); Console.ForegroundColor = ConsoleColor.Red;