From 1bbc0b705f29452ed105d95687343173b8af60d7 Mon Sep 17 00:00:00 2001 From: Joscha Date: Sat, 22 May 2021 20:38:56 +0000 Subject: [PATCH] Improve transformer error handling --- PFERD/__main__.py | 5 +++++ PFERD/transformer.py | 33 ++++++++++++++++++--------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/PFERD/__main__.py b/PFERD/__main__.py index 0e84e34..5cc6ef6 100644 --- a/PFERD/__main__.py +++ b/PFERD/__main__.py @@ -7,6 +7,7 @@ from .cli import PARSER, load_default_section from .config import Config, ConfigDumpError, ConfigLoadError, ConfigOptionError from .logging import log from .pferd import Pferd +from .transformer import RuleParseError from .version import NAME, VERSION @@ -122,6 +123,10 @@ def main() -> None: log.unlock() log.error(str(e)) exit(1) + except RuleParseError as e: + log.unlock() + e.pretty_print() + exit(1) except KeyboardInterrupt: log.unlock() log.explain_topic("Interrupted, exiting immediately") diff --git a/PFERD/transformer.py b/PFERD/transformer.py index 135baf2..293274a 100644 --- a/PFERD/transformer.py +++ b/PFERD/transformer.py @@ -6,10 +6,11 @@ import ast import re from abc import ABC, abstractmethod -from dataclasses import dataclass from pathlib import PurePath from typing import Dict, Optional, Union +from .logging import log + class Rule(ABC): @abstractmethod @@ -122,16 +123,18 @@ class ReRule(Rule): return False -@dataclass -class RuleParseException(Exception): - line: "Line" - reason: str +class RuleParseError(Exception): + def __init__(self, line: "Line", reason: str): + super().__init__(f"Error in rule on line {line.line_nr}, column {line.index}: {reason}") + + self.line = line + self.reason = reason def pretty_print(self) -> None: - print(f"Error parsing rule on line {self.line.line_nr}:") - print(self.line.line) + log.error(f"Error parsing rule on line {self.line.line_nr}:") + log.error_contd(self.line.line) spaces = " " * self.line.index - print(f"{spaces}^--- {self.reason}") + log.error_contd(f"{spaces}^--- {self.reason}") class Line: @@ -170,7 +173,7 @@ class Line: if self.get() == char: self.advance() else: - raise RuleParseException(self, f"Expected {char!r}") + raise RuleParseError(self, f"Expected {char!r}") QUOTATION_MARKS = {'"', "'"} @@ -186,7 +189,7 @@ def parse_string_literal(line: Line) -> str: if quotation_mark not in QUOTATION_MARKS: # This should never happen as long as this function is only called from # parse_string. - raise RuleParseException(line, "Invalid quotation mark") + raise RuleParseError(line, "Invalid quotation mark") line.advance() while c := line.get(): @@ -204,7 +207,7 @@ def parse_string_literal(line: Line) -> str: else: line.advance() - raise RuleParseException(line, "Expected end of string literal") + raise RuleParseError(line, "Expected end of string literal") def parse_until_space_or_eol(line: Line) -> str: @@ -235,12 +238,12 @@ def parse_arrow(line: Line) -> str: while True: c = line.get() if not c: - raise RuleParseException(line, "Expected rest of arrow") + raise RuleParseError(line, "Expected rest of arrow") elif c == "-": line.advance() c = line.get() if not c: - raise RuleParseException(line, "Expected rest of arrow") + raise RuleParseError(line, "Expected rest of arrow") elif c == ">": line.advance() break # End of arrow @@ -267,7 +270,7 @@ def parse_rule(line: Line) -> Rule: left = parse_string(line) if isinstance(left, bool): line.index = leftindex - raise RuleParseException(line, "Left side can't be '!'") + raise RuleParseError(line, "Left side can't be '!'") # Parse arrow parse_whitespace(line) @@ -301,7 +304,7 @@ def parse_rule(line: Line) -> Rule: return NameRule(ReRule(left, right)) else: line.index = arrowindex + 1 # For nicer error message - raise RuleParseException(line, "Invalid arrow name") + raise RuleParseError(line, "Invalid arrow name") class Transformer: