168 lines
5.6 KiB
C#
168 lines
5.6 KiB
C#
using System.Collections.Generic;
|
|
using Upsilon.BaseTypes;
|
|
using Upsilon.Exceptions;
|
|
using Upsilon.Parser;
|
|
using Upsilon.Text;
|
|
|
|
namespace Upsilon
|
|
{
|
|
public class Diagnostics
|
|
{
|
|
public string FileName { get; }
|
|
public SourceText ScriptString { get; }
|
|
public readonly List<DiagnosticsMessage> Errors = new List<DiagnosticsMessage>();
|
|
public readonly List<DiagnosticsMessage> Warnings = new List<DiagnosticsMessage>();
|
|
public bool ThrowsOnError { get; }
|
|
|
|
public Diagnostics(SourceText scriptString, bool throwsOnError, string fileName)
|
|
{
|
|
ScriptString = scriptString;
|
|
ThrowsOnError = throwsOnError;
|
|
FileName = fileName;
|
|
}
|
|
|
|
public void Log(DiagnosticLevel level, string message, TextSpan location)
|
|
{
|
|
if (level == DiagnosticLevel.Error)
|
|
Errors.Add(new DiagnosticsMessage(this, level, message, location));
|
|
else if (level == DiagnosticLevel.Warning)
|
|
Warnings.Add(new DiagnosticsMessage(this, level, message, location));
|
|
}
|
|
|
|
public void LogError(string message, TextSpan location)
|
|
{
|
|
if (ThrowsOnError)
|
|
{
|
|
var text = ScriptString.GetSpan(location);
|
|
throw new ParseException(FileName, message, location.StartLine, location.StartPosition, text);
|
|
}
|
|
Log(DiagnosticLevel.Error, message, location);
|
|
}
|
|
|
|
public void LogWarning(string message, TextSpan location)
|
|
{
|
|
Log(DiagnosticLevel.Warning, message, location);
|
|
}
|
|
|
|
public void LogBadCharacter(TextSpan location, SyntaxKind expectedToken, SyntaxKind currentKind)
|
|
{
|
|
LogError($"Invalid character found. Expected: '{expectedToken}', Got: '{currentKind}'", location);
|
|
}
|
|
|
|
public void LogBadCharacter(TextSpan location, SyntaxKind expectedToken)
|
|
{
|
|
LogError($"Invalid character found. Expected: '{expectedToken}'", location);
|
|
}
|
|
public void LogBadCharacter(TextSpan location, char expected, char actual)
|
|
{
|
|
LogError($"Invalid character found. Expected: '{expected}', Got: '{actual}'", location);
|
|
}
|
|
|
|
public void LogBadCharacter(TextSpan location)
|
|
{
|
|
LogError($"Invalid character found.", location);
|
|
}
|
|
|
|
public void LogUnknownVariable(TextSpan span, string variable)
|
|
{
|
|
LogError($"Unknown variable '{variable}'", span);
|
|
}
|
|
|
|
public void LogNullReferenceError(TextSpan span)
|
|
{
|
|
LogError($"Null Reference Encountered", span);
|
|
}
|
|
|
|
public void LogUnknownType(TextSpan eSpan)
|
|
{
|
|
LogError($"Unknown Type found", eSpan);
|
|
}
|
|
|
|
public void LogUnknownBinaryOperator(TextSpan eSpan, SyntaxKind text, Type leftType, Type rightType)
|
|
{
|
|
LogError($"No binary operator {text} found for types '{leftType}' and '{rightType}'", eSpan);
|
|
}
|
|
|
|
public void LogUnknownUnaryOperator(TextSpan eSpan, SyntaxKind text, Type inType)
|
|
{
|
|
LogError($"No unary operator {text} found for type '{inType}'", eSpan);
|
|
}
|
|
|
|
public void LogCannotConvert(Type actualType, Type expectedType, TextSpan span)
|
|
{
|
|
LogError($"Cannot convert type '{actualType}' to '{expectedType}'", span);
|
|
}
|
|
|
|
public void LogInvalidIndexExpression(Type expressionType, Type indexType, TextSpan span)
|
|
{
|
|
LogError($"Cannot index type '{expressionType}' with type '{indexType}'", span);
|
|
}
|
|
|
|
public void LogUnknownVariableType(string variableName, TextSpan span)
|
|
{
|
|
LogWarning(
|
|
$"Variable '{variableName}' has an unknown variable type, and as such errors won't be visible before evaluation.",
|
|
span);
|
|
}
|
|
}
|
|
|
|
public class DiagnosticsMessage
|
|
{
|
|
public Diagnostics Diagnostics { get; }
|
|
public DiagnosticLevel DiagnosticLevel { get; }
|
|
public string Message { get; }
|
|
public TextSpan Span { get; }
|
|
|
|
public DiagnosticsMessage(Diagnostics diagnostics, DiagnosticLevel diagnosticLevel, string message, TextSpan span)
|
|
{
|
|
DiagnosticLevel = diagnosticLevel;
|
|
Diagnostics = diagnostics;
|
|
Message = message;
|
|
Span = span;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{Message} at ({Span.StartLine}, {Span.StartPosition})\n{Diagnostics.ScriptString.GetSpan(Span)}";
|
|
}
|
|
|
|
public string GetDiagnosticPosition()
|
|
{
|
|
return $"({Span.StartLine},{Span.StartPosition})";
|
|
}
|
|
|
|
public string LineBeforeError()
|
|
{
|
|
return Diagnostics.ScriptString.GetSpan(Span.StartLine, 0, Span.StartLine, Span.StartPosition);
|
|
}
|
|
|
|
public string BeforeError(int i = 5)
|
|
{
|
|
return Diagnostics.ScriptString.GetSpan(Span.StartLine, Span.StartPosition - i, Span.StartLine, Span.StartPosition);
|
|
}
|
|
|
|
public string AtError()
|
|
{
|
|
return Diagnostics.ScriptString.GetSpan(Span);
|
|
}
|
|
|
|
public string LineAfterError()
|
|
{
|
|
return Diagnostics.ScriptString.GetSpan(Span.EndLine, Span.EndPosition, Span.EndLine, 10000);
|
|
}
|
|
|
|
public string AfterError(int i = 5)
|
|
{
|
|
return Diagnostics.ScriptString.GetSpan(Span.EndLine, Span.EndPosition, Span.EndLine, Span.EndPosition + i);
|
|
}
|
|
|
|
}
|
|
|
|
public enum DiagnosticLevel
|
|
{
|
|
Information,
|
|
Warning,
|
|
Error,
|
|
}
|
|
|
|
} |