Расширение возможностей транслятора С0
Цель работы - получение навыков разработки простейших типовых программ транслятора.
Изменения компилятора С0 удобно разрабатывать и реализовать в том же порядке, в каком он проектировался, и в каком дается его описание в пособиях [1-3, 6]. Таким образом, план разработки изменений транслятора состоит из следующих этапов.
1. Разработать изменения грамматики входного языка С0. Придумать примеры программ с использованием новых конструкций. Они облегчают разработку программ транслятора и послужат тестами для их отладки.
2. Определить, как изменится семантика входного языка, т. е. структура объектного кода программы в целом, новых конструкций языка, а возможно, и ранее существовавших конструкций. Составить объектный код для разработанных на этапе 1 тестовых примеров С0-программ.
2. Продумать, как изменения входного языка и объектного кода повлияют на структуры данных транслятора, в частности, на описание глобальных данных.
3. Уточнить модульную структуру, в частности, определить множество модулей (подпрограмм) транслятора, которые потребуется изменить.
4. Разработать программы новых и изменяемых модулей.
5. Выписать список всех заменяемых, вставляемых и удаляемых строк транслятора с указанием номеров строк в порядке возрастания этих номеров.
Вносить же эти изменения необходимо, наоборот, в порядке убывания номеров строк, чтобы ранее сделанные изменения не влияли на номера строк последующих изменений.
|
|
6. Провести отладку измененного транслятора на разработанных тестах.
Пример расширения языка и транслятора C0
Задача состоит в том, чтобы реализовать в языке C0 операции ++ и – – языка C (увеличение и уменьшение переменной на 1).
Для включения новых операций в грамматику C0 необходимо добавить правило: терм ::= ++ имя | имя ++ | -- имя | имя --
Операции увеличения и уменьшения на 1 можно реализовать следующим объектным кодом.
; ++ имя ; имя ++ ; -- имя ; имя --
INC адрес MOV AX,адрес DEC адрес MOV AX,адрес
MOV AX,адрес INC адрес MOV AX,адрес DEC адрес
Для глобальной переменной адрес - это имя, для локальной переменной адрес записывается в виде: смещение[BP].
Если операция в выражении не последняя, а промежуточная, добавляется команда вталкивания результата в стек: PUSH AX.
В трансляторе C0 добавятся новые значения лексемы uvel и umen, что потребует изменения: описаний типа tipleks и глобальных переменных tpr, st2, значения nvir множества начальных лексем выражения, подпрограммы чтения лексемы chleks. Новые лексемы uvel и umen будут вставлены в описание типа tipleks между лексемами plus и prisv, чтобы попасть в диапазон операций для вычисления приоритета в строке 387. В массив tpr с таблицей приоритетов (строка 80) добавятся приоритеты новых операций (как в языке С). В подпрограмму operac добавляется генерация кода для новых операций.
|
|
Таким образом, потребуются следующие изменения текста транслятора C0.
Заменить строки:
79 /* пpиоpитеты: + - * / % == != < > <= >= ( ) , ; ++ -- = */
80 int tpr[16]= { 5,5,6,6,6,3, 3, 4,4,4, 4, 0,1,1,1,7, 7, 2 };
84 mravn,bravn,lskob,pskob,zpt,tchzpt,uvel,umen,prisv,
85 flskob,fpskob,ifsl,intsl,retsl,whilesl};
102 long int st2[27]= /* st2[i]=2**i (i=0..26) */
105 8388608,16777216,33554432,67108864};
133 nvir=st2[ident]|st2[chislo]|st2[minus]|st2[lskob]|st2[uvel]|st2[umen];
Вставить после строки 458:
char kop[3]; /* код операции: INC или DEC */
Заменить строку:
460 if (*t1<=1 && t2==1 && op!=prisv && op!=uvel && op!=umen)
Вставить после строки 489:
else if (op==uvel || op==umen) /* ++ или -- */
{ kop = (op==uvel)? "INC" : "DEC" ;
if (*t1 == 0) /*нет 1-го операнда: префиксная оп-ция */
if(t2==3 && tabim[z2].vidob==1) /*2-й оп-д - пер-я*/
{ fprintf(fvih,"\t%s\t%s\n",kop,adrper(z2));
zopreg(z2,t2,"AX");
}
else oshibka(16); /* неверный тип операнда */
else
if(t2==0&&*t1==3&&tabim[*z1].vidob==1)/*имя++|имя--*/
{ zopreg(*z1,*t1,"AX");
fprintf(fvih,"\t%s\t%s\n",kop,adrper(*z1));
}
else oshibka(16); /* неверный тип операнда */
}
Вставить после строки 620:
|
|
else if (*usim=='+' || *usim=='-') /* + или - или ++ или -- */
{ c=*usim;
if (chsim() == c) /* ++ или -- */
{ if (c == '+') leksema=uvel; /* ++ */
else leksema=umen; /* -- */
chsim(); /* чтение символа след. лексемы */
}
else
leksema=leksim[c]; /* + или - */
}
Тестами послужат операторы-выражения с операциями ++ и --. Кроме ++ и --, требуются операции + и -, чтобы проверить правильность чтения этих лексем. Поскольку + и - имеют более низкий приоритет, для проверки учета приоритетов желательны также операции более высокого приоритета, чем ++ и -- (унарная операция изменения знака “-“).
Тестом может быть, например, программа со следующим фрагментом:
++x; y++; -x--; --y; x=-y+++5; x=++y+5; y=--x-5; x=y---5;
Объектный код этого фрагмента (считая x глобальной переменной, а y - локальной переменной со смещением -2) записан в три колонки:
; ++x; INC WORD PTR 2[BP] MOV AX,x
INC x PUSH AX PUSH AX
MOV AX,x MOV BX,5 MOV BX,5
; y++; POP AX POP AX
MOV AX,-2[BP] ADD AX,BX SUB AX,BX
INC WORD PTR -2[BP] PUSH AX PUSH AX
; -x--; POP AX POP AX
MOV AX,x MOV x,AX MOV -2[BP],AX
NEG AX ; x=++y+5; ; x=y---5;
|
|
PUSH AX INC WORD PTR -2[BP] MOV AX,-2[BP]
POP AX MOV AX,-2[BP] DEC WORD PTR -2[BP]
DEC x PUSH AX PUSH AX
; --y; MOV BX,5 MOV BX,5
DEC WORD PTR -2[BP] POP AX POP AX
MOV AX,-2[BP] ADD AX,BX SUB AX,BX
; x=-y+++5; PUSH AX PUSH AX
MOV AX,-2[BP] POP AX POP AX
NEG AX MOV x,AX MOV x,AX
PUSH AX ; y=--x-5;
POP AX DEC x
Необходимо проверить не только текстуальную правильность получаемого объектного кода, но и корректность его выполнения, например, в следующей тестовой программе на расширенном языке С0.
int x;
print(z)
{ putn(z); putchar(32);
}
main()
{ int y;
x = 5; y=9;
++x; print(x);
y++; print(y);
-x--; print(x);
--y; print(y);
x=-y+++5; print(x); print(y);
x=++y+5; print(x); print(y);
y=--x-5; print(x); print(y);
x=y---5; print(x); print(y);
}
Определите самостоятельно ожидаемый результат исполнения этой тестовой программы.
Порядок выполнения работы
1. Разработать изменения грамматики и семантики языка и транслятора C0, необходимые для реализации заданной преподавателем дополнительной возможности языка C0.
2. Изменения транслятора описать с указанием номеров вставляемых, заменяемых и удаляемых строк его текста (в порядке возрастания номеров) и сопроводить кратким пояснением основных идей, как показано в приведенном выше примере.
3. Разработать тесты и провести комплексную отладку измененного транслятора.
4. Составить отчет, включающий описание изменений языка и транслятора, отладочные средства и результаты отладки.
5. Сдать работу, ответив на вопросы преподавателя по транслятору С0 и представленному отчету.
Задания
Расширить язык и транслятор С0, реализовав в них следующие возможности.
1) Запись числа в восьмеричной системе счисления, начиная с цифры ноль, например: 027 = 2*8 + 7 = 23.
2) Запись числа в шестнадцатеричной системе счисления, начиная с 0x или 0X, например: 0x4C = 4*16 + 12 = 76.
3) Запись служебных слов как малыми, так и большими буквами.
4) Задание имен входного и выходного файлов при запуске транслятора.
5) Использование поразрядных операций: конъюнкции &, дизъюнкции | и отрицания ~, как в языке C.
6) Использование логических операций: конъюнкции &&, дизъюнкции || и отрицания !, как в языке C.
7) Выдача текстовых сообщений об ошибках вместо числовых.
8) Использование оператора цикла с предусловием, как в языке C:
do оператор while (выражение);
9) Использование условного оператора, как в языке C:
if (выражение) оператор [else оператор]
10) Использование оператора цикла for, как в языке C:
for (выражение ; выражение ; выражение) оператор
Указание: удобно расположить объектные коды выражений в том порядке, как они записаны в операторе for, а необходимый порядок их выполнения обеспечить за счет меток и команд перехода, как делается при трансляции операторов if и while.
11) Использование оператора переключателя, как в языке C:
switch (выражение)
{ [case число:[оператор] … ]…
default: [оператор] …
}
12) Описание локальных переменных в начале составного оператора - блока, как в языке C.
Указание: удобно выделять и освобождать память для локальных переменных составного оператора в начале кадра стека, используя отрицательные смещения.
13) Символьные константы вида: '*' = 42, 'A' = 65 и т. д.
14) Комментарии вида: /* [символ]... */, как в языке С.
15) Строчные комментарии, как в языке С++, вида:
//[символ]... конец-строки
16) Задание начальных значений в определении глобальных переменных, например: int a=5, b, x=-78;
Контрольные вопросы и упражнения
1. Какие подпрограммы компилятора С0 потребуется изменить для реализации возможности задавать имена входного и выходного файла?
2. Какие подпрограммы компилятора С0 потребуется изменить для выдачи тестовых сообщений об ошибках вместо номеров ошибок?
3. Какие подпрограммы компилятора потребуется изменить для трансляции комментариев, если они появятся в языке С0?
4. Какие подпрограммы компилятора потребуется изменить для трансляции символьных констант, если они появятся в языке С0?
5. Какие подпрограммы компилятора потребуется изменить для трансляции логических операций, если они появятся в языке С0?
6. Какие подпрограммы компилятора потребуется изменить для трансляции операторов do-while, если они появятся в языке С0?
7. Какие подпрограммы компилятора потребуется изменить для трансляции начальных значений в описании глобальных переменных, если они появятся в языке С0?
8. Какие подпрограммы компилятора потребуется изменить для трансляции начальных значений в описании локальных переменных, если они появятся в языке С0?
Лабораторная работа № 4
Дата добавления: 2019-02-12; просмотров: 227; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!