""" This syntax highlighter is modified from the following code: https://wiki.python.org/moin/PyQt/Python%20syntax%20highlighting License: https://directory.fsf.org/wiki/License:BSD-3-Clause """ from PyQt5.QtCore import QRegExp from PyQt5.QtGui import QColor, QTextCharFormat, QFont, QSyntaxHighlighter def format(color, style=""): """Return a QTextCharFormat with the given attributes.""" _color = QColor() _color.setNamedColor(color) _format = QTextCharFormat() _format.setForeground(_color) if "bold" in style: _format.setFontWeight(QFont.Bold) if "italic" in style: _format.setFontItalic(True) return _format # Syntax styles STYLES = { "instr_general": format("lightGreen"), "instr_cmp": format("green"), "instr_branch": format("green"), "instr_arith": format("darkOrange"), "instr_vm": format("red", "bold"), "keywords_vm": format("darkMagenta"), "instr_stack": format("lightBlue"), "instr_bitwise": format("red"), "operator": format("red"), "brace": format("darkMagenta"), "comment": format("darkGreen", "italic"), "numbers": format("brown"), } class AsmHighlighter(QSyntaxHighlighter): """Syntax highlighter for the x86 ASM language.""" instr_general = ["mov", "movzx", "movsx", "movsx", "lea"] instr_cmp = ["cmp", "test"] instr_branch = ["jmp", "call"] instr_arith = ["add", "sub", "dec", "inc", "mul"] instr_vm = ["nor", "load", "exit", "enter", "init"] instr_stack = ["push", "pushad", "pushfd", "pushal", "pop", "popfd"] instr_bitwise = ["xor", "and", "or", "shl", "shr", "bswap", "rol", "ror", "neg", "not", "btc", "bts", ] # Operators operators = [ "=", # Comparison "==", "!=", "<", "<=", ">", ">=", # Arithmetic "\+", "-", "\*", "/", "//", "\%", "\*\*", # In-place "\+=", "-=", "\*=", "/=", "\%=", # Bitwise "\^", "\|", "\&", "\~", ">>", "<<", ] # Braces braces = ["\[", "\]"] def __init__(self, document): QSyntaxHighlighter.__init__(self, document) rules = [] # Keyword, operator, and brace rules rules += [ (r"\b%s\b" % w, 0, STYLES["instr_general"]) for w in AsmHighlighter.instr_general ] rules += [ (r"\b%s\b" % w, 0, STYLES["instr_cmp"]) for w in AsmHighlighter.instr_cmp ] rules += [ (r"\b%s\b" % w, 0, STYLES["instr_branch"]) for w in AsmHighlighter.instr_branch ] rules += [ (r"\b%s\b" % w, 0, STYLES["instr_arith"]) for w in AsmHighlighter.instr_arith ] rules += [ (r"\b%s\b" % w, 0, STYLES["instr_vm"]) for w in AsmHighlighter.instr_vm ] rules += [ (r"\b%s\b" % w, 0, STYLES["instr_stack"]) for w in AsmHighlighter.instr_stack ] rules += [ (r"\b%s\b" % w, 0, STYLES["instr_bitwise"]) for w in AsmHighlighter.instr_bitwise ] rules += [(r"%s" % o, 0, STYLES["operator"]) for o in AsmHighlighter.operators] rules += [(r"%s" % b, 0, STYLES["brace"]) for b in AsmHighlighter.braces] # All other rules rules += [ # Numeric literals (r"\b[+-]?[0-9]+[lL]?\b", 0, STYLES["numbers"]), (r"\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b", 0, STYLES["numbers"]), (r"\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b", 0, STYLES["numbers"]), # From 'vm_' until a space or a comma (r"vm_[^ ,]*", 0, STYLES["keywords_vm"]), # From '#' until a newline (r"#[^\n]*", 0, STYLES["comment"]), # From ';' until a newline (r";[^\n]*", 0, STYLES["comment"]), ] # Build a QRegExp for each pattern self.rules = [(QRegExp(pat), index, fmt) for (pat, index, fmt) in rules] def highlightBlock(self, text): """Apply syntax highlighting to the given block of text.""" # Do other syntax formatting for expression, nth, format in self.rules: index = expression.indexIn(text, 0) while index >= 0: # We actually want the index of the nth match index = expression.pos(nth) length = len(expression.cap(nth)) self.setFormat(index, length, format) index = expression.indexIn(text, index + length) self.setCurrentBlockState(0)