summaryrefslogtreecommitdiff
path: root/nandgame/assembler
diff options
context:
space:
mode:
authoruvok2026-01-12 19:49:04 +0100
committeruvok2026-01-12 19:52:26 +0100
commit87e878548d475c21999a2be1a0aaa89485d5ede2 (patch)
treeb9be8a85777aadc1593bbc48472dd37e9680de57 /nandgame/assembler
parent8912777281a8fee34254d2c070d922836660c208 (diff)
py: Reformat files with black
Diffstat (limited to 'nandgame/assembler')
-rwxr-xr-xnandgame/assembler/createbin.py19
-rwxr-xr-xnandgame/assembler/disas.py3
-rwxr-xr-xnandgame/assembler/disas_ins.py4
-rwxr-xr-xnandgame/assembler/lexer.py52
-rwxr-xr-xnandgame/assembler/parser.py64
-rwxr-xr-xnandgame/assembler/tlexer.py10
-rwxr-xr-xnandgame/assembler/tparser.py8
7 files changed, 95 insertions, 65 deletions
diff --git a/nandgame/assembler/createbin.py b/nandgame/assembler/createbin.py
index c8559a5..9f1105d 100755
--- a/nandgame/assembler/createbin.py
+++ b/nandgame/assembler/createbin.py
@@ -6,25 +6,27 @@ or rather, 15-bit, to have valid
nandgame instructions, skip reserved bits.
"""
-#ENDIANNESS = 'big'
-ENDIANNESS = 'little'
+# ENDIANNESS = 'big'
+ENDIANNESS = "little"
+
def main():
with open("allins.bin", "wb") as f:
- ins=0x0000
+ ins = 0x0000
# ldi A, 0
- f.write(ins.to_bytes(2, byteorder = ENDIANNESS))
+ f.write(ins.to_bytes(2, byteorder=ENDIANNESS))
- ins=0x00ff
+ ins = 0x00FF
# ldi A, 255
- f.write(ins.to_bytes(2, byteorder = ENDIANNESS))
+ f.write(ins.to_bytes(2, byteorder=ENDIANNESS))
- for ins in range(0x8000, 0xffff + 1):
+ for ins in range(0x8000, 0xFFFF + 1):
# unused bytes, force 1
if (ins & 0x6800) != 0x6800:
continue
- f.write(ins.to_bytes(2, byteorder = ENDIANNESS))
+ f.write(ins.to_bytes(2, byteorder=ENDIANNESS))
+
import sys
@@ -36,4 +38,3 @@ if __name__ == "__main__":
ENDIANNESS = "big"
print(f"Use Endianness: {ENDIANNESS}")
main()
-
diff --git a/nandgame/assembler/disas.py b/nandgame/assembler/disas.py
index dc27ad5..9353bb5 100755
--- a/nandgame/assembler/disas.py
+++ b/nandgame/assembler/disas.py
@@ -17,6 +17,7 @@ JUMPS_IF_ZERO = ["jge", "jle", "jeq", "jmp"]
ENDIANNESS = "little"
+
def decode_jump(ins: int) -> str:
if (ins & 0x7) == 0:
return JUMP_NONE
@@ -138,7 +139,7 @@ def fixup_ins(ins: int) -> list[str]:
# fixups
if op1 == ZERO:
# subtract something from #0 - subtraction
- if mnemonic == "sub":
+ if mnemonic == "sub":
return ["neg", dest, op2, "", jumpdest]
# 0 AND something = 0
diff --git a/nandgame/assembler/disas_ins.py b/nandgame/assembler/disas_ins.py
index f7eb265..4841087 100755
--- a/nandgame/assembler/disas_ins.py
+++ b/nandgame/assembler/disas_ins.py
@@ -11,7 +11,7 @@ if __name__ == "__main__":
ins_hex = sys.argv[1]
insb = bytes.fromhex(ins_hex)
- if (len(insb) != 2):
+ if len(insb) != 2:
print("Invalid instruction")
sys.exit(1)
ins = int.from_bytes(insb)
@@ -22,4 +22,4 @@ if __name__ == "__main__":
line = f"\t{raw_ins}\t{decoded_ins}"
else:
line = f"\t{raw_ins}\t{decoded_ins2:<25}; {decoded_ins}"
- print(line) \ No newline at end of file
+ print(line)
diff --git a/nandgame/assembler/lexer.py b/nandgame/assembler/lexer.py
index e716af8..d0c9462 100755
--- a/nandgame/assembler/lexer.py
+++ b/nandgame/assembler/lexer.py
@@ -4,68 +4,79 @@ import ply.lex as lex
# List of token names. This is always required
tokens = (
- 'OP',
- 'JUMP',
- 'COMMA',
- 'COLON',
- 'SYMBOL',
- 'NUMBER',
- 'HEXNUMBER',
- 'DOT',
- 'REG',
- 'NL'
+ "OP",
+ "JUMP",
+ "COMMA",
+ "COLON",
+ "SYMBOL",
+ "NUMBER",
+ "HEXNUMBER",
+ "DOT",
+ "REG",
+ "NL",
)
# Regular expression rules for simple tokens
-t_COMMA = r','
-t_COLON = r':'
-t_DOT = r'\.'
+t_COMMA = r","
+t_COLON = r":"
+t_DOT = r"\."
+
def t_OP(t):
r"mov|and|dec|hlt|add|sub|inc"
return t
+
def t_REG(t):
r"\b(AD?M?|DM?|M|_)\b"
return t
+
def t_JUMP(t):
r"jmp|jlt|jgt|jle|jge|jeq|jne"
return t
+
def t_NUMBER(t):
- r'\#\d+'
+ r"\#\d+"
t.value = int(t.value[1:])
return t
+
def t_HEXNUMBER(t):
- r'\#0x[0-9a-fA-F]+'
+ r"\#0x[0-9a-fA-F]+"
t.value = int(t.value[1:], 16)
return t
+
def t_SYMBOL(t):
- r'[a-z][A-Za-z0-9_]+'
+ r"[a-z][A-Za-z0-9_]+"
return t
+
# Define a rule so we can track line numbers
def t_NL(t):
- r'\n+'
+ r"\n+"
t.lexer.lineno += len(t.value)
return t
+
# A string containing ignored characters (spaces and tabs)
-t_ignore = ' \t'
-#t_ignore_COMMENT = r';.*'
+t_ignore = " \t"
+# t_ignore_COMMENT = r';.*'
+
def t_COMMENT(t):
- r';.*'
+ r";.*"
pass
+
# Error handling rule
def t_error(t):
print("!!! Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
+
# EOF handling rule
def t_eof(t):
if not t.lexer.newline_added:
@@ -74,6 +85,7 @@ def t_eof(t):
return t.lexer.token()
return None
+
# Build the lexer
lexer = lex.lex()
lexer.newline_added = False
diff --git a/nandgame/assembler/parser.py b/nandgame/assembler/parser.py
index 8925f3f..9e4bf45 100755
--- a/nandgame/assembler/parser.py
+++ b/nandgame/assembler/parser.py
@@ -10,25 +10,30 @@ from lexer import tokens
# Error rule for syntax errors
+
def p_error(p: LexToken):
if p:
print(f"Unexpected {repr(p.value)} on line {p.lineno}")
else:
print("Unexpected end of file.")
+
def p_program(p):
- '''program : instruction_list
- | empty'''
+ """program : instruction_list
+ | empty
+ """
pass
+
def p_empty(p):
- '''empty :'''
+ """empty :"""
pass
+
def p_inss(p):
- '''instruction_list : instruction_list line
+ """instruction_list : instruction_list line
| line
- '''
+ """
if len(p) == 2:
p[0] = [p[1]]
else:
@@ -40,10 +45,11 @@ def p_inss(p):
# print(f" {p[2]}")
pass
+
def p_inss2(p):
- '''instruction_list2 : line instruction_list2
+ """instruction_list2 : line instruction_list2
| line
- '''
+ """
if len(p) == 2:
p[0] = [p[1]]
else:
@@ -55,62 +61,71 @@ def p_inss2(p):
print(f" {p[2]}")
pass
+
def p_line(p):
- '''line : instruction NL
+ """line : instruction NL
| NL
- '''
+ """
if len(p) == 2:
pass
else:
p[0] = p[1]
+
def p_instruction(p):
- '''instruction : noarg
+ """instruction : noarg
| onearg
| twoarg
| jumpdest
| invalid_arg
- '''
- print(f"INS: {p[1]}")
+ """
+ print(f"Item: {p[1]}")
p[0] = p[1]
pass
+
def p_jumpdest(p):
- '''jumpdest : SYMBOL COLON'''
- p[0] = (p[1], )
+ """jumpdest : SYMBOL COLON"""
+ p[0] = (p[1],)
+
def p_twoarg(p):
- '''twoarg : op REG COMMA argument COMMA argument'''
+ """twoarg : op REG COMMA argument COMMA argument"""
p[0] = (*p[1], p[2], p[4], p[6])
pass
+
def p_argument(p):
- '''argument : number
+ """argument : number
| REG
| SYMBOL
- '''
+ """
pass
+
def p_onearg(p):
- '''onearg : op REG COMMA argument'''
+ """onearg : op REG COMMA argument"""
p[0] = (*p[1], p[2], p[4], None)
pass
+
def p_noarg(p):
- '''noarg : op'''
+ """noarg : op"""
p[0] = (*p[1], None, None, None)
pass
+
def p_invalid_arg(p):
- '''invalid_arg : op argument'''
+ """invalid_arg : op argument"""
print(f"Invalid opcode, destination missing: {p[1:]}")
sys.exit(1)
pass
+
def p_op(p):
- '''op : OP DOT JUMP
+ """op : OP DOT JUMP
| OP
- '''
+ """
if len(p) == 2:
p[0] = (p[1], None)
else:
@@ -118,9 +133,10 @@ def p_op(p):
def p_number(p):
- '''number : NUMBER
+ """number : NUMBER
| HEXNUMBER
- '''
+ """
p[0] = p[1]
+
parser = yacc.yacc()
diff --git a/nandgame/assembler/tlexer.py b/nandgame/assembler/tlexer.py
index 7830299..a285401 100755
--- a/nandgame/assembler/tlexer.py
+++ b/nandgame/assembler/tlexer.py
@@ -4,13 +4,13 @@ import sys
from lexer import lexer
-with open(sys.argv[1], 'rb') as f:
- data = f.read()
- data2 = data.decode('ascii')
- lexer.input(data2)
+with open(sys.argv[1], "rb") as f:
+ data = f.read()
+ data2 = data.decode("ascii")
+ lexer.input(data2)
while True:
tok = lexer.token()
if not tok:
- break # No more input
+ break
print(tok)
diff --git a/nandgame/assembler/tparser.py b/nandgame/assembler/tparser.py
index 0f35a50..b1697ed 100755
--- a/nandgame/assembler/tparser.py
+++ b/nandgame/assembler/tparser.py
@@ -4,7 +4,7 @@ import sys
from parser import parser
-with open(sys.argv[1], 'rb') as f:
- data = f.read()
- data2 = data.decode('ascii')
- parser.parse(data2, tracking=True)
+with open(sys.argv[1], "rb") as f:
+ data = f.read()
+ data2 = data.decode("ascii")
+ parser.parse(data2, tracking=True)