for i:=1 to RULE_NUM do
if GramRules[i] = sRuleStr then{Если правило найдено,}
begin { создаем новый нетерминальный символ }
Result:= TSymbol.CreateSymb(i,iSymbN,SymbArr);
Add(Result); { и добавляем его в стек. }
Break; { Прерываем цикл поиска правил }
end;
{ Если не был создан новый символ (правило не найдено),
надо удалить все исходные символы, это ошибка }
if Result = nil then
for i:=0 to iSymbN-1 do SymbArr[i].Free;
end;
end;
function BuildSyntList(
const listLex: TLexList{входная таблица лексем};
symbStack: TSymbStack{стек для работы алгоритма}
): TSymbol;
{ Функция, выполняющая алгоритм «сдвиг-свертка».
Результат функции:
– нетерминальный символ (корень синтаксического дерева),
если разбор был выполнен успешно;
– терминальный символ, ссылающийся на лексему, где была
обнаружена ошибка, если разбор выполнен с ошибками. }
var
i,iCnt: integer; {счетчик лексем и длина таблицы лексем}
lexStop: TLexem; { Ссылка на начальную лексему }
lexTCur: TLexType; { Тип текущей лексемы }
cRule: char;{ Текущее отношение предшествования }
begin
Result:= nil; { Сначала результат функции пустой }
iCnt:= listLex.Count-1; { Берем длину таблицы лексем }
{ Создаем дополнительную лексему «начало строки» }
lexStop:= TLexem.CreateInfo('Начало файла',0,0,0);
try { Помещаем начальную лексему в стек }
symbStack.Push(lexStop);
i:= 0; { Обнуляем счетчик входных лексем }
while i<=iCnt do { Цикл по всем лексемам от начала }
begin { до конца таблицы лексем }
{ Получаем тип лексемы на вершине стека }
lexTCur:= symbStack.TopLexem.LexType;
{ Если на вершине стека начальная лексема,
а текущая лексема – конечная, то разбор завершен }
if (lexTCur = LEX_START)
and (listLex[i].LexType = LEX_START) then Break;
{ Смотрим отношение лексемы на вершине стека
и текущей лексемы в строке }
cRule:= GramMatrix[lexTCur,listLex[i].LexType];
{ Корректируем отношение. Если корректировка матрицы
предшествования не используется, то функция должна
вернуть то же самое отношение }
cRule:= CorrectRule(cRule,lexTCur,
listLex[i].LexType,symbStack);
case cRule of
'<, =: { Надо выполнять сдвиг (перенос) }
begin { Помещаем текущую лексему в стек }
symbStack.Push(listLex[i]);
Inc(i); { Увеличиваем счетчик входных лексем }
end;
'>: { Надо выполнять свертку }
if symbStack.MakeTopSymb = nil then
begin { Если не удалось выполнить свертку, }
{ запоминаем текущую лексему как место ошибки }
Result:= TSymbol.CreateLex(listLex[i]);
Break; { Прерываем алгоритм }
end;
else { Отношение не установлено – ошибка разбора }
begin {Запоминаем текущую лексему (место ошибки)}
Result:= TSymbol.CreateLex(listLex[i]);
Break; { Прерываем алгоритм }
end;
end{case};
end{while};
if Result = nil then { Если разбор прошел без ошибок }
begin{Убеждаемся, что в стеке осталось только 2 символа}
if symbStack.Count = 2 then
{ Если да, то верхний символ – результат разбора }
Result:= symbStack[1]
{ Иначе это ошибка – отмечаем место ошибки }
else Result:= TSymbol.CreateLex(listLex[iCnt]);
end;
finally { Уничтожаем временную начальную лексему }
lexStop.Free;
end;
end;
end.
Модуль описания допустимых типов триад
Листинг П3.8. Описание допустимых типов триад
unit TrdType; {!!! Зависит от входного языка!!!}
interface
{ Модуль для описания допустимых типов триад }
const { Имена предопределенных функций и переменных }
NAME_PROG = 'MyCurs';
NAME_INPVAR = 'InpVar';
NAME_RESULT = 'Result';
NAME_FUNCT = 'CompileTest';
NAME_TYPE = 'integer';
type { Типы триад, соответствующие типам допустимых
операций, а также три дополнительных типа триад:
– CONST – для алгоритма свертки объектного кода;
– SAME – для алгоритма исключения лишних операций;
– NOP (No OPerations) – для ссылок на конец списка триад. }
TTriadType = (TRD_IF,TRD_OR,TRD_XOR,TRD_AND,TRD_NOT,
TRD_LT,TRD_GT,TRD_EQ,TRD_NEQ,TRD_ADD,TRD_SUB,TRD_UMIN,
TRD_ASSIGN,TRD_JMP,TRD_CONST,TRD_SAME,TRD_NOP);
{Массив строковых обозначений триад для вывода их на экран}
TTriadStr = array[TTriadType] of string;
const TriadStr: TTriadStr =('if','or','xor','and','not',
'<, >, =, <>, +, -, -,
':=,'jmp','C','same','nop');
{ Множество триад, которые являются линейными операциями }
TriadLineSet: set of TTriadType =
[TRD_OR, TRD_XOR, TRD_AND, TRD_NOT, TRD_ADD, TRD_SUB,
TRD_LT, TRD_GT, TRD_EQ, TRD_NEQ, TRD_UMIN];
implementation
end.
Модуль вычисления значений триад при свертке объектного кода
Листинг П3.9. Вычисление значений триад при свертке объектного кода
unit TrdCalc; {!!! Зависит от входного языка!!!}
Читать дальше
Конец ознакомительного отрывка
Купить книгу