mirror of
https://github.com/piotr-wiszowaty/foco65.git
synced 2024-10-31 19:04:28 +00:00
support for including files
This commit is contained in:
parent
03f471ba7e
commit
b273e25a17
56
foco65
56
foco65
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
# foco65
|
||||
# Copyright (C) 2014 Piotr Wiszowaty
|
||||
@ -23,42 +23,45 @@ import sys
|
||||
#####
|
||||
|
||||
class StackUnderflow(Exception):
|
||||
def __init__(self, text, line, column):
|
||||
def __init__(self, text, filename, line, column):
|
||||
self.filename = filename
|
||||
self.text = text
|
||||
self.line = line
|
||||
self.column = column
|
||||
|
||||
def __str__(self):
|
||||
return "stack underflow (%d,%d): %s" % (self.line, self.column, self.text)
|
||||
return "stack underflow (%s,%d,%d): %s" % (self.filename, self.line, self.column, self.text)
|
||||
|
||||
|
||||
class StackNotEmpty(Exception):
|
||||
def __init__(self, line, column):
|
||||
def __init__(self, filename, line, column):
|
||||
self.filename = filename
|
||||
self.line = line
|
||||
self.column = column
|
||||
|
||||
def __str__(self):
|
||||
return "stack not empty (%d,%d)" % (self.line, self.column)
|
||||
return "stack not empty (%s,%d,%d)" % (self.filename, self.line, self.column)
|
||||
|
||||
|
||||
class ParseError(Exception):
|
||||
def __init__(self, message, line, column):
|
||||
def __init__(self, message, filename, line, column):
|
||||
self.message = message
|
||||
self.line = line
|
||||
self.column = column
|
||||
self.filename = filename
|
||||
|
||||
def __str__(self):
|
||||
return "%s at line %d column %d" % (self.message, self.line, self.column)
|
||||
return "%s at line %d column %d in file %s" % (self.message, self.line, self.column, self.filename)
|
||||
|
||||
|
||||
class UnknownWord(ParseError):
|
||||
def __init__(self, token):
|
||||
ParseError.__init__(self, "unknown word '%s'" % token.text, token.line, token.column)
|
||||
def __init__(self, filename, token):
|
||||
ParseError.__init__(self, "unknown word '%s'" % token.text, filename, token.line, token.column)
|
||||
|
||||
|
||||
class UnexpectedEndOfStream(ParseError):
|
||||
def __init__(self, line, column):
|
||||
ParseError.__init__(self, "unexpected end of input", line, column)
|
||||
def __init__(self, filename, line, column):
|
||||
ParseError.__init__(self, "unexpected end of input", filename, line, column)
|
||||
|
||||
#####
|
||||
|
||||
@ -116,7 +119,7 @@ class Input:
|
||||
|
||||
def next_char(self):
|
||||
if self.end():
|
||||
raise UnexpectedEndOfStream(self.line, self.column)
|
||||
raise UnexpectedEndOfStream(self.current_file_name, self.line, self.column)
|
||||
c = self.text[self.offset]
|
||||
self.offset += 1
|
||||
if c in self.EOL:
|
||||
@ -285,13 +288,14 @@ class Forth:
|
||||
self.int_prog = re.compile("-?[0-9]+")
|
||||
self.hex_prog = re.compile("\$[0-9A-Fa-f]+")
|
||||
self.state = None
|
||||
self.inputs = []
|
||||
|
||||
def push(self, item):
|
||||
self.stack.append(item)
|
||||
|
||||
def pop(self, token):
|
||||
if not self.stack:
|
||||
raise StackUnderflow(token.text, token.line, token.column)
|
||||
raise StackUnderflow(token.text, self.current_file_name, token.line, token.column)
|
||||
else:
|
||||
return self.stack.pop()
|
||||
|
||||
@ -303,7 +307,7 @@ class Forth:
|
||||
|
||||
def pop_do_loop(self, token):
|
||||
if not self.do_loop_stack:
|
||||
raise StackUnderflow(token.text, token.line, token.column)
|
||||
raise StackUnderflow(token.text, self.current_file_name, token.line, token.column)
|
||||
else:
|
||||
return self.do_loop_stack.pop()
|
||||
|
||||
@ -339,8 +343,9 @@ class Forth:
|
||||
def set_state(self, state):
|
||||
self.state = state
|
||||
|
||||
def parse_input(self, input):
|
||||
def parse_input(self, input, current_file_name):
|
||||
self.input = input
|
||||
self.current_file_name = current_file_name
|
||||
self.set_state("interpret")
|
||||
while not self.input.end():
|
||||
if self.state == "interpret":
|
||||
@ -354,6 +359,13 @@ class Forth:
|
||||
token = self.next()
|
||||
self.word = Word(token.text, self.text_section, label=token.canon())
|
||||
self.set_state("compile")
|
||||
elif token == "[include]":
|
||||
self.inputs.append((self.input, self.current_file_name))
|
||||
include_file_name = self.next().replace('"', '')
|
||||
with open(include_file_name, "rt") as f:
|
||||
self.parse_input(Input(f.read()), include_file_name)
|
||||
self.input, self.current_file_name = self.inputs.pop()
|
||||
|
||||
elif token == "[code]":
|
||||
self.items.append(self.parse_code())
|
||||
elif token == "[text-section]":
|
||||
@ -414,11 +426,11 @@ class Forth:
|
||||
else:
|
||||
self.push(word.name)
|
||||
else:
|
||||
raise UnknownWord(token)
|
||||
raise UnknownWord(self.current_file_name, token)
|
||||
|
||||
def compile(self, word):
|
||||
if self.input.end():
|
||||
raise UnexpectedEndOfStream(self.input.line, self.input.column)
|
||||
raise UnexpectedEndOfStream(self.current_file_name, self.input.line, self.input.column)
|
||||
token = self.next()
|
||||
if token == ";":
|
||||
word.add("exit")
|
||||
@ -519,7 +531,7 @@ class Forth:
|
||||
word.add("lit")
|
||||
word.add(token.text)
|
||||
else:
|
||||
raise UnknownWord(token)
|
||||
raise UnknownWord(self.current_file_name, token)
|
||||
|
||||
def parse_code(self):
|
||||
self.input.mark_start()
|
||||
@ -613,7 +625,7 @@ class Forth:
|
||||
def generate_output(self):
|
||||
self.filter_used_words("main")
|
||||
if self.stack:
|
||||
raise StackNotEmpty(self.input.line, self.input.column)
|
||||
raise StackNotEmpty(self.current_file_name, self.input.line, self.input.column)
|
||||
section_outputs = []
|
||||
for section in self.sections:
|
||||
section_outputs.append("; section %s\n" % section)
|
||||
@ -1952,9 +1964,9 @@ with open(args.file, "rt") as f:
|
||||
f = Forth(args.sections.split(","))
|
||||
|
||||
try:
|
||||
f.parse_input(Input(boot_text % boot_params))
|
||||
f.parse_input(Input(basewords_text))
|
||||
f.parse_input(Input(text))
|
||||
f.parse_input(Input(boot_text % boot_params), "boot_text % boot_params")
|
||||
f.parse_input(Input(basewords_text), "basewords_text")
|
||||
f.parse_input(Input(text), args.file)
|
||||
print f.generate_output()
|
||||
except (ParseError, StackUnderflow, StackNotEmpty) as e:
|
||||
sys.stderr.write("error: %s\n" % str(e))
|
||||
|
Loading…
Reference in New Issue
Block a user