Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
13
Добавлен:
02.05.2014
Размер:
9.73 Кб
Скачать
unit Triads;

interface
{ Модуль, обеспечивающий работу с триадами
и списком триад }

uses Classes, TblElem, LexElem, TrdType;

type
{ Предварительное описание класса триад }
TTriad = class;
{ Типы операндов: константа, переменная,
ссылка на другую триаду }
TOpType = (OP_CONST, OP_VAR, OP_LINK);

{ Структура данных для описания операнда в триадах }
TOperand = record
{ Тип операнда }
case OpType: TOpType of
OP_CONST: (ConstVal: integer);
{ для константы - её значение }
OP_VAR: (VarLink: TVarInfo);
{ для переменной - ссылка на элемент
таблицы идентификаторов }
OP_LINK: (TriadNum: integer);
{ для триады - номер триады }
end;
{ Массив операндов из двух элементов }
TOpArray = array[1..2] of TOperand;

{ Структура данных для описания триады }
TTriad = class(TObject)
private
{ Тип триады }
TriadType: TTriadType;
{ Массив операндов }
Operands: TOpArray;
public
{ Дополнительная информация для оптимизирующих алгоритмов }
Info: longint;
{ Флаг наличия ссылки на эту триаду }
IsLinked: Boolean;
{ Конструктор для создания триады }
constructor Create(Typ: TTriadType; const Ops: TOpArray);
{ Функции для чтения и записи операндов }
function GetOperand(iIdx: integer): TOperand;
procedure SetOperand(iIdx: integer; Op: TOperand);
{ Функции для чтения и записи ссылок на другие триады }
function GetLink(iIdx: integer): integer;
procedure SetLink(iIdx: integer; TrdN: integer);
{ Функции для чтения и записи типа операндов }
function GetOpType(iIdx: integer): TOpType;
procedure SetOpType(iIdx: integer; OpT: TOpType);
{ Функции для чтения и записи значений констант }
function GetConstVal(iIdx: integer): integer;
procedure SetConstVal(iIdx: integer; iVal: integer);
{ Свойства триады, основанные на описанных выше
функциях }
property TrdType: TTriadType read TriadType;
property Opers[iIdx: integer]: TOperand read GetOperand
write SetOperand; default;
property Links[iIdx: integer]: integer read GetLink
write SetLink;
property OpTypes[iIdx: integer]: TOpType read GetOpType
write SetOpType;
property Values[iIdx: integer]: integer read GetConstVal
write SetConstVal;
{ Функция, проверяющая совпадение (эквивалентность)
двух триад }
function IsEqual(Trd1: TTriad): Boolean;
{ Функция, формирующая строковое представление триады }
function MakeString(i: integer): string;
end;

{ Класс для описания списка триад и работы с ним }
TTriadList = class(TList)
public
{ Процедура очистки списка и деструктор
для удаления списка }
procedure Clear; override;
destructor Destroy; override;
{ Процедура вывода списка триад в список строк
для отображения списка триад }
procedure WriteToList(list: TStrings);
{ Процедура удаления триады из списка }
procedure DelTriad(iIdx: integer);
{ Функция получения триады из списка по её номеру }
function GetTriad(iIdx: integer): TTriad;
{ Свойство списка триад для доступа к нему
по номеру триады }
property Triads[iIdx: integer]: TTriad read GetTriad;
default;
end;

{ Процедура удаления из списка триад
всех триад заданного типа }
procedure DelTriadTypes(listTriad: TTriadList;
TrdType: TTriadType);

implementation

uses SysUtils, FncTree, LexType;

constructor TTriad.Create(Typ: TTriadType;
const Ops: TOpArray);
{ Конструктор создания триады }
var i: integer;
begin
{ Вызываем конструктор базового класса }
inherited Create;
{ Запоминаем тип триады }
TriadType := Typ;
{ Запоминаем два операнда триады }
for i:=1 to 2 do Operands[i] := Ops[i];
{ Очищаем поле дополнительной информации
и поле внешней ссылки }
Info := 0;
IsLinked := False;
end;

function TTriad.GetOperand(iIdx: integer): TOperand;
{ Функция получения данных об операнде триады
по его номеру }
begin
Result := Operands[iIdx];
end;

procedure TTriad.SetOperand(iIdx: integer; Op: TOperand);
{ Функция записи данных операнда триады по его номеру }
begin
Operands[iIdx] := Op;
end;

function TTriad.GetLink(iIdx: integer): integer;
{ Функция получения ссылки на другую триаду из операнда
по его номеру }
begin
Result := Operands[iIdx].TriadNum;
end;

procedure TTriad.SetLink(iIdx: integer; TrdN: integer);
{ Функция записи номера ссылки на другую триаду
в операнд по его номеру }
begin
Operands[iIdx].TriadNum := TrdN;
end;

function TTriad.GetOpType(iIdx: integer): TOpType;
{ Функция получения типа операнда по его номеру }
begin
Result := Operands[iIdx].OpType;
end;

function TTriad.GetConstVal(iIdx: integer): integer;
{ Функция записи типа операнда по его номеру }
begin
Result := Operands[iIdx].ConstVal;
end;

procedure TTriad.SetConstVal(iIdx: integer; iVal: integer);
{ Функция получения значения константы в операнде
по его номеру }
begin
Operands[iIdx].ConstVal := iVal;
end;

procedure TTriad.SetOpType(iIdx: integer; OpT: TOpType);
{ Функция записи значения константы в операнд
по его номеру }
begin
Operands[iIdx].OpType := OpT;
end;

function IsEqualOp(const Op1,Op2: TOperand): Boolean;
{ Функция проверки совпадения (эквивалентности)
двух операндов }
begin
{ Операнды равны, если совпадают их типы }
Result := (Op1.OpType = Op2.OpType);
{ и значения в зависимости от типа }
if Result then
case Op1.OpType of
OP_CONST: Result := (Op1.ConstVal = Op2.ConstVal);
OP_VAR: Result := (Op1.VarLink = Op2.VarLink);
OP_LINK: Result := (Op1.TriadNum = Op2.TriadNum);
end;
end;

function TTriad.IsEqual(Trd1: TTriad): Boolean;
{ Функция, проверяющая совпадение (эквивалентность)
двух триад }
begin
{ Триады эквивалентны, если совпадают их типы }
Result := (TriadType = Trd1.TriadType)
{ и оба операнда }
and IsEqualOp(Operands[1],Trd1[1])
and IsEqualOp(Operands[2],Trd1[2]);
end;

function GetOperStr(Op: TOperand): string;
{ Функция формирования строки для отображения
оператора триады }
begin
case Op.OpType of
OP_CONST: Result := IntToStr(Op.ConstVal);
OP_VAR: Result := Op.VarLink.VarName;
OP_LINK: Result := '^'+ IntToStr(Op.TriadNum+1);
end{case};
end;

function TTriad.MakeString(i: integer): string;
begin
Result := Format('%d:'#9'%s (%s, %s)',
[i+1,TriadStr[TriadType],
GetOperStr(Opers[1]),GetOperStr(Opers[2])]);
end;

destructor TTriadList.Destroy;
{ Деструктор для удаления списка триад }
begin
{ Очищаем список триад }
Clear;
{ Вызываем деструктор базового класса }
inherited Destroy;
end;

procedure TTriadList.Clear;
{ Процедура очистки списка триад }
var i: integer;
begin
{ Освобождаем память для всех триад из списка }
for i:=Count-1 downto 0 do TTriad(Items[i]).Free;
{ Вызываем функцию базового класса }
inherited Clear;
end;

procedure TTriadList.DelTriad(iIdx: integer);
{ Функция удаления триады из списка триад }
begin
{ Если это не последняя триада }
if iIdx < Count-1 then
{ и если на нее есть ссылка - переставляем
флаг ссылки на предыдущую }
TTriad(Items[iIdx+1]).IsLinked :=
TTriad(Items[iIdx+1]).IsLinked
or TTriad(Items[iIdx]).IsLinked;
{ Освобождаем память триады }
TTriad(Items[iIdx]).Free;
{ Удаляем ссылку на триаду из списка }
Delete(iIdx);
end;

function TTriadList.GetTriad(iIdx: integer): TTriad;
{ Функция выборки триады из списка по её номеру }
begin
Result := TTriad(Items[iIdx]);
end;

procedure TTriadList.WriteToList(list: TStrings);
{ Процедура вывода списка триад в список строк
для отображения списка триад }
var
i,iCnt: integer;
begin
{ Очищаем список строк }
list.Clear;
iCnt := Count-1;
{ Для всех триад из списка триад }
for i:=0 to iCnt do
{ Формируем строковое представление триады
и добавляем его в список строк }
list.Add(TTriad(Items[i]).MakeString(i));
end;

procedure DelTriadTypes(listTriad: TTriadList;
TrdType: TTriadType);
{ Процедура удаления из списка триад всех триад
заданного типа }
var
i,j,iCnt,iDel: integer;
listNum: TList;
Trd: TTriad; { список для запоминания изменений
индексов триад }
begin
{ Вначале изменение индекса нулевое }
iDel := 0;
iCnt := listTriad.Count-1;
{ Создаем список для запоминания изменений
индексов триад }
listNum := TList.Create;
try
{ Для всех триад списка выполняем запоминание
изменений индекса }
for i:=0 to iCnt do
begin
{ Запоминем изменение индекса данной триады }
listNum.Add(TObject(iDel));
{ Если эта триада удаляемого типа,
то увеличиваем изменение индекса }
if listTriad[i].TriadType = TrdType then Inc(iDel);
end;
{ Для всех триад списка изменяем индексы ссылок }
for i:=iCnt downto 0 do
begin
Trd := listTriad[i];
{ Если эта триада удаляемого типа, то удаляем ее }
if Trd.TriadType = TrdType then listTriad.DelTriad(i)
else
{ Иначе для обоих операндов триады смотрим,
не является ли он ссылкой }
for j:=1 to 2 do
if Trd[j].OpType = OP_LINK then
{ Если операнд является ссылкой на триаду,
уменьшаем её индекс }
Trd.Links[j] :=
Trd.Links[j] - integer(listNum[Trd.Links[j]]);
end;
{ Уничтожаем список для запоминания
изменений индексов триад }
finally listNum.Free;
end;
end;

end.

Соседние файлы в папке Common