mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
multiple parse errors
This commit is contained in:
parent
6922ea2a0b
commit
50db122525
139
il65/parse.py
139
il65/parse.py
@ -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,49 +591,59 @@ class Parser:
|
|||||||
else:
|
else:
|
||||||
raise self.PError("invalid statement in block")
|
raise self.PError("invalid statement in block")
|
||||||
while True:
|
while True:
|
||||||
self._parse_comments()
|
try:
|
||||||
line = self.next_line()
|
go_on, resultblock = self._parse_block_statement(is_zp_block)
|
||||||
unstripped_line = line
|
if not go_on:
|
||||||
line = line.strip()
|
return resultblock
|
||||||
if line == "}":
|
except ParseError as x:
|
||||||
if is_zp_block and any(b.name == "ZP" for b in self.result.blocks):
|
self.handle_parse_error(x)
|
||||||
return None # we already have the ZP block
|
|
||||||
if self.cur_block.ignore:
|
def _parse_block_statement(self, is_zp_block: bool) -> Tuple[bool, Optional[Block]]:
|
||||||
self.print_warning("ignoring block without name and address", self.cur_block.sourceref)
|
# parse the statements inside a block
|
||||||
return None
|
self._parse_comments()
|
||||||
return self.cur_block
|
line = self.next_line()
|
||||||
if line.startswith(("var ", "var\t")):
|
unstripped_line = line
|
||||||
self.parse_var_def(line)
|
line = line.strip()
|
||||||
elif line.startswith(("const ", "const\t")):
|
if line == "}":
|
||||||
self.parse_const_def(line)
|
if is_zp_block and any(b.name == "ZP" for b in self.result.blocks):
|
||||||
elif line.startswith(("memory ", "memory\t")):
|
return False, None # we already have the ZP block
|
||||||
self.parse_memory_def(line, is_zp_block)
|
if self.cur_block.ignore:
|
||||||
elif line.startswith(("sub ", "sub\t")):
|
self.print_warning("ignoring block without name and address", self.cur_block.sourceref)
|
||||||
if is_zp_block:
|
return False, None
|
||||||
raise self.PError("ZP block cannot contain subroutines")
|
return False, self.cur_block
|
||||||
self.parse_subroutine_def(line)
|
if line.startswith(("var ", "var\t")):
|
||||||
elif line.startswith(("asminclude ", "asminclude\t", "asmbinary ", "asmbinary\t")):
|
self.parse_var_def(line)
|
||||||
if is_zp_block:
|
elif line.startswith(("const ", "const\t")):
|
||||||
raise self.PError("ZP block cannot contain assembler directives")
|
self.parse_const_def(line)
|
||||||
self.cur_block.statements.append(self.parse_asminclude(line))
|
elif line.startswith(("memory ", "memory\t")):
|
||||||
elif line.startswith(("asm ", "asm\t")):
|
self.parse_memory_def(line, is_zp_block)
|
||||||
if is_zp_block:
|
elif line.startswith(("sub ", "sub\t")):
|
||||||
raise self.PError("ZP block cannot contain code statements")
|
if is_zp_block:
|
||||||
self.prev_line()
|
raise self.PError("ZP block cannot contain subroutines")
|
||||||
self.cur_block.statements.append(self.parse_asm())
|
self.parse_subroutine_def(line)
|
||||||
elif line == "breakpoint":
|
elif line.startswith(("asminclude ", "asminclude\t", "asmbinary ", "asmbinary\t")):
|
||||||
self.cur_block.statements.append(BreakpointStmt(self.sourceref))
|
if is_zp_block:
|
||||||
self.print_warning("breakpoint defined")
|
raise self.PError("ZP block cannot contain assembler directives")
|
||||||
elif unstripped_line.startswith((" ", "\t")):
|
self.cur_block.statements.append(self.parse_asminclude(line))
|
||||||
if is_zp_block:
|
elif line.startswith(("asm ", "asm\t")):
|
||||||
raise self.PError("ZP block cannot contain code statements")
|
if is_zp_block:
|
||||||
self.cur_block.statements.append(self.parse_statement(line))
|
raise self.PError("ZP block cannot contain code statements")
|
||||||
elif line:
|
self.prev_line()
|
||||||
if is_zp_block:
|
self.cur_block.statements.append(self.parse_asm())
|
||||||
raise self.PError("ZP block cannot contain code labels")
|
elif line == "breakpoint":
|
||||||
self.parse_label(line)
|
self.cur_block.statements.append(BreakpointStmt(self.sourceref))
|
||||||
else:
|
self.print_warning("breakpoint defined")
|
||||||
raise self.PError("invalid statement in block")
|
elif unstripped_line.startswith((" ", "\t")):
|
||||||
|
if is_zp_block:
|
||||||
|
raise self.PError("ZP block cannot contain code statements")
|
||||||
|
self.cur_block.statements.append(self.parse_statement(line))
|
||||||
|
elif line:
|
||||||
|
if is_zp_block:
|
||||||
|
raise self.PError("ZP block cannot contain code labels")
|
||||||
|
self.parse_label(line)
|
||||||
|
else:
|
||||||
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user