1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-02-19 20:30:45 +00:00

Clean up driver code, add filename to error messages.

This commit is contained in:
Chris Pressey 2018-03-27 15:55:29 +01:00
parent 3f0e36a67c
commit d9e625db30
4 changed files with 82 additions and 80 deletions

View File

@ -1,7 +1,7 @@
SixtyPical
==========
_Version 0.14. Work-in-progress, everything is subject to change._
_Version 0.15. Work-in-progress, everything is subject to change._
**SixtyPical** is a 6502-like programming language with advanced
static analysis.

View File

@ -24,6 +24,66 @@ from sixtypical.emitter import Emitter, Byte, Word
from sixtypical.compiler import Compiler
def process_input_files(filenames, options):
programs = []
for filename in options.filenames:
text = open(filename).read()
parser = Parser(text, filename)
program = parser.program()
programs.append(program)
if options.parse_only:
return
#program = merge_programs(programs)
program = programs[0]
analyzer = Analyzer(debug=options.debug)
analyzer.analyze_program(program)
if options.analyze_only:
return
fh = sys.stdout
if options.origin.startswith('0x'):
start_addr = int(options.origin, 16)
else:
start_addr = int(options.origin, 10)
output_format = options.output_format
prelude = []
if options.prelude == 'c64':
output_format = 'prg'
start_addr = 0x0801
prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32,
0x30, 0x36, 0x31, 0x00, 0x00, 0x00]
elif options.prelude == 'vic20':
output_format = 'prg'
start_addr = 0x1001
prelude = [0x0b, 0x10, 0xc9, 0x07, 0x9e, 0x34,
0x31, 0x30, 0x39, 0x00, 0x00, 0x00]
elif options.prelude:
raise NotImplementedError("Unknown prelude: {}".format(options.prelude))
# If we are outputting a .PRG, we output the load address first.
# We don't use the Emitter for this b/c not part of addr space.
if output_format == 'prg':
fh.write(Word(start_addr).serialize(0))
emitter = Emitter(start_addr)
for byte in prelude:
emitter.emit(Byte(byte))
compiler = Compiler(emitter)
compiler.compile_program(program)
if options.debug:
pprint(emitter.accum)
else:
emitter.serialize(fh)
if __name__ == '__main__':
argparser = ArgumentParser(__doc__.strip())
@ -72,69 +132,11 @@ if __name__ == '__main__':
options, unknown = argparser.parse_known_args(sys.argv[1:])
remainder = ' '.join(unknown)
for filename in options.filenames:
text = open(filename).read()
try:
parser = Parser(text)
program = parser.program()
except Exception as e:
if options.traceback:
raise
else:
traceback.print_exception(e.__class__, e, None)
sys.exit(1)
if options.parse_only:
sys.exit(0)
try:
analyzer = Analyzer(debug=options.debug)
analyzer.analyze_program(program)
except Exception as e:
if options.traceback:
raise
else:
traceback.print_exception(e.__class__, e, None)
sys.exit(1)
if options.analyze_only:
sys.exit(0)
fh = sys.stdout
if options.origin.startswith('0x'):
start_addr = int(options.origin, 16)
try:
process_input_files(options.filenames, options)
except Exception as e:
if options.traceback:
raise
else:
start_addr = int(options.origin, 10)
output_format = options.output_format
prelude = []
if options.prelude == 'c64':
output_format = 'prg'
start_addr = 0x0801
prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32,
0x30, 0x36, 0x31, 0x00, 0x00, 0x00]
elif options.prelude == 'vic20':
output_format = 'prg'
start_addr = 0x1001
prelude = [0x0b, 0x10, 0xc9, 0x07, 0x9e, 0x34,
0x31, 0x30, 0x39, 0x00, 0x00, 0x00]
elif options.prelude:
raise NotImplementedError("Unknown prelude: {}".format(options.prelude))
# If we are outputting a .PRG, we output the load address first.
# We don't use the Emitter for this b/c not part of addr space.
if output_format == 'prg':
fh.write(Word(start_addr).serialize(0))
emitter = Emitter(start_addr)
for byte in prelude:
emitter.emit(Byte(byte))
compiler = Compiler(emitter)
compiler.compile_program(program)
if options.debug:
pprint(emitter.accum)
else:
emitter.serialize(fh)
traceback.print_exception(e.__class__, e, None)
sys.exit(1)

View File

@ -6,7 +6,7 @@ from sixtypical.model import (
RoutineType, VectorType, TableType, BufferType, PointerType,
LocationRef, ConstantRef, IndirectRef, IndexedRef, AddressRef,
)
from sixtypical.scanner import Scanner, SixtyPicalSyntaxError
from sixtypical.scanner import Scanner
class SymEntry(object):
@ -19,8 +19,8 @@ class SymEntry(object):
class Parser(object):
def __init__(self, text):
self.scanner = Scanner(text)
def __init__(self, text, filename):
self.scanner = Scanner(text, filename)
self.symbols = {} # token -> SymEntry
self.current_statics = {} # token -> SymEntry
self.typedefs = {} # token -> Type AST
@ -32,7 +32,7 @@ class Parser(object):
self.backpatch_instrs = []
def syntax_error(self, msg):
raise SixtyPicalSyntaxError(self.scanner.line_number, msg)
self.scanner.syntax_error(msg)
def soft_lookup(self, name):
if name in self.current_statics:

View File

@ -4,16 +4,17 @@ import re
class SixtyPicalSyntaxError(ValueError):
def __init__(self, line_number, message):
super(SixtyPicalSyntaxError, self).__init__(line_number, message)
def __init__(self, filename, line_number, message):
super(SixtyPicalSyntaxError, self).__init__(filename, line_number, message)
def __str__(self):
return "Line {}: {}".format(self.args[0], self.args[1])
return "{}, line {}: {}".format(self.args[0], self.args[1], self.args[2])
class Scanner(object):
def __init__(self, text):
def __init__(self, text, filename):
self.text = text
self.filename = filename
self.token = None
self.type = None
self.line_number = 1
@ -62,9 +63,7 @@ class Scanner(object):
if self.token == token:
self.scan()
else:
raise SixtyPicalSyntaxError(self.line_number, "Expected '{}', but found '{}'".format(
token, self.token
))
self.syntax_error("Expected '{}', but found '{}'".format(token, self.token))
def on(self, *tokens):
return self.token in tokens
@ -74,9 +73,7 @@ class Scanner(object):
def check_type(self, type):
if not self.type == type:
raise SixtyPicalSyntaxError(self.line_number, "Expected {}, but found '{}'".format(
self.type, self.token
))
self.syntax_error("Expected {}, but found '{}'".format(self.type, self.token))
def consume(self, token):
if self.token == token:
@ -84,3 +81,6 @@ class Scanner(object):
return True
else:
return False
def syntax_error(self, msg):
raise SixtyPicalSyntaxError(self.filename, self.line_number, msg)