Лекция: Пример расширения языка и транслятора 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 и представленному отчету.

еще рефераты
Еще работы по информатике