From 8b0ec8cbe218c00a6f9d87e46b461fdd0a6d1917 Mon Sep 17 00:00:00 2001 From: Antoine Viallon Date: Sat, 6 Jan 2024 00:17:47 +0100 Subject: [PATCH] errors: use termcolor for terminal output coloring + enable raising non-fatal errors --- compiler/errors.py | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/compiler/errors.py b/compiler/errors.py index 64648b4..6dde985 100644 --- a/compiler/errors.py +++ b/compiler/errors.py @@ -1,29 +1,57 @@ from __future__ import annotations +import enum import inspect import sys +from typing import TextIO + +from termcolor import termcolor from . import source, lexer +class LevelType: + + def __init__(self, name: str, color: termcolor.Color = None): + """ + + :param name: + :param color: ANSI style color escapes without the prefix nor the suffix + """ + self.name = name + self.color = color + + def __str__(self) -> str: + return self.show_with_suffix() + + def show_with_suffix(self, suffix=":") -> str: + return termcolor.colored(f"{self.name}{suffix}", color=self.color, attrs=["bold"]) + + +class Levels(enum.Enum): + Warning = LevelType("warning", color="light_yellow") + Error = LevelType("error", color="red") + + class CompilationError(Exception): def __init__(self, location: source.SourceLocation, message: str = "Unknown error"): - super().__init__(f"{str(location)}: \033[1merror:\033[0m {message}") + super().__init__(f"{str(location)}: {Levels.Error.value.show_with_suffix(':')} {message}") self.location = location class CompilationWarning(Warning): _pending_warnings: list[CompilationWarning] = [] - def __init__(self, location: source.SourceLocation, message: str = "Unknown warning"): - super().__init__(f"{str(location)}: \033[1mwarning:\033[0m {message}") + def __init__(self, location: source.SourceLocation, message: str = "Unknown warning", + level: Levels = Levels.Warning): + super().__init__(f"{str(location)}: {level.value.show_with_suffix(':')} {message}") self.location = location @classmethod - def show_warnings(cls, _source: str): + def show_warnings(cls, _source: str, file: TextIO = sys.stderr): for warning in CompilationWarning._pending_warnings: warning.location.source = _source - print(f"{warning}\n{warning.location.show_in_source()}", file=sys.stderr) + print(f"{warning}\n{warning.location.show_in_source()}", file=file) def raise_warning(self): CompilationWarning._pending_warnings += [self]