Der Texteditor meiner Wahl zur Zeit ist Sublime Text 2. Leider kann er von Haus aus kein MIPS und eine Syntaxdefinition dafür habe ich auch nicht gefunden. Hier stelle ich meine erste Version einer Sprachbeschreibung für MIPS-Assembler vor, die auch für Sublime benutzt werden kann.

Syntax

MIPS-Assembler lässt sich angenehmerweise Zeilenweise definieren. In einer Zeile kann ein Label, ein Befehl, eine Direktive und ein Kommentar sein.

Ein Label besteht aus Text und einem Doppelpunkt.

Ein Befehl kann R-, I- oder J-Typ sein. Dabei bestehen R-Typ-Befehle aus Namen und drei Registern, I-Typ-Befehle aus einem Namen, zwei Registern und einem Direktoperanden und J-Typ-Befehle aus dem Namen und einem Direktoperand.

Semantik

Semantik wird in Sublime (wie auch in vielen anderen Editoren) mit Textdarstellung vermittelt. Diese Textdarstellung hängt von einer Vorgabe ab, die einem Textelement (z.B. “function”) einen Scope (z.B. “storage.type”) zuordnet.

Um den syntaktischen Elementen eine Semantik zuzuordnen, liest man hier nach, was TextMate unterstützt - Sublime benutzt nämlich die selben Scopes. Nützlich scheinen

  • comment.line für Kommentare
  • constant.numeric für Zahlen
  • constant.character für einzelne Zeichen als Direktoperand
  • support.function für Befehlsnamen
  • variable.language für die Registernamen

Daraus wird ein Schuh.

Regexen

Für das spätere Matching brauchen wir Reguläre Ausdrücke, damit wir z.B. sagen können “Alles was auf den regluären Ausdruck ‘x’ zutrifft, ist ein Kommentar.”

Kommentare fangen einem Leerzeichen mit einem ‘#’ an und gehen bis zum Zeilenende:

#(.)*$

Registernamen fangen mit einem Dollar an, danach kommt entweder der Name oder die Nummer von 0 - 31. (Wobei wir z.B. $04 als Registernamen nicht erlauben wollen!) Letzteres sieht so aus:

\$(3[01])|([12]?[0-9])|[0-9]

Ersteres so:

\$(zero|at|v[01]|a[0-3]|s[0-7]|t[0-9]|k[01]|gp|sp|fp|ra)

Also einfach endliche Fallunterscheidungen, die beiden kann man auch noch zusammenbauen:

\$(((3[01])|([12]?[0-9])|[0-9])|zero|at|v[01]|a[0-3]|s[0-7]|t[0-9]|k[01]|gp|sp|fp|ra)

Ähnlich spannend geht es mit den Befehlen, diese hänge ich der Einfachheit aneinander und trimme mit \b Whitespaces davor und dahinter:

\b(add|addu|addi|addiu|sub|subu|and|andi|or|not|ori|nor|xor|xori|slt|sltu|slti|sltiu|sll|sllv|rol|srl|sra|srlv|ror|j|jr|jal|beq|bne|lw|sw|lui|move|mfhi|mflo|mthi|mtlo)\b

Bei Zahlen haben wir auch wieder verschiedene Möglichkeiten, wie diese eingegeben sind, entweder Hexadezimal (also mit vorgestelltem 0x):

0(x|X)[0-9A-Fa-f]*

oder Dezimal, dafür evtl auch negativ

(\-)?[0-9]*

Wieder zusammengebaut und Leerzeichen getrimmt:

\b(0(x|X)[0-9A-Fa-f]*|(\-)?[0-9]*)\b