Improve transformer error handling

This commit is contained in:
Joscha 2021-05-22 20:38:56 +00:00
parent 662191eca9
commit 1bbc0b705f
2 changed files with 23 additions and 15 deletions

View File

@ -7,6 +7,7 @@ from .cli import PARSER, load_default_section
from .config import Config, ConfigDumpError, ConfigLoadError, ConfigOptionError from .config import Config, ConfigDumpError, ConfigLoadError, ConfigOptionError
from .logging import log from .logging import log
from .pferd import Pferd from .pferd import Pferd
from .transformer import RuleParseError
from .version import NAME, VERSION from .version import NAME, VERSION
@ -122,6 +123,10 @@ def main() -> None:
log.unlock() log.unlock()
log.error(str(e)) log.error(str(e))
exit(1) exit(1)
except RuleParseError as e:
log.unlock()
e.pretty_print()
exit(1)
except KeyboardInterrupt: except KeyboardInterrupt:
log.unlock() log.unlock()
log.explain_topic("Interrupted, exiting immediately") log.explain_topic("Interrupted, exiting immediately")

View File

@ -6,10 +6,11 @@
import ast import ast
import re import re
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass
from pathlib import PurePath from pathlib import PurePath
from typing import Dict, Optional, Union from typing import Dict, Optional, Union
from .logging import log
class Rule(ABC): class Rule(ABC):
@abstractmethod @abstractmethod
@ -122,16 +123,18 @@ class ReRule(Rule):
return False return False
@dataclass class RuleParseError(Exception):
class RuleParseException(Exception): def __init__(self, line: "Line", reason: str):
line: "Line" super().__init__(f"Error in rule on line {line.line_nr}, column {line.index}: {reason}")
reason: str
self.line = line
self.reason = reason
def pretty_print(self) -> None: def pretty_print(self) -> None:
print(f"Error parsing rule on line {self.line.line_nr}:") log.error(f"Error parsing rule on line {self.line.line_nr}:")
print(self.line.line) log.error_contd(self.line.line)
spaces = " " * self.line.index spaces = " " * self.line.index
print(f"{spaces}^--- {self.reason}") log.error_contd(f"{spaces}^--- {self.reason}")
class Line: class Line:
@ -170,7 +173,7 @@ class Line:
if self.get() == char: if self.get() == char:
self.advance() self.advance()
else: else:
raise RuleParseException(self, f"Expected {char!r}") raise RuleParseError(self, f"Expected {char!r}")
QUOTATION_MARKS = {'"', "'"} QUOTATION_MARKS = {'"', "'"}
@ -186,7 +189,7 @@ def parse_string_literal(line: Line) -> str:
if quotation_mark not in QUOTATION_MARKS: if quotation_mark not in QUOTATION_MARKS:
# This should never happen as long as this function is only called from # This should never happen as long as this function is only called from
# parse_string. # parse_string.
raise RuleParseException(line, "Invalid quotation mark") raise RuleParseError(line, "Invalid quotation mark")
line.advance() line.advance()
while c := line.get(): while c := line.get():
@ -204,7 +207,7 @@ def parse_string_literal(line: Line) -> str:
else: else:
line.advance() 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: def parse_until_space_or_eol(line: Line) -> str:
@ -235,12 +238,12 @@ def parse_arrow(line: Line) -> str:
while True: while True:
c = line.get() c = line.get()
if not c: if not c:
raise RuleParseException(line, "Expected rest of arrow") raise RuleParseError(line, "Expected rest of arrow")
elif c == "-": elif c == "-":
line.advance() line.advance()
c = line.get() c = line.get()
if not c: if not c:
raise RuleParseException(line, "Expected rest of arrow") raise RuleParseError(line, "Expected rest of arrow")
elif c == ">": elif c == ">":
line.advance() line.advance()
break # End of arrow break # End of arrow
@ -267,7 +270,7 @@ def parse_rule(line: Line) -> Rule:
left = parse_string(line) left = parse_string(line)
if isinstance(left, bool): if isinstance(left, bool):
line.index = leftindex line.index = leftindex
raise RuleParseException(line, "Left side can't be '!'") raise RuleParseError(line, "Left side can't be '!'")
# Parse arrow # Parse arrow
parse_whitespace(line) parse_whitespace(line)
@ -301,7 +304,7 @@ def parse_rule(line: Line) -> Rule:
return NameRule(ReRule(left, right)) return NameRule(ReRule(left, right))
else: else:
line.index = arrowindex + 1 # For nicer error message line.index = arrowindex + 1 # For nicer error message
raise RuleParseException(line, "Invalid arrow name") raise RuleParseError(line, "Invalid arrow name")
class Transformer: class Transformer: