begin { ищем совпадающую триаду с таким же }
if Trd.IsEqual(listTriad[j]) { числом зависимости }
and (Trd.Info = listTriad[j].Info) then
begin { Если триада найдена, запоминаем ссылку }
Ops[1].TriadNum:= j;
{ запоминаем ее в триаде типа «SAME», которую
записываем в список вместо прежней триады }
listTriad.Items[i]:=
TTriad.Create(TRD_SAME,Ops);
listTriad[i].IsLinked:= Trd.IsLinked; { Если на
прежнюю триаду была ссылка, сохраняем ее }
Trd.Free; { Уничтожаем прежнюю триаду }
Break; { Прерываем поиск }
end;
end;
end{if};
end{for};
end;
end.
Модуль создания списка триад на основе дерева разбора
unit TrdMake; {!!! Зависит от входного языка!!!}
interface
{ Модуль, обеспечивающий создание списка триад на основе
структуры синтаксического разбора }
uses LexElem, Triads, SyntSymb;
function MakeTriadList(symbTop: TSymbol;
listTriad: TTriadList): TLexem;
{ Функция создания списка триад начиная от корневого
символа дерева синтаксического разбора.
Функция возвращает nil при успешном выполнении, иначе
она возвращает ссылку на лексему, где произошла ошибка }
implementation
uses LexType, TrdType;
function GetLexem(symbOp: TSymbol): TLexem;
{ Функция, проверяющая, является ли операнд лексемой }
begin
case symbOp.Rule of
0: Result:= symbOp.Lexem; {Нет правил – это лексема!}
27,28: Result:= symbOp[0].Lexem; { Если дочерний
символ построен по правилу № 27 или 28, то это лексема }
19,26: Result:= GetLexem(symbOp[1]) { Если это
арифметические скобки, надо проверить,
не является ли лексемой операнд в скобках }
else Result:= nil; { Иначе это не лексема }
end;
end;
function MakeTriadListNOP(symbTop: TSymbol;
listTriad: TTriadList): TLexem;
{ Функция создания списка триад начиная от корневого
символа дерева синтаксического разбора
(без добавления триады NOP в конец списка) }
var
Opers: TOpArray; { массив операндов триад }
iIns1,iIns2,iIns3: integer; { переменные для запоминания
индексов триад в списке }
function MakeOperand(
iOp{номер операнда},
iSymOp{порядковый номер символа в синтаксической конструкции},
iMin{минимальная позиция триады в списке},
iSymErr{номер лексемы, на который
позиционировать ошибку}: integer;
var iIns: integer{индекс триады в списке}): TLexem;
{ Функция формирования ссылки на операнд }
var lexTmp: TLexem;
begin
lexTmp:= GetLexem(symbTop[iSymOp]); { Проверяем, }
if lexTmp <> nil then { является ли операнд лексемой }
with lexTmp do { Если да, то берем имя операнда }
begin { в зависимости от типа лексемы }
if LexType = LEX_VAR then
begin
if VarInfo.VarName = NAME_RESULT then
begin{Убеждаемся, что переменная имеет допустимое имя}
Result:= lexTmp;
Exit;
end; { Если это переменная, то запоминаем ссылку
на таблицу идентификаторов }
Opers[iOp].OpType:= OP_VAR;
Opers[iOp].VarLink:= VarInfo;
end
else
if LexType = LEX_CONST then
begin { Если это константа, то запоминаем ее значение }
Opers[iOp].OpType:= OP_CONST;
Opers[iOp].ConstVal:= ConstVal;
end
else begin { Иначе это ошибка, возвращаем лексему }
Result:= lexTmp; { как указатель на место ошибки }
Exit;
end;
iIns:= iMin; Result:= nil;
end
else { иначе это синтаксическая конструкция }
begin {Вызываем рекурсивно функцию создания списка триад}
Result:= MakeTriadListNOP(symbTop[iSymOp],listTriad);
if Result <> nil then Exit; {Ошибка – прерываем алгоритм}
iIns:= listTriad.Count; { Запоминаем индекс триады }
if iIns <= iMin then {Если индекс меньше минимального —}
begin { это ошибка }
Result:= symbTop[iSymErr].Lexem;
Exit;
end;
Opers[iOp].OpType:= OP_LINK;{Запоминаем ссылку на}
Opers[iOp].TriadNum:= iIns-1; {предыдущую триаду }
end;
end;
function MakeOperation(
Trd: TTriadType{тип создаваемой триады}): TLexem;
{ Функция создания списка триад для линейных операций }
begin { Создаем ссылку на первый операнд }
Result:= MakeOperand(1{op},0{sym},listTriad.Count,
1{sym err},iIns1);
if Result <> nil then Exit; {Ошибка – прерываем алгоритм}
{ Создаем ссылку на второй операнд }
Result:= MakeOperand(2{op},2{sym},iIns1,
1{sym err},iIns2);
if Result <> nil then Exit; {Ошибка – прерываем алгоритм}
{ Создаем саму триаду с двумя ссылками на операнды }
listTriad.Add(TTriad.Create(Trd,Opers));
end;
begin { Тело главной функции }
case symbTop.Rule of { Начинаем с выбора типа правила }
5:{'if(B)EelseE'} { Полный условный оператор }
begin { Запоминаем ссылку на первый операнд
(условие «if(B)») }
Result:= MakeOperand(1{op},2{sym},listTriad.Count,
1{sym err},iIns1);
{ Если произошла ошибка, прерываем выполнение }
if Result <> nil then Exit;
Opers[2].OpType:= OP_LINK; { Второй операнд – }
Opers[2].TriadNum:= 0; {ссылка на триаду, номер
которой пока не известен}
{ Создаем триаду типа «IF» }
listTriad.Add(TTriad.Create(TRD_IF,Opers));
{ Запоминаем ссылку на второй операнд (раздел «(B)E») }
Result:= MakeOperand(2{op},4{sym},iIns1,
3{sym err},iIns2);
{ Если произошла ошибка, прерываем выполнение }
if Result <> nil then Exit;
Opers[1].OpType:= OP_CONST; {Заполняем операнды}
Opers[1].ConstVal:= 1; { для триады типа «JMP»,
которая должна быть в конце раздела «(B)E»}
Opers[2].OpType:= OP_LINK; { Второй операнд – }