Макропроцессор. Таблицы и логика 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Макропроцессор. Таблицы и логика



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

 

1 MACROS MACRO {стандартная версия макросов для УУМ}

2 RDBUFF MACRO &INDEV,&BUFADR,&RECLTH

*

* {стандартная версия для УУМ}

*

3 MEND {конец RDBUFF}

4 WRBUFF MACRO &OUTDEV,&BUFADR,&RECLTH

*

* {стандартная версия для УУМ}

*

5 MEND {конец WRBUFF}

*

*

*

6 MEND {конец MACROS}

a

 

 

1 MACROS MACRO {версия макросов для УУМ/ДС}

2 RDBUFF MACRO &INDEV,&BUFADR,&RECLTH

*

* {версия для УУМ/ДС}

*

3 MEND {конец RDBUFF}

4 WRBUFF MACRO &OUTDEV,&BUFADR,&RECLTH

*

* {версия для УУМ/ДС}

*

5 MEND {конец WRBUFF}

*

*

*

6 MEND {конец MACROS}

б

Рис.4.3. Пример использования макроопределения внутри тела другого макроопределения.

 

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

Подобного рода определение одних макросов с помощью других может быть иногда полезно. Рассмотрим в качестве примера два макроопределения на рис. 4.3. Тело первого макроса (MACROS) содержит предложения, определяющие RDBUFF, WRBUFF и другие макроинструкции для УУМ (рис. 4.3а). Тело другого макроопределения (MACROX) содержит определения тех же макросов для УУМ/ДС (рис. 4.36). Программа, предназначенная для использования на стандартной УУМ, может инициализировать MACROS для определения необходимых ей макросов. Программа для УУМ/ДС может инициализировать MACROX для определения тех же макросов в расширенной ДС версии. Таким образом, одна и та же программа сможет работать как на стандартной УУМ, так и на УУМ/ДС (используя все ее дополнительные возможности). Единственное, что для этого надо сделать, - это инициализировать один из макросов: либо MACROS, либо MACROX. Важно понять, что само описание макроопределений MACROS или MACROX не определяет RDBUFF и других макросов. Они становятся доступными для использования только после завершения обработки предложений макроинициализации макросов MACROS или MACROX.

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

В нашем макропроцессоре используются три основные структуры данных. Сами макроопределения находятся в таблице макроопределений (DEFTAB), которая содержит макропрототипы и предложения, составляющие тело макроопределений (с некоторыми модификациями). Строки комментариев, содержащиеся внутри макроопределений, отсутствуют в таблице DEFTAB, поскольку они не нужны на этапе макрогенерации. Для повышения эффективности процесса подстановки аргументов ссылки на формальные параметры макроопределений преобразованы в их порядковые номера. Имена макросов содержатся в таблице NAMTAB, которая, по существу, является таблицей указателей на DEFTAB. Для каждого макроопределения таблица NAMTAB содержит указатели на начало и конец макроопределения, содержащегося в DEFTAB.

Третья структура данных - это таблица аргументов (ARG-ТАВ), заполняемая на этапе обработки предложений макроинициализации. Как только такое предложение распознано, его аргументы записываются в таблицу ARGTAB в соответствии с их номерами в списке аргументов. В процессе макрогенерации аргументы из таблицы ARGTAB заменяют собой соответствующие формальные параметры в теле макроопределения.

Рис.4.4. Содержимое таблиц макропроцессора для программы на рис. 4.1.: а - фрагменты таблиц NAMTAB и DEFTAB, связанные с макроопределением RDBUFF, б - содержимое таблицы ARGTAB для макроинициализации RDBUFF в строке 190.

 

На рис. 4.4 показаны фрагменты содержимого этих таблиц на этапе обработки программы, изображенной на рис. 4.1. Рис. 4..4а содержит макроопределение RDBUFF, записанное в таблицу DEFTAB, на начало и конец которого смотрят соответствующие указатели из таблицы NAMTAB. Обратите внимание на позиционную нотацию, использованную для обозначения параметров: параметр &INDF превращен в?1 (указывая на то, что это первый параметр в прототипе), параметр &BUFADR преобразован в?2 и т.д. На рис. 4.46 изображена таблица ARGTAB в том виде, в котором она окажется во время расширения макроса RDBUFF в строке 190. Для этой макроинициализации первым аргументом будет FI, вторым - BUFFER и т. д. Такая запись параметров делает процесс их замены на соответствующие аргументы существенно более эффективным. Как только встречается конструкция?n в строке таблицы DEFTAB, за счет простых индексных операций можно выбрать соответствующий аргумент из таблицы ARGTAB.

Собственно алгоритм работы макропроцессора представлен на рис. 4.5. Процедура DEFINE, которая вызывается, как только распознано начало макроопределения, формирует соответствующие строки таблиц DEFTAB и NAMTAB. Процедура EXPAND записывает аргументы в таблицу ARGTAB и осуществляет расширение предложений макроинициализации. Процедура GETLINE, которая вызывается в нескольких местах алгоритма, выбирает очередную строку для обработки. Это можете быть строка из таблицы DEFTAB (очередная строка тела макроопределения) или очередная строка входного файла в зависимости от того, какое значение имеет булевская переменная EXPANDING.

Одна из особенностей этого алгоритма заслуживает дальнейших пояснений. Это обработка макроопределений внутри тела других макроопределений (как на рис. 4.3). После того как заголовок макроопределения записан в таблицу DEFTAB, было бы естественно продолжат ь заполнять эту таблицу до тех пор, пока не встретилась директива MEND. Этого, однако, нельзя делать для примера, изображенного на рис. 4.3, поскольку директива MEND в строке 3 (конец макроопределения RDBUFF) была бы интерпретирована как конец макроопределения MACROS. Для того чтобы обойти эту трудность, наша процедура DEFINE содержит счетчик LEVEL. Каждый раз, когда встречается MACRO, величина счетчика LEVEL увеличивается на 1; по каждой директиве MEND его величина уменьшается на 1. Нулевое значение этого счетчика означает, что встретилась директива MEND, соответствующая исходной директиве MACRO. Этот процесс во многом аналогичен анализу открывающихся и закрывающихся скобок при обработке арифметических выражений. Для того чтобы убедиться, что вы понимаете работу этого алгоритма, вы можете применить его вручную к программе на рис. 4.1. Результат должен быть тот же, что и на рис. 4.2.

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

 

begin {макропроцессор}

EXPANDING:= FALSE

while OPCODE <> 'END' do

begin

GETLINE

PROCESSLINE

end {while}

end {макропроцессор}

 

procedure PROCESSLINE

begin

поиск OPCODE в NAMTAB

if нашли then

EXPAND

else if OPCODE = 'MACRO' then

DEFINE

else записать исходную строку в файл макрорасширения

end {PROCESSLINE}

 

procedure DEFINE

begin

записать имя макроопределения в NAMTAB

записать макропрототип в DEFTAB

LEVEL:= 1

while LEVEL > 0 do

begin

GETLINE

if это не строка-комментарий then

begin

заменить вхождение имени к-го параметра на?к

занести строку в DEFTAB

if OPCODE = 'MACRO' then

LEVEL:= LEVEL + 1

else if OPCODE = 'MEND' then

LEVEL:= LEVEL - 1

end {если не строка-комментарий}

end {while}

записать в NAMETAB указатели на начало и конец макроопределения

end {DEFINE}

 

procedure EXPAND

begin

EXPANDING:= TRUE

взять первую строку макроопределения {заголовок} из DEFTAB

записать аргументы макроинициалазации в ARGTAB

записать предложение макроинициализации как комментарий

while не конец макроопределения do

begin

GETLINE

PROCESSLINE

end {while}

EXPANDING:= FALSE

end {EXPAND}

 

procedure GETLINE

begin

if EXPANDING then

begin

взять следующую строку макроопределения из DEFTAB

заменить выражения?к на аргументы из ARGTAB

end {if}

else

прочитать очередную строку входного файла

end {CETLINE}

 

Рис.4.5. Алгоритм работы однопросмотрового макропроцессора.



Поделиться:


Последнее изменение этой страницы: 2017-02-17; просмотров: 190; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.127.232 (0.021 с.)