fixed some bugs in the assembler
This commit is contained in:
@@ -108,24 +108,20 @@ class Assembler(object):
|
||||
if(token in self._marks):
|
||||
if(self._marks[token]["target"] != -1):
|
||||
raise ParsingError("Error in line {} column {} mark already defined: '{}'. Previous was in line {}.".format(
|
||||
self._line
|
||||
self._file_context._line
|
||||
, self._column
|
||||
, token
|
||||
, self._marks[token]["target_line"]))
|
||||
self._marks[token]["target"] = self._word_count
|
||||
self._marks[token]["target_line"] = self._line
|
||||
self._marks[token]["target_line"] = self._file_context._line
|
||||
|
||||
else:
|
||||
self._marks[token] = {
|
||||
"target": self._word_count
|
||||
, "target_line": self._line
|
||||
, "target_line": self._file_context._line
|
||||
, "references": []
|
||||
}
|
||||
|
||||
should_be_newline = next(self._tokenizer)
|
||||
if(should_be_newline != "\n"):
|
||||
self.raise_unexpected_token(token, "newline", should_be_newline)
|
||||
|
||||
|
||||
def parse_directive(self):
|
||||
should_be_name = next(self._tokenizer)
|
||||
@@ -133,6 +129,10 @@ class Assembler(object):
|
||||
if(not should_be_name in self._directives):
|
||||
self.raise_unexpected_token(".", "directive name", should_be_name)
|
||||
|
||||
should_be_whitespace = next(self._tokenizer)
|
||||
if(not should_be_whitespace in WHITESPACE):
|
||||
self.raise_unexpected_token(should_be_name, "' '", should_be_whitespace)
|
||||
|
||||
words = self._directives[should_be_name].parse(self, self._tokenizer)
|
||||
|
||||
self._word_count += len(words)
|
||||
@@ -146,16 +146,16 @@ class Assembler(object):
|
||||
|
||||
|
||||
def parse_command(self, cmd):
|
||||
|
||||
self._code_objects.append(self._opcodes[cmd])
|
||||
self._word_count += 1
|
||||
|
||||
# We have no arguments
|
||||
if(not self._commands_by_mnemonic[cmd]["args"]):
|
||||
self._code_objects.append(self._opcodes[cmd])
|
||||
self._word_count += 1
|
||||
token = next(self._tokenizer)
|
||||
if(token != "\n"):
|
||||
self.raise_unexpected_token(cmd, "newline", token)
|
||||
return
|
||||
|
||||
# Small argument must be treated separately
|
||||
should_be_whitespace = next(self._tokenizer)
|
||||
if(should_be_whitespace not in WHITESPACE
|
||||
or should_be_whitespace == "\n"):
|
||||
@@ -166,9 +166,12 @@ class Assembler(object):
|
||||
, should_be_an_argument
|
||||
, self._commands_by_mnemonic[cmd]["args"][0])
|
||||
self._word_count += 1
|
||||
self._code_objects.append(argument)
|
||||
# NOTE:
|
||||
# The Small Argument is stored within the first word (!)
|
||||
self._code_objects.append(self._opcodes[cmd] | (argument & 0xffff))
|
||||
|
||||
|
||||
# All the 16bit arguments
|
||||
for argument in self._commands_by_mnemonic[cmd]["args"][1:]:
|
||||
should_be_comma = next(self._tokenizer)
|
||||
if(should_be_comma != ","):
|
||||
@@ -239,22 +242,31 @@ class Assembler(object):
|
||||
return argument
|
||||
|
||||
if(argument_definition == "program_memory"):
|
||||
# Non-integer Argument.
|
||||
if(not can_convert_to_int(argument)):
|
||||
# Just nonsense.
|
||||
if(not can_be_mark(argument)):
|
||||
self.raise_unexpected_token(cmd, "integer address or mark", argument)
|
||||
# The Mark has appeared before.
|
||||
if(argument in self._marks):
|
||||
self._marks[argument]["references"].append(self._line)
|
||||
# Add this line to the references.
|
||||
self._marks[argument]["references"].append(self._file_context._line)
|
||||
# The target is already known. Insert it now.
|
||||
if(self._marks[argument]["target"] != -1):
|
||||
return self._marks[argument]["target"]
|
||||
# The target is unknown.
|
||||
return argument
|
||||
# The Mark has not appeared before.
|
||||
self._marks[argument] = {
|
||||
"target": -1
|
||||
, "target_line": 0
|
||||
, "references": [self._line]
|
||||
, "references": [self._file_context._line]
|
||||
}
|
||||
# Target is obviously unknown.
|
||||
return argument
|
||||
|
||||
|
||||
# Integer argument.
|
||||
argument = autoint(argument)
|
||||
|
||||
if(argument < 0 or argument > self._memory_definition["program_memory"]):
|
||||
@@ -264,17 +276,29 @@ class Assembler(object):
|
||||
, argument)
|
||||
return argument
|
||||
|
||||
# This is direct input (default).
|
||||
|
||||
# Integer
|
||||
if(can_convert_to_int(argument)):
|
||||
return autoint(argument)
|
||||
|
||||
# This is nonsense.
|
||||
if(not can_be_mark(argument)):
|
||||
self.raise_unexpected_token(cmd, "integer, char or mark", argument)
|
||||
if(argument in self._marks and self._marks[argument] >= 0):
|
||||
return self._marks[argument]
|
||||
self._marks[argument] = -1
|
||||
|
||||
# It is a Mark.
|
||||
if(argument in self._marks):
|
||||
if(self._marks[argument]["target"] >= 0):
|
||||
self._marks[argument]["references"].append(self._file_context._line)
|
||||
return self._marks[argument]["target"]
|
||||
self._marks[argument]["references"].append(self._file_context._line)
|
||||
return argument
|
||||
|
||||
self._marks[argument] = {
|
||||
"target": -1
|
||||
, "target_line": 0
|
||||
, "references": [self._file_context._line]
|
||||
}
|
||||
|
||||
return argument
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -5,6 +5,8 @@ Directives for explicitly modifying the program memory.
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import deque
|
||||
|
||||
from .util import can_convert_to_int, autoint
|
||||
|
||||
class AbstractDirective(ABC):
|
||||
@abstractmethod
|
||||
def parse(self, assembler, tokenizer):
|
||||
|
Reference in New Issue
Block a user