mirror of
https://github.com/Garmelon/PFERD.git
synced 2023-12-21 10:23:01 +01:00
Improve transformer error handling
This commit is contained in:
parent
662191eca9
commit
1bbc0b705f
@ -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")
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user