Commit 7e680e4a authored by Taddeus Kroes's avatar Taddeus Kroes

Updated printer format, also added inline comments as an option instead of a separate command.

parent 0285fcca
...@@ -79,11 +79,12 @@ def p_line_instruction(p): ...@@ -79,11 +79,12 @@ def p_line_instruction(p):
def p_line_comment(p): def p_line_comment(p):
'line : COMMENT NEWLINE' 'line : COMMENT NEWLINE'
statements.append(S('comment', p[1], inline=False)) statements.append(S('comment', p[1]))
def p_line_inline_comment(p): def p_line_inline_comment(p):
'line : instruction COMMENT NEWLINE' 'line : instruction COMMENT NEWLINE'
statements.append(S('comment', p[2], inline=True)) # Add the inline comment to the last parsed statement
statements[-1].options['comment'] = p[2]
def p_instruction_command(p): def p_instruction_command(p):
'instruction : command' 'instruction : command'
......
...@@ -38,12 +38,12 @@ class Statement: ...@@ -38,12 +38,12 @@ class Statement:
def __repr__(self): # pragma: nocover def __repr__(self): # pragma: nocover
return str(self) return str(self)
def has_inline_comment(self):
return 'comment' in self.options and len(self.options['comment'])
def is_comment(self): def is_comment(self):
return self.stype == 'comment' return self.stype == 'comment'
def is_inline_comment(self):
return self.is_comment() and self.options['inline']
def is_directive(self): def is_directive(self):
return self.stype == 'directive' return self.stype == 'directive'
......
from math import ceil from math import ceil
TABSIZE = 4 # Size in spaces of a single tab
INLINE_COMMENT_LEVEL = 6 # Number of tabs to inline commment level
COMMAND_SIZE = 8 # Default length of a command name, used for
# indenting
ADD_COMMENT_BLOCKS = True # Wether to add newlines before and after
# non-inline comment
ADD_ARGUMENT_SPACE = False # Wether to add a space between command arguments
# and the previous comma
def write_statements(statements): def write_statements(statements):
"""Write a list of statements to valid assembly code.""" """Write a list of statements to valid assembly code."""
out = '' out = ''
indent_level = 0 indent_level = 0
prevline = '' prev_comment = False
for i, s in enumerate(statements): for i, s in enumerate(statements):
newline = '\n' if i else '' current_comment = False
if s.is_label(): if s.is_label():
line = s.name + ':' line = s.name + ':'
indent_level = 1 indent_level = 1
elif s.is_comment(): elif s.is_comment():
line = '#' + s.name line = '\t' * indent_level + '#' + s.name
current_comment = True
if s.is_inline_comment():
l = len(prevline.expandtabs(4))
tabs = int(ceil((24 - l) / 4.)) + 1
newline = '\t' * tabs
else:
line = '\t' * indent_level + line
elif s.is_directive(): elif s.is_directive():
line = '\t' + s.name line = '\t' + s.name
elif s.is_command(): elif s.is_command():
line = '\t' + s.name line = '\t' + s.name
# If there are arguments, add tabs until the 8 character limit has
# been reached. If the command name is 8 or more characers long,
# add a single space
if len(s): if len(s):
if len(s.name) < 8: l = len(s.name)
line += '\t'
if l < COMMAND_SIZE:
line += '\t' * int(ceil((COMMAND_SIZE - l)
/ float(TABSIZE)))
else: else:
line += ' ' line += ' '
line += ','.join(map(str, s)) delim = ', ' if ADD_ARGUMENT_SPACE else ','
line += delim.join(map(str, s))
else: else:
raise Exception('Unsupported statement type "%s"' % s.stype) raise Exception('Unsupported statement type "%s"' % s.stype)
out += newline + line # Add the inline comment, if there is any
prevline = line if s.has_inline_comment():
start = INLINE_COMMENT_LEVEL * TABSIZE
diff = start - len(line.expandtabs(TABSIZE))
# Add newline at end of file # The comment must not be directly adjacent to the command itself
tabs = int(ceil(diff / float(TABSIZE))) + 1 if diff > 0 else 1
line += '\t' * tabs + '#' + s.options['comment']
# Add newline at end of command
line += '\n'
if ADD_COMMENT_BLOCKS:
if prev_comment ^ current_comment:
out += '\n' out += '\n'
out += line
prev_comment = current_comment
return out return out
def write_to_file(filename, statements): def write_to_file(filename, statements):
"""Convert a list of statements to valid assembly code and write it to a """Convert a list of statements to valid assembly code and write it to a
file.""" file."""
......
...@@ -36,9 +36,10 @@ class TestStatement(unittest.TestCase): ...@@ -36,9 +36,10 @@ class TestStatement(unittest.TestCase):
self.assertFalse(S('comment', 'foo', inline=False).is_label()) self.assertFalse(S('comment', 'foo', inline=False).is_label())
self.assertFalse(S('directive', 'foo').is_command()) self.assertFalse(S('directive', 'foo').is_command())
def test_is_inline_comment(self): def test_has_inline_comment(self):
self.assertTrue(S('comment', 'foo', inline=True).is_inline_comment()) self.assertTrue(S('comment', 'foo', comment='bar').has_inline_comment())
self.assertFalse(S('comment', 'foo', inline=False).is_inline_comment()) self.assertFalse(S('comment', 'foo', comment='').has_inline_comment())
self.assertFalse(S('comment', 'foo').has_inline_comment())
def test_jump_target(self): def test_jump_target(self):
self.assertEqual(S('command', 'j', 'foo').jump_target(), 'foo') self.assertEqual(S('command', 'j', 'foo').jump_target(), 'foo')
...@@ -165,5 +166,5 @@ class TestStatement(unittest.TestCase): ...@@ -165,5 +166,5 @@ class TestStatement(unittest.TestCase):
self.assertEqual(S('command', 'c.lt.d', '$1', '$2').get_use(), arg2) self.assertEqual(S('command', 'c.lt.d', '$1', '$2').get_use(), arg2)
self.assertEqual(S('command', 'bgez', '$1', '$2').get_use(), arg1) self.assertEqual(S('command', 'bgez', '$1', '$2').get_use(), arg1)
self.assertEqual(S('command', 'bltz', '$1', '$2').get_use(), arg1) self.assertEqual(S('command', 'bltz', '$1', '$2').get_use(), arg1)
self.assertEqual(S('command', 'trunc.w.d', '$3', '$1', '$2').get_use()\ self.assertEqual(S('command', 'trunc.w.d', '$3', '$1', '$2').get_use(),
, arg2) arg2)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment