Skip to content

Instantly share code, notes, and snippets.

@andydude
Created August 16, 2024 04:18
Show Gist options
  • Save andydude/3c0dbe962c8b723a9547702bba21a76c to your computer and use it in GitHub Desktop.
Save andydude/3c0dbe962c8b723a9547702bba21a76c to your computer and use it in GitHub Desktop.
Hex0 assembler in python
from dataclasses import dataclass
from typing import List, Tuple
from enum import IntEnum
@dataclass
class ScannerDFA:
class Variable(IntEnum):
EOF = -1
WS = 0
HEX = 1
COM = 2
Alphabet = int # Char
@classmethod
def delta_dfa(cls,
state: Variable,
char: Alphabet) -> Variable:
if char is None:
return cls.Variable.EOF
# for readability
c = chr(char)
# comment state
if state == cls.Variable.COM:
if c == '\n':
return cls.Variable.WS
else:
return cls.Variable.COM
# normal states
if c in ' \t\n':
return cls.Variable.WS
elif c in '#;':
return cls.Variable.COM
elif c.isdigit():
return cls.Variable.HEX
elif c.isalpha() and c in "ABCDEFabcdef":
return cls.Variable.HEX
raise ValueError(c)
@dataclass
class ScannerPDA:
dfa: ScannerDFA
pos: int
input: str
@dataclass
class Token:
state: ScannerDFA.Variable
stack: List[ScannerDFA.Alphabet]
def __init__(self, dfa, pos, input):
type(self).dfac = type(dfa)
self.dfa = dfa
self.pos = pos
self.input = input
self.curToken = ScannerPDA.Token(
ScannerDFA.Variable.WS, [])
type(self).Stack = List[ScannerDFA.Alphabet]
@classmethod
def delta_pda(cls,
token: Token,
char: ScannerDFA.Alphabet) -> Token:
if token.state == cls.dfac.Variable.EOF:
raise StopIteration
oldState = token.state
oldStack = token.stack
token.state = cls.dfac.delta_dfa(
token.state, char)
if char != None:
token.stack.append(char)
if token.state == oldState:
return None
if token.state != cls.dfac.Variable.EOF:
token.stack = [oldStack.pop()]
return cls.Token(oldState, oldStack)
def nextChar(self) -> ScannerDFA.Alphabet:
self.pos += 1
if self.pos >= len(self.input):
return None
char = ord(self.input[self.pos])
return char
def nextToken(self) -> Token:
while True:
char = self.nextChar()
try:
token = type(self).delta_pda(
self.curToken, char)
if token is not None:
return token
except StopIteration:
break
if __name__ == '__main__':
import sys
import binascii
input = sys.stdin.read()
dfa = ScannerDFA()
pda = ScannerPDA(pos=-1, input=input, dfa=dfa)
binout = open("/dev/stdout", "wb")
while True:
token = pda.nextToken()
if token is None:
break
if token.state is ScannerDFA.Variable.HEX:
s = ''.join(list(map(chr, token.stack)))
b = binascii.unhexlify(s)
binout.write(b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment