multiple parse errors

This commit is contained in:
Irmen de Jong 2018-01-01 05:49:12 +01:00
parent 6922ea2a0b
commit 50db122525

View File

@ -93,6 +93,7 @@ class Parser:
self.ppsymbols = ppsymbols # symboltable from preprocess phase self.ppsymbols = ppsymbols # symboltable from preprocess phase
self.print_block_parsing = True self.print_block_parsing = True
self.existing_imports = existing_imports self.existing_imports = existing_imports
self.parse_errors = 0
def load_source(self, filename: str) -> List[Tuple[int, str]]: def load_source(self, filename: str) -> List[Tuple[int, str]]:
with open(filename, "rU") as source: with open(filename, "rU") as source:
@ -115,22 +116,9 @@ class Parser:
def parse(self) -> Optional[ParseResult]: def parse(self) -> Optional[ParseResult]:
# start the parsing # start the parsing
try: try:
return self.parse_file() result = self.parse_file()
except ParseError as x: except ParseError as x:
if sys.stderr.isatty(): self.handle_parse_error(x)
print("\x1b[1m", file=sys.stderr)
print("", file=sys.stderr)
if x.sourcetext:
print("\tsource text: '{:s}'".format(x.sourcetext), file=sys.stderr)
if x.sourceref.column:
print("\t" + ' '*x.sourceref.column + ' ^', file=sys.stderr)
if self.parsing_import:
print("Error (in imported file):", str(x), file=sys.stderr)
else:
print("Error:", str(x), file=sys.stderr)
if sys.stderr.isatty():
print("\x1b[0m", file=sys.stderr)
raise # XXX temporary solution to get stack trace info in the event of parse errors
except Exception as x: except Exception as x:
if sys.stderr.isatty(): if sys.stderr.isatty():
print("\x1b[1m", file=sys.stderr) print("\x1b[1m", file=sys.stderr)
@ -140,8 +128,27 @@ class Parser:
else: else:
print(" file:", self.sourceref.file, file=sys.stderr) print(" file:", self.sourceref.file, file=sys.stderr)
if sys.stderr.isatty(): if sys.stderr.isatty():
print("\x1b[0m", file=sys.stderr) print("\x1b[0m", file=sys.stderr, end="", flush=True)
raise # XXX temporary solution to get stack trace info in the event of parse errors raise
if self.parse_errors:
self.print_bold("\nNo output; there were {:d} errors in file {:s}\n".format(self.parse_errors, self.sourceref.file))
raise SystemExit(1)
return result
def handle_parse_error(self, exc: ParseError) -> None:
self.parse_errors += 1
if sys.stderr.isatty():
print("\x1b[1m", file=sys.stderr)
if exc.sourcetext:
print("\t" + exc.sourcetext, file=sys.stderr)
if exc.sourceref.column:
print("\t" + ' ' * exc.sourceref.column + ' ^', file=sys.stderr)
if self.parsing_import:
print("Error (in imported file):", str(exc), file=sys.stderr)
else:
print("Error:", str(exc), file=sys.stderr)
if sys.stderr.isatty():
print("\x1b[0m", file=sys.stderr, end="", flush=True)
def parse_file(self) -> ParseResult: def parse_file(self) -> ParseResult:
print("\nparsing", self.sourceref.file) print("\nparsing", self.sourceref.file)
@ -155,7 +162,7 @@ class Parser:
def print_bold(self, text: str) -> None: def print_bold(self, text: str) -> None:
if sys.stdout.isatty(): if sys.stdout.isatty():
print("\x1b[1m" + text + "\x1b[0m") print("\x1b[1m" + text + "\x1b[0m", flush=True)
else: else:
print(text) print(text)
@ -584,17 +591,26 @@ class Parser:
else: else:
raise self.PError("invalid statement in block") raise self.PError("invalid statement in block")
while True: while True:
try:
go_on, resultblock = self._parse_block_statement(is_zp_block)
if not go_on:
return resultblock
except ParseError as x:
self.handle_parse_error(x)
def _parse_block_statement(self, is_zp_block: bool) -> Tuple[bool, Optional[Block]]:
# parse the statements inside a block
self._parse_comments() self._parse_comments()
line = self.next_line() line = self.next_line()
unstripped_line = line unstripped_line = line
line = line.strip() line = line.strip()
if line == "}": if line == "}":
if is_zp_block and any(b.name == "ZP" for b in self.result.blocks): if is_zp_block and any(b.name == "ZP" for b in self.result.blocks):
return None # we already have the ZP block return False, None # we already have the ZP block
if self.cur_block.ignore: if self.cur_block.ignore:
self.print_warning("ignoring block without name and address", self.cur_block.sourceref) self.print_warning("ignoring block without name and address", self.cur_block.sourceref)
return None return False, None
return self.cur_block return False, self.cur_block
if line.startswith(("var ", "var\t")): if line.startswith(("var ", "var\t")):
self.parse_var_def(line) self.parse_var_def(line)
elif line.startswith(("const ", "const\t")): elif line.startswith(("const ", "const\t")):
@ -627,6 +643,7 @@ class Parser:
self.parse_label(line) self.parse_label(line)
else: else:
raise self.PError("invalid statement in block") raise self.PError("invalid statement in block")
return True, None # continue with more statements
def parse_label(self, line: str) -> None: def parse_label(self, line: str) -> None:
label_line = line.split(maxsplit=1) label_line = line.split(maxsplit=1)