Преобразование грамматики в атрибутную грамматику

Лекция 2.4

Виртуальная машина

 

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

 

Стековая машина имеет нуль-адресную систему команд и прекрасно приспособлена для обработки выражений представленных в обратной польской записи. Но команды пересылки, переходов требуют 1 адреса. Поэтому приходится использовать либо 1 адресную систему команд (в арифметических операциях адрес не будет использоваться), либо нуль-адресную систему команд (адреса располагаются сразу за командой).

В учебных целях для простоты разработаем одноадресную виртуальную машину:

КОП Адрес

 

 

Архитектура виртуальной машины

 


Нуль-адресные операции: арифметические, отношения, логические

КОП Адрес = 0

 

Pop – функция извлечения числа из вершины стека

Push(значение) – процедура записи значения в стек

  Мат. знак Мнемо-код  
унарный минус - op_um  
модуль abs op_abs  
сложение + op_add push(pop+pop)
вычитание op_sub buf=pop push(pop-buf)
умножение * op_mult push(pop*pop)
деление целочислен / op_div . . . .
остаток % op_mod . . . .
меньше < op_less buf=pop if (pop<buf) then push(1) else push(0)
больше > op_grt . . . .
равно = op_equ . . . .
или | op_or push(pop | pop)
и & op_and . . . .
не ~ op_not  
Вывод из вершины стека в окно вывода   op_view  
останов   op_stop  

 

Дополнительные команды

  Мат. знак Мнемо-код  
  >= op_  
  <= op_  
  <> op_  
  !> op_  
  !< op_  
  != op_  
  e2 op_  
  sign op_  

 


Операции пересылки и перехода

КОП Адрес переменной
КОП константа

 

curr_code.op - поле операции текущей команды

curr_code.adr – адрес перехода или значение константы в текущей команде

var[1..v_max] - массив переменных

code[1..c_max] – массив команд

операция Мнемокод Выполнение
Запись константы в стек op_pushC константа push(curr_code.adr)
Запись значения переменной в стек op_pushV адр_пер push(var[curr_code.adr])
Запись вершины стека по адресу op_pop адр_пер  
Безусловный переход по адресу op_jamp адр_ком curr_adr = adr_com
Условный переход по адресу если результат сравнения Истина op_jmpC адр_ком if pop=1 then curr_adr = adr_com else curr_adr=curr_adr + 1

 

Виртуальная машина в процессе выполнения команд должна обнаруживать и выводить сообщения об ошибках времени выполнения:

· несуществующая операция

· некорректный адрес перехода

· некорректный операнд (деление на ноль)

 

 


Алгоритм работы виртуальной машины

 

Procedure VirtComp(

Code array[1..CMAX) of instr, {целевой код}

Var array[1..VMAX] of integer) {переменные}

 

begin

curr_adr:=1; {установка начального адр}

curr_code:=code[curr_adr]; {выборка 1 команды}

 

{команды будут выбираться до команды «СТОП»}

while curr_code.op<>op_stop do

begin

{блок интерпретации команд}

case curr_code.op of

{многоальтернативный оператор выбора}

 

op_plus: begin push(pop+pop); {сложение}

curr_adr:=curr_adr+1 end;

 

op_sub: begin buf:=pop; push(pop-buf);

curr_adr:=curr_adr+1 end; {вычитание}

. . . . . . . .

op_less: begin buf:=pop; {сравнение по <}

if pop<buf then push(1)

else push(0) end;

. . . . . . . .

{запись в стек констант и переменных}

op_pushC: begin push(curr_code.adr);

curr_adr:=curr_adr+1 end;

 

op_pushV: begin push(var[curr_code.adr]]);

curr_adr:=curr_adr+1 end;

 

{безусловный и условный переход}

op_jamp: curr_adr:=curr_code.adr;

op_jampC: begin if pop=1

then curr_adr:=curr_code.adr]

else curr_adr:=curr_adr+1 end;

 

else w_err(«некорректный код операции»)

end{case};

curr_code:=code[curr_adr]; {выборка команды}

end {while}

end { VirtComp}


Преобразование грамматики в атрибутную грамматику

(синтаксически управляемый перевод для виртуальной машины)

 

1. активные действия: {gencode(код_операции, операнд)}

2. действия над атрибутами

 

Правило

MULT

MULT=id | number | ( EXPR )

 

 

Добавляем активные действия, атрибуты

 

 

MULT= idP {gencode(op_pushV, P)} |

numberP {gencode(op_pushC, P)} |

( EXPR )

 

 


ADD

 

ADD = MULT { oper MULT }

 

ADD = MULT { operP {R=P запомнить операция} MULT {gencode(R, 0)} }

 

Аналогично EXPR

 

Аналогично LOGIC


 

Оператор присваивания

 

STMT= id =EXPR

STMT= idP =EXPR {gencode(op_pop, Q)} Q:=P

 

If typeLex=id then

Begin

Buf=valueLex

Getlex();

EXPR();

Gencode(op_pop, buf)

End

Else if typeLex=view then

 

Оператор вывода VIEW

 

STMT= view EXPR

STMT= view EXPR {gencode(op_view, 0)}

 

if typeLex=view then

begin

getlex();

EXPR();

gencode(op_view, 0)

end

else if typeLex=view then