Created
August 16, 2024 04:18
-
-
Save andydude/3c0dbe962c8b723a9547702bba21a76c to your computer and use it in GitHub Desktop.
Hex0 assembler in python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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