регулярное выражение для перехвата C-команды ассемблера

Я прохожу курс Нанд-2-Тетрис. Нас просят написать и на ассемблере. C-команда имеет тип dest=comp;jump, где каждая часть является необязательной.

Я пытался написать регулярное выражение, чтобы все упростить - я хочу иметь возможность скомпилировать выражение в заданной строке и просто по номеру группы узнать, какую часть выражения я использую. Например, для выражения: A=M+1;JMP я хочу получить group(1) = A, group(2) = M и group(3) = JMP.

Моя проблема в том, что каждая часть не является обязательной, поэтому я точно не знаю, как написать это регулярное выражение. Пока что я придумал:

(A?M?D?)\s=([^;\s]*)\s?(?=;[\s]*([a-zA-Z]{1,4})|$)

Это работает в большинстве случаев, но не так, как я ожидаю. Например, отсутствие компа не сработает (D;JGT). Я пробовал положительный взгляд вперед, но это не сработало.


person Dvir Itzko    schedule 02.10.2016    source источник
comment
Ассемблер — это парсер, и хотя регулярное выражение, безусловно, может быть инструментом, который вы используете, это не единственная проблема.   -  person Tim Biegeleisen    schedule 02.10.2016
comment
Согласовано. Это похоже на случай, когда все, что у вас есть, это молоток, любая проблема выглядит как гвоздь. Regex — мощный инструмент, но его использование для такого рода задач требует затрат вашего времени и времени тех, кто должен читать ваш код.   -  person MadOverlord    schedule 02.10.2016


Ответы (2)


RegEx, который вы ищете, выглядит следующим образом:

(?P<dest>[AMD]{1,3}=)?(?P<comp>[01\-AMD!|+&><]{1,3})(?P<jump>;[JGTEQELNMP]{3})?

Разобьем на части:

  • (?P<dest>[AMD]{1,3}=)? - будет искать необязательный destination для сохранения в нем результата вычислений.
  • (?P<comp>[01\-AMD!|+&><]{1,3}) - будет искать computation инструкцию.
  • (?P<jump>;[JGTEQELNMP]{3})? - будет искать необязательную директиву jump.

Обратите внимание, что dest и jump части каждого C-Instruction являются необязательными.
Они появляются только с постфиксом = и префиксом ; соответственно.

Следовательно, вам придется позаботиться об этих признаках:

if dest is not None:
    dest = dest.rstrip("=")

if jump is not None:
    jump = jump.lstrip(";")

Наконец, вы получите желаемый C-Instrucion разбор:

Для строки A=A+M;JMP вы получите:

dest = 'A'
comp = 'A+M'
jump = 'JMP'

Для строки D;JGT вы получите:

dest = None
comp = 'D'
jump = 'JGT'

А для строки M=D вы получите:

dest = 'M'
comp = 'D'
jump = None
person Yair    schedule 10.11.2020

Не совсем уверен, что вы хотите сделать, но на основе ваших примеров вы можете сделать регулярное выражение следующим образом:

([\w]+)[=]?([\w])*[+-]*[\w]*;([\w]+)

Затем для этой строки:

A=M+1;JMP

Вы получите следующее:

Full match  A=M+1;JMP
Group 1     A
Group 2     M
Group 3     JMP

И для этой строки:

D;JGT

Ты получишь:

Full match  D;JGT
Group 1     D
Group 3     JGT

См. пример здесь: https://regex101.com/r/v8t4Ma/1.

person Community    schedule 02.10.2016
comment
Этого еще недостаточно. Мне также нужно иметь возможность написать A=M+1, и это должно работать. а также мне также нужно поддерживать такие операции, как !M (отрицать) -M и т. д., поэтому в моем регулярном выражении я не указал, какие символы предопределены для компа, я просто удостоверился, что я заметил что-то, что я не делаю не хочу ([^;\s]) - person Dvir Itzko; 03.10.2016