Смекни!
smekni.com

Структура и реализация макроязыков (стр. 3 из 4)

Наш ал­го­ритм бу­дет вы­пол­нять 2 сис­те­ма­ти­че­ских про­смот­ра вход­но­го тек­ста. В пер­вый про­ход бу­дут де­тер­ми­ни­ро­ва­ны все мак­ро­оп­ре­де­ле­ния, во вто­рой про­ход бу­дут от­кры­ты все ссыл­ки на мак­ро­сы. Так же, как и язык ас­семб­ле­ра не мо­жет вы­пол­нить ссыл­ку на сим­вол до то­го мо­мен­та, как он встре­тит этот сим­вол, язык мак­ро­ко­манд не мо­жет вы­пол­нить рас­ши­ре­ние до тех пор, по­ка не встре­тит со­от­вет­ст­вую­щее мак­ро­оп­ре­де­ле­ние. Во вре­мя пер­во­го про­смот­ра про­ве­ря­ет­ся ка­ж­дый код опе­ра­ции, мак­ро­оп­ре­де­ле­ния за­по­ми­на­ют­ся в таб­ли­це мак­ро­оп­ре­де­ле­ний, а ко­пия ис­ход­но­го тек­ста без мак­ро­оп­ре­де­ле­ний за­по­ми­на­ет­ся во внеш­ней па­мя­ти, для ис­поль­зо­ва­ния ее при вто­ром про­хо­де. По­ми­мо таб­ли­цы мак­ро­оп­ре­де­ле­ний во вре­мя пер­во­го про­хо­да бу­дет так­же таб­ли­ца имен, во вто­рой про­ход она бу­дет ис­поль­зо­вать­ся для вы­де­ле­ния мак­ро­опе­ра­ций и рас­ши­ре­ния их до тек­ста со­от­вет­ст­вую­ще­го мак­ро­оп­ре­де­ле­ния.

ДАН­НЫЕ ДЛЯ ПЕР­ВО­ГО ПРО­СМОТ­РА

1. ВХТ - Вход­ной текст

2. ВЫХ1 - Вы­ход­ная ко­пия тек­ста для ис­поль­зо­ва­ния во вто­рой про­ход.

3. МДТ - таб­ли­ца мак­ро­оп­ре­де­ле­ний, в ко­то­рой хра­нят­ся те­ла мак­ро­оп­ре­де­ле­ний

4. МНТ - таблица имен, не­об­хо­ди­мая для хра­не­ния имен мак­ро­ко­манд, оп­ре­де­лен­ных в МНТ

5. МДТС - счет­чик для таб­ли­цы МДТ

6. МНТС - счет­чик для таб­ли­цы МНТ

7. АЛА - мас­сив спи­ска па­ра­мет­ров для под­ста­нов­ки ин­декс­ных мар­ке­ров вме­сто фор­маль­ных па­ра­мет­ров, пе­ред за­по­ми­на­ни­ем оп­ре­де­ле­ния.

ДАН­НЫЕ ДЛЯ ВТО­РО­ГО ПРО­СМОТ­РА

1. ВЫХ1 - Вы­ход­ная ко­пия тек­ста по­сле­ пер­во­го про­хо­да

2. ВЫХ2 - Вы­ход­ная ко­пия тек­ста по­сле­ второ­го про­хо­да

3. МДТ - таб­ли­ца мак­ро­оп­ре­де­ле­ний, в ко­то­рой хра­нят­ся те­ла мак­ро­оп­ре­де­ле­ний

4. МНТ - таблица имен, не­об­хо­ди­мая для хра­не­ния имен мак­ро­ко­манд, оп­ре­де­лен­ных в МНТ

5. МДТС - счет­чик для таб­ли­цы МДТ

6. МНТС - счет­чик для таб­ли­цы МНТ

7. АЛА - мас­сив спи­ска па­ра­мет­ров для под­ста­нов­ки ин­декс­ных мар­ке­ров вме­сто фор­маль­ных па­ра­мет­ров, пе­ред за­по­ми­на­ни­ем оп­ре­де­ле­ния.


АЛГОРИТМ

Ни­же при­ве­де­на фор­маль­ная за­пись со­от­вет­ст­вую­щих ал­го­рит­мов об­ра­бот­ки мак­ро­оп­ре­де­ле­ний двух­про­смот­ро­вым спо­со­бом.

Ка­ж­дый из ал­го­рит­мов осу­ще­ст­в­ля­ет по­строч­ный про­смотр вход­но­го тек­ста.

ПЕР­ВЫЙ ПРО­СМОТР - МАК­РО­ОП­РЕ­ДЕ­ЛЕ­НИЯ: Ал­го­ритм пер­во­го про­смот­ра про­ве­ря­ет ка­ж­дую стро­ку вход­но­го тек­ста. Ес­ли она пред­став­ля­ет со­бой псев­до­опе­ра­цию MACRO, то все сле­дую­щие за ней стро­ки за­по­ми­на­ют­ся в бли­жай­ших сво­бод­ных ячей­ках МДТ. Пер­вая стро­ка мак­ро­оп­ре­де­ле­ния - это имя са­мо­го мак­ро­са. Имя за­но­сит­ся в таблицу имен МНТ с ин­дек­сом этой стро­ки в МДТ. При этом про­ис­хо­дит так­же под­ста­нов­ка но­ме­ров фор­маль­ных па­ра­мет­ров, вме­сто их имен. Ес­ли в те­че­ние про­смот­ра встре­ча­ет­ся ко­ман­да END, то это оз­на­ча­ет, что весь текст об­ра­бо­тан, и управ­ле­ние мож­но пе­ре­да­вать вто­ро­му про­смот­ру для об­ра­бот­ки мак­ро­ко­манд.

ВТО­РОЙ ПРО­СМОТР - РАС­ШИ­РЕ­НИЕ МАК­РО­КО­МАНД: Ал­го­ритм вто­ро­го про­смот­ра про­ве­ря­ет мне­мо­ни­че­ский код ка­ж­до­го пред­ло­же­ния. Ес­ли это имя со­дер­жит­ся в МНТ, то про­ис­хо­дит об­ра­бот­ка мак­ро­пред­ло­же­ния по сле­дую­ще­му пра­ви­лу: из таб­ли­цы МНТ бе­рет­ся ука­за­тель на на­ча­ло опи­са­ния мак­ро­са в МДТ. Макропроцессор го­то­вит мас­сив спи­ска АЛА со­дер­жа­щий таб­ли­цу ин­дек­сов фор­маль­ных па­ра­мет­ров и со­от­вет­ст­вую­щих опе­ран­дов мак­ро­ко­ман­ды. Чте­ние про­из­во­дит­ся из МДТ, по­сле че­го в про­чи­тан­ную стро­ку под­став­ля­ют­ся не­об­хо­ди­мые па­ра­мет­ры, и по­лу­чен­ная та­ким об­ра­зом стро­ка за­пи­сы­ва­ет­ся в ВЫХТ2. Ко­гда встре­ча­ет­ся ди­рек­ти­ва END, текст по­лу­чен­но­го ко­да пе­ре­да­ет­ся для ком­пи­ля­ции ас­семб­ле­ру.


Пер­вый про­смотр

На­ча­ло ал­го­рит­ма

МДТС = 0

МНТС = 0

ФЛАГ ВЫХОДА = 0

цикл по­ка (ФЛАГ ВЫХОДА == 0) {

чтение следующей строки ВХТ

если !(операция MACRO) {

вывод строки в ВЫХТ1

если (операция END) ФЛАГ ВЫХОДА = 1

}

иначе {

чтение идентификатора

запись имени и индекса в МНТ

МНТС ++

приготовить массив списка АЛА

запись имени в МДТ

МДТС ++

цикл {

чтение следующей строки ВХТ

подстановка индекса операторов

добавление в МДТ

МДТС ++

} пока !(операция MEND)

}

}

переход ко второму проходу

конец алгоритма


Второй просмотр

Начало алгоритма

ФЛАГ ВЫХОДА = 0

цикл пока (ФЛАГ ВЫХОДА == 0) {

чтение строки из ВЫХТ1

НАЙДЕНО = поиск кода в МНТ

если !(НАЙДЕНО) {

запись в ВЫХТ2 строки

если (операция END) {

ФЛАГ ВЫХОДА = 1

}

}

иначе {

УКАЗАТЕЛЬ = индекс из МНТ

Заполнение списка параметров АЛА

цикл {

УКАЗАТЕЛЬ ++

чтение след. строки из МДТ

подстановка параметров

вывод в ВЫХТ2

} пока !(операция MEND)

}

}

переход к компиляции

конец алгоритма


ОДНОПРОСМОТРОВЫЙ АЛГОРИТМ

Предположим, что мы допускаем реализацию макроопределения внутри макроопределений. Основная проблема здесь заключена в том, что внутреннее макро определено только после того, как выполнен вызов внешнего. Для обеспечения использования внутреннего макро нам придется повторять как просмотр обработки макроопределений, так и просмотр обработки макрокоманд. Однако существует и еще одно решение, которое позволяет произвести распознавание и расширение в один просмотр.

Рассмотрим аналогию с ассемблером. Макроопределение должно обрабатываться до обработки макрокоманд, поскольку макро должны быть определены для процессора раньше, чем макрокоманды обращения к ним. Однако, если мы наложим ограничение, что каждое макроопределение должно быть определено до того, как произойдет обращение к нему, мы устраним основное препятствие для однопросмотровой обработки. Заметим, что то же самое может быть верно и для символических имен в ассемблере, но такое требование было бы неоправданным ограничением для программиста. В случае же макрорасширения может быть вполне естественно потребовать, чтобы объявления макро предшествовали вызовам. Это не накладывает очень существенных ограничений на использование аппарата макрокоманд. Этот механизм даже не запрещает обращение макро к самому себе, поскольку обращение ведется в тот момент, когда имя макроса уже определено. Расширение же макроса идет не в процессе разбора макроса, а в процессе последующего вызова.

Предложенный ниже алгоритм объединяет два вышеприведенных алгоритма для двупросмотрового макроассемблера в один.


АЛГОРИТМ

Однопросмотровый макроассемблер

Начало алгоритма

МТДС = 0

МНТС = 0

ФЛАГ ВЫХОДА = 0

цикл пока !(ФЛАГ ВЫХОДА) {

чтение следующей строки ВХТ

НАЙДЕНО = поиск кода в МНТ

если (НАЙДЕНО) {

МДИ = 1

УКАЗАТЕЛЬ = индекс из МНТ

Заполнение списка параметров АЛА

цикл {

УКАЗАТЕЛЬ ++

чтение след. строки из МДТ

подстановка параметров

вставка во ВХТ

} пока !(операция MEND)

иначе если !(операция MACRO) {

вывод строки в ВЫХТ1

если (операция END) ФЛАГ ВЫХОДА = 1

}


иначе {

чтение идентификатора

запись имени и индекса в МНТ

МНТС ++

приготовить массив списка АЛА

запись имени в МДТ

МДТС ++

цикл {

чтение следующей строки ВХТ

подстановка индекса операторов

добавление в МДТ

МДТС ++

} пока !(операция MEND)

}

}

конец алгоритма

ОПИСАНИЕ АЛГОРИТМА

данный алгоритм является упрощением алгоритма приведенного в [1], глава 4.3.2. Различие состоит в том, что современные средства интеллектуализации программирования дают нам возможность осуществлять вставки и удаления из крупных массивов с минимальными затратами процессорного времени, что было невозможно при использовании перфокарт. Кроме того, скорость работы современных процессоров настолько велика, что позволяет производить прямые вставки и удаления в массивах данных средней величины (скажем, до 64 килобайт) в режиме реального времени. Таким образом, расширение исходного макроса может быть напрямую вставлено в массив исходного текста и обработано в расширенном виде. Такая технология позволяет значительно упростить алгоритм обработки макроязыка.


РЕАЛИЗАЦИЯ ВНУТРИ АССЕМБЛЕРА

Макропроцессор, описанный нами предназначался для обработки текста в режиме препроцессора, то-есть он выполнял полный просмотр входного текста, до того, как передать управление ассемблеру. Но макропроцессор также может быть реализован внутри первого прохода ассемблера. Такая реализация позволяет исключить промежуточные файлы, и позволяет достичь на порядок большей интеграции макропроцессора и ассемблера путем объединения сходных функций. Например, возможно объединение таблиц имен макросов и имен кода операции; специальный признак может указывать на то макро это или встроенная операция.

Основные преимущества включения макропроцессора в первый просмотр состоят в следующем: