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
|
# foco65
|
||||||
# Copyright (C) 2014 Piotr Wiszowaty
|
# Copyright (C) 2014 Piotr Wiszowaty
|
||||||
@ -23,42 +23,45 @@ import sys
|
|||||||
#####
|
#####
|
||||||
|
|
||||||
class StackUnderflow(Exception):
|
class StackUnderflow(Exception):
|
||||||
def __init__(self, text, line, column):
|
def __init__(self, text, filename, line, column):
|
||||||
|
self.filename = filename
|
||||||
self.text = text
|
self.text = text
|
||||||
self.line = line
|
self.line = line
|
||||||
self.column = column
|
self.column = column
|
||||||
|
|
||||||
def __str__(self):
|
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):
|
class StackNotEmpty(Exception):
|
||||||
def __init__(self, line, column):
|
def __init__(self, filename, line, column):
|
||||||
|
self.filename = filename
|
||||||
self.line = line
|
self.line = line
|
||||||
self.column = column
|
self.column = column
|
||||||
|
|
||||||
def __str__(self):
|
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):
|
class ParseError(Exception):
|
||||||
def __init__(self, message, line, column):
|
def __init__(self, message, filename, line, column):
|
||||||
self.message = message
|
self.message = message
|
||||||
self.line = line
|
self.line = line
|
||||||
self.column = column
|
self.column = column
|
||||||
|
self.filename = filename
|
||||||
|
|
||||||
def __str__(self):
|
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):
|
class UnknownWord(ParseError):
|
||||||
def __init__(self, token):
|
def __init__(self, filename, token):
|
||||||
ParseError.__init__(self, "unknown word '%s'" % token.text, token.line, token.column)
|
ParseError.__init__(self, "unknown word '%s'" % token.text, filename, token.line, token.column)
|
||||||
|
|
||||||
|
|
||||||
class UnexpectedEndOfStream(ParseError):
|
class UnexpectedEndOfStream(ParseError):
|
||||||
def __init__(self, line, column):
|
def __init__(self, filename, line, column):
|
||||||
ParseError.__init__(self, "unexpected end of input", line, column)
|
ParseError.__init__(self, "unexpected end of input", filename, line, column)
|
||||||
|
|
||||||
#####
|
#####
|
||||||
|
|
||||||
@ -116,7 +119,7 @@ class Input:
|
|||||||
|
|
||||||
def next_char(self):
|
def next_char(self):
|
||||||
if self.end():
|
if self.end():
|
||||||
raise UnexpectedEndOfStream(self.line, self.column)
|
raise UnexpectedEndOfStream(self.current_file_name, self.line, self.column)
|
||||||
c = self.text[self.offset]
|
c = self.text[self.offset]
|
||||||
self.offset += 1
|
self.offset += 1
|
||||||
if c in self.EOL:
|
if c in self.EOL:
|
||||||
@ -285,13 +288,14 @@ class Forth:
|
|||||||
self.int_prog = re.compile("-?[0-9]+")
|
self.int_prog = re.compile("-?[0-9]+")
|
||||||
self.hex_prog = re.compile("\$[0-9A-Fa-f]+")
|
self.hex_prog = re.compile("\$[0-9A-Fa-f]+")
|
||||||
self.state = None
|
self.state = None
|
||||||
|
self.inputs = []
|
||||||
|
|
||||||
def push(self, item):
|
def push(self, item):
|
||||||
self.stack.append(item)
|
self.stack.append(item)
|
||||||
|
|
||||||
def pop(self, token):
|
def pop(self, token):
|
||||||
if not self.stack:
|
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:
|
else:
|
||||||
return self.stack.pop()
|
return self.stack.pop()
|
||||||
|
|
||||||
@ -303,7 +307,7 @@ class Forth:
|
|||||||
|
|
||||||
def pop_do_loop(self, token):
|
def pop_do_loop(self, token):
|
||||||
if not self.do_loop_stack:
|
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:
|
else:
|
||||||
return self.do_loop_stack.pop()
|
return self.do_loop_stack.pop()
|
||||||
|
|
||||||
@ -339,8 +343,9 @@ class Forth:
|
|||||||
def set_state(self, state):
|
def set_state(self, state):
|
||||||
self.state = state
|
self.state = state
|
||||||
|
|
||||||
def parse_input(self, input):
|
def parse_input(self, input, current_file_name):
|
||||||
self.input = input
|
self.input = input
|
||||||
|
self.current_file_name = current_file_name
|
||||||
self.set_state("interpret")
|
self.set_state("interpret")
|
||||||
while not self.input.end():
|
while not self.input.end():
|
||||||
if self.state == "interpret":
|
if self.state == "interpret":
|
||||||
@ -354,6 +359,13 @@ class Forth:
|
|||||||
token = self.next()
|
token = self.next()
|
||||||
self.word = Word(token.text, self.text_section, label=token.canon())
|
self.word = Word(token.text, self.text_section, label=token.canon())
|
||||||
self.set_state("compile")
|
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]":
|
elif token == "[code]":
|
||||||
self.items.append(self.parse_code())
|
self.items.append(self.parse_code())
|
||||||
elif token == "[text-section]":
|
elif token == "[text-section]":
|
||||||
@ -414,11 +426,11 @@ class Forth:
|
|||||||
else:
|
else:
|
||||||
self.push(word.name)
|
self.push(word.name)
|
||||||
else:
|
else:
|
||||||
raise UnknownWord(token)
|
raise UnknownWord(self.current_file_name, token)
|
||||||
|
|
||||||
def compile(self, word):
|
def compile(self, word):
|
||||||
if self.input.end():
|
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()
|
token = self.next()
|
||||||
if token == ";":
|
if token == ";":
|
||||||
word.add("exit")
|
word.add("exit")
|
||||||
@ -519,7 +531,7 @@ class Forth:
|
|||||||
word.add("lit")
|
word.add("lit")
|
||||||
word.add(token.text)
|
word.add(token.text)
|
||||||
else:
|
else:
|
||||||
raise UnknownWord(token)
|
raise UnknownWord(self.current_file_name, token)
|
||||||
|
|
||||||
def parse_code(self):
|
def parse_code(self):
|
||||||
self.input.mark_start()
|
self.input.mark_start()
|
||||||
@ -613,7 +625,7 @@ class Forth:
|
|||||||
def generate_output(self):
|
def generate_output(self):
|
||||||
self.filter_used_words("main")
|
self.filter_used_words("main")
|
||||||
if self.stack:
|
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 = []
|
section_outputs = []
|
||||||
for section in self.sections:
|
for section in self.sections:
|
||||||
section_outputs.append("; section %s\n" % section)
|
section_outputs.append("; section %s\n" % section)
|
||||||
@ -1952,9 +1964,9 @@ with open(args.file, "rt") as f:
|
|||||||
f = Forth(args.sections.split(","))
|
f = Forth(args.sections.split(","))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
f.parse_input(Input(boot_text % boot_params))
|
f.parse_input(Input(boot_text % boot_params), "boot_text % boot_params")
|
||||||
f.parse_input(Input(basewords_text))
|
f.parse_input(Input(basewords_text), "basewords_text")
|
||||||
f.parse_input(Input(text))
|
f.parse_input(Input(text), args.file)
|
||||||
print f.generate_output()
|
print f.generate_output()
|
||||||
except (ParseError, StackUnderflow, StackNotEmpty) as e:
|
except (ParseError, StackUnderflow, StackNotEmpty) as e:
|
||||||
sys.stderr.write("error: %s\n" % str(e))
|
sys.stderr.write("error: %s\n" % str(e))
|
||||||
|
Loading…
Reference in New Issue
Block a user