Расширение возможностей транслятора С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; Мы поможем в написании вашей работы!

Поделиться с друзьями:






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