2013-09-29 3 views
3

Вступление немного длинное, поэтому, пожалуйста, несите меня. :)Регулярное выражение для синтаксического анализа аналогичных инструкций ассемблера

Я пишу простой парсер, основанный на регулярном выражении, для большого исходного файла, написанного на ассемблере. Большинство этих инструкций просто перемещаются, добавляются, вычитаются и перескакивают, но это довольно большой файл, который мне нужно переносить на два разных языка, и я слишком ленив, чтобы сделать это вручную. Это требование, и я не могу много сделать »(так что, пожалуйста, не отвечайте на такие вещи, как« почему бы вам просто не использовать ANTLR »).

Итак, после выполнения некоторой предварительной обработки (я уже выполнил эту часть: заменил define и макросы и разделил лишние пробелы и комментарии), теперь я в основном должен читать файл по строкам и анализировать один или потенциально больше строк в " промежуточных "инструкций, которые я буду использовать для создания более или менее эквивалента 1 к 1 (с использованием фактической целочисленной арифметики и группы GOTO).

Таким образом, предполагая, что я могу иметь все эти различные режимы адресации:

Addressing mode depends on the format of the instruction

Я могу пойти двумя различными способами:

  1. имеют единый МОВ регулярное выражение, которое будет обрабатывать все эти случаи , или
  2. Имеются несколько регулярных выражений MOV для каждого типа инструкции. Проблема с этим подходом заключается в том, что я должен был тщательно спроектировать каждое регулярное выражение, чтобы избежать какой-либо двусмысленности. И похоже, что будет много дубликатов, поскольку операнды источника и адресата разделяют многие режимы адресации.

Мой вопрос: если у меня есть одно регулярное выражение для всех инструкций, как я должен указывать свои группы и записи, чтобы иметь возможность просто различать разные режимы?

Или я просто поймаю все, а затем обработаю адрес источника/получателя после начального совпадения?

E.g. довольно простой матч-все регулярное выражение будет:

^MOV\s+(?<dest>[^\s,]+)[\s,]*(?<src>[^\s,]+)$ 

(Разделить на несколько строк с комментариями):

^MOV    (?#instruction) 
\s+    (?#some whitespace) 
(?<dest>[^\s,]+) (?#match everything except whitespace and comma) 
\s*,\s*   (?#match comma, allow some whitespace) 
(?<src>[^\s,]+) (?#match everything except whitespace and comma)$ 

Итак, я, безусловно, может сделать это, а затем обработать dest и src группы отдельно. Но было бы лучше создать неприятное сложное регулярное выражение для соответствия всем случаям из таблицы ниже? В этом случае я не уверен, как я буду интерпретировать эти снимки, чтобы понять, какой режим адресации был согласован.

Я использую C#, если это имеет значение.

+1

Не пытайтесь всегда решать такую ​​проблему с ** просто чистым Regex **, на самом деле нам нужно больше ** предварительной обработки и постобработки **, кроме вывода, которое может вывести Regex. –

+0

Почему бы не просто разобрать его сверху вниз? .. зачем нужно регулярное выражение? –

+0

Хм, ваши комментарии имеют смысл, я, вероятно, слишком задумываюсь об этом. Дело в том, что у меня уже есть множество регулярных выражений для других инструкций, которые быстрее мне писать и тестировать, чем повторять по символам вручную, но для этих инструкций с несколькими вариантами (например, MOV), вероятно, лучше всего просто сопоставить код операции и затем проанализируйте оставшуюся часть, используя пару if-clauses. – Lou

ответ

1

Вы обнаруживаете, что происходит, когда вы пытаетесь принести лексера заданию на парсера. Большая часть ваших трудностей, я думаю, заключается в попытке сделать слишком много с регулярными выражениями.

И да, я собираюсь предложить парсер, такой как ANTLR или его эквивалент.

Если вы пошли по этому маршруту, вы должны написать много маленьких регулярных выражений, чтобы идентифицировать токены («MOV», «#», «[», ...), а затем вы должны написать грамматику, которая определила как они составляют инструкции. Если ничего другого, это упрощает простое создание парсинговой части.

Вы можете увидеть, что представляет собой ассемблерный код looks like. (Использует систему, отличную от ANTLR, но идеи одинаковы). Это было довольно просто написать, и не было никакой агонии в попытке написать «Одно правило», чтобы исправить их всех. [Я сделал этот пример вечером и использовал его для анализа довольно большого набора источников].

Вы не понимали, что означает «порт». Предположительно, вы перейдете к другому синтаксису ассемблера, если не к другой машинной архитектуре. Для этого вам понадобится доступ к различным разделам инструкций (которые не дает вам отдельного регулярного выражения для всех возможных инструкций MOV). Вот красота разбора и производства деревьев: все эти части подвержены вам, встроенные в структуру, в которой они принадлежат. Вы даже можете генерировать отдельные инструкции из нескольких операторов языка ассемблера, потому что дерево содержит всю программу. (Скорее большой не означает многого по размеру дерева на системах с гигабайтом ОЗУ).

+0

Хорошо, я думаю, вы правы. Не существует «правильного» способа сделать это так, как я делаю это сейчас, за исключением перехода в другое направление. Неважно, набор инструкций довольно ограничен, поэтому я уже вручную проанализировал типы операндов после согласования двоичной инструкции. – Lou

+0

Я бы сказал, что ANTLR слишком много для этой проблемы. Ваш первый подход выглядит хорошо для меня. –

1

Вот регулярное выражение, которое делает в значительной степени то, что вы хотите (вам нужно будет отредактировать фактические формы данных, т. Е. Вместо всех ярлыков регистров ax, bx, ... Я просто использовал 'reg' и т. Д.)

(?<Opt1>MOV\s*Rw,\sRw) 
|(?<Opt2>MOV\s*Rw,\s\#data4) 
|(?<Opt3>MOV\s*Rw,\s\#data16) 
|(?<Opt4>MOV\s*Rw,\s\[Rw\]) 
|(?<Opt5>MOV\s*Rw,\s\[Rw\+\]) 
|(?<Opt6>MOV\s*\[Rw\],\sRw) 
|(?<Opt7>MOV\s*\[-Rw\],\sRw) 
|(?<Opt8>MOV\s*\[Rw\],\s\[Rw\]) 
|(?<Opt9>MOV\s*\[Rw\+\],\s\[Rw\]) 
|(?<OptA>MOV\s*\[Rw\],\s\[Rw\+\]) 

используя эти данные:

MOV Rw, Rw 
MOV Rw, #data4 
MOV Rw, #data16 
MOV Rw, [Rw] 
MOV Rw, [Rw+] 
MOV [Rw], Rw 
MOV [-Rw], Rw 
MOV [Rw], [Rw] 
MOV [Rw+], [Rw] 
MOV [Rw], [Rw+] 

RegexBuddy генерирует это:

Match 1: MOV Rw, Rw  0  10 
Group "Opt1": MOV Rw, Rw  0  10 
Group "Opt2" did not participate in the match 
Group "Opt3" did not participate in the match 
Group "Opt4" did not participate in the match 
Group "Opt5" did not participate in the match 
Group "Opt6" did not participate in the match 
Group "Opt7" did not participate in the match 
Group "Opt8" did not participate in the match 
Group "Opt9" did not participate in the match 
Group "OptA" did not participate in the match 
Match 2: MOV Rw, #data4  12  14 
Group "Opt1" did not participate in the match 
Group "Opt2": MOV Rw, #data4  12  14 
Group "Opt3" did not participate in the match 
Group "Opt4" did not participate in the match 
Group "Opt5" did not participate in the match 
Group "Opt6" did not participate in the match 
Group "Opt7" did not participate in the match 
Group "Opt8" did not participate in the match 
Group "Opt9" did not participate in the match 
Group "OptA" did not participate in the match 
Match 3: MOV Rw, #data16  28  15 
Group "Opt1" did not participate in the match 
Group "Opt2" did not participate in the match 
Group "Opt3": MOV Rw, #data16  28  15 
Group "Opt4" did not participate in the match 
Group "Opt5" did not participate in the match 
Group "Opt6" did not participate in the match 
Group "Opt7" did not participate in the match 
Group "Opt8" did not participate in the match 
Group "Opt9" did not participate in the match 
Group "OptA" did not participate in the match 
Match 4: MOV Rw, [Rw]  45  12 
Group "Opt1" did not participate in the match 
Group "Opt2" did not participate in the match 
Group "Opt3" did not participate in the match 
Group "Opt4": MOV Rw, [Rw]  45  12 
Group "Opt5" did not participate in the match 
Group "Opt6" did not participate in the match 
Group "Opt7" did not participate in the match 
Group "Opt8" did not participate in the match 
Group "Opt9" did not participate in the match 
Group "OptA" did not participate in the match 
Match 5: MOV Rw, [Rw+]  59  13 
Group "Opt1" did not participate in the match 
Group "Opt2" did not participate in the match 
Group "Opt3" did not participate in the match 
Group "Opt4" did not participate in the match 
Group "Opt5": MOV Rw, [Rw+]  59  13 
Group "Opt6" did not participate in the match 
Group "Opt7" did not participate in the match 
Group "Opt8" did not participate in the match 
Group "Opt9" did not participate in the match 
Group "OptA" did not participate in the match 
Match 6: MOV [Rw], Rw  74  12 
Group "Opt1" did not participate in the match 
Group "Opt2" did not participate in the match 
Group "Opt3" did not participate in the match 
Group "Opt4" did not participate in the match 
Group "Opt5" did not participate in the match 
Group "Opt6": MOV [Rw], Rw  74  12 
Group "Opt7" did not participate in the match 
Group "Opt8" did not participate in the match 
Group "Opt9" did not participate in the match 
Group "OptA" did not participate in the match 
Match 7: MOV [-Rw], Rw  88  13 
Group "Opt1" did not participate in the match 
Group "Opt2" did not participate in the match 
Group "Opt3" did not participate in the match 
Group "Opt4" did not participate in the match 
Group "Opt5" did not participate in the match 
Group "Opt6" did not participate in the match 
Group "Opt7": MOV [-Rw], Rw  88  13 
Group "Opt8" did not participate in the match 
Group "Opt9" did not participate in the match 
Group "OptA" did not participate in the match 
Match 8: MOV [Rw], [Rw]  103  14 
Group "Opt1" did not participate in the match 
Group "Opt2" did not participate in the match 
Group "Opt3" did not participate in the match 
Group "Opt4" did not participate in the match 
Group "Opt5" did not participate in the match 
Group "Opt6" did not participate in the match 
Group "Opt7" did not participate in the match 
Group "Opt8": MOV [Rw], [Rw]  103  14 
Group "Opt9" did not participate in the match 
Group "OptA" did not participate in the match 
Match 9: MOV [Rw+], [Rw] 119  15 
Group "Opt1" did not participate in the match 
Group "Opt2" did not participate in the match 
Group "Opt3" did not participate in the match 
Group "Opt4" did not participate in the match 
Group "Opt5" did not participate in the match 
Group "Opt6" did not participate in the match 
Group "Opt7" did not participate in the match 
Group "Opt8" did not participate in the match 
Group "Opt9": MOV [Rw+], [Rw] 119  15 
Group "OptA" did not participate in the match 
Match 10: MOV [Rw], [Rw+] 136  15 
Group "Opt1" did not participate in the match 
Group "Opt2" did not participate in the match 
Group "Opt3" did not participate in the match 
Group "Opt4" did not participate in the match 
Group "Opt5" did not participate in the match 
Group "Opt6" did not participate in the match 
Group "Opt7" did not participate in the match 
Group "Opt8" did not participate in the match 
Group "Opt9" did not participate in the match 
Group "OptA": MOV [Rw], [Rw+] 136  15 
Смежные вопросы