Створення компілятора

Автор работы: Пользователь скрыл имя, 26 Мая 2013 в 02:23, курсовая работа

Описание работы

Мета роботи: вивчення складових частин, основних принципів побудови і функціонування компіляторів. Практичне освоєння методів побудови простих компіляторів для заданої вхідної мови.


Завдання:
Для програмної організації компілятора рекомендується використовувати Borland Delphi:
Компілятор повинен складатися:
лексичний аналізатор
синтаксичний аналізатор
оптимізатор
генератор результуючого кода

Файлы: 1 файл

Kursova_SPZ.doc

— 850.00 Кб (Скачать файл)

Компілятор  виділяє закінчену синтаксичну конструкцію з тексту початкової програми, генерує для неї фрагмент результуючого коду і записує цей фрагмент в текст результуючої програми. Це повторюється для всіх синтаксичних конструкцій в програмі. Аналізуються такі синтаксичні конструкції як блоки операторів, описи процедур і функцій.

В лабораторній роботі результатом  генерації коду є програма на мові асемблера. Взагалі є такі форми внутрішнього представлення програми:

  1. структури зв’язних списків, що представляють синтаксичні дерева;
  2. багатоадресний код з явно іменованими результатами (тетради);
  3. багатоадресний код з неявно іменованими результатами (тріади);
  4. зворотній постфікс ний польський запис операції;
  5. асемблер ний код або машинні команди;

В кожному конкретному  компіляторі  розробник вибирає одну з даних форм. В даній лабораторній роботі використовується 3 форма.

Тріада – запис операцій в формі з 3 складових: операція і 2 операнди.

<операція> (<операнд  1><операнд 2>)

Особливістю тріад є  те, що один або обидва операнди можуть бути посиланнями на іншу тріаду в тому випадку, якщо в якості операнда даної тріади виступає результат іншої тріади, тому тріади послідовно нумерують для зручності вказання посилань одних тріад на інші (в реалізації компілятора можуть бути не номери, а вказівники). Тоді при зміні нумерації і порядка слідування не треба змінювати посилання.

 

Приклад: A := B*C + D - B*10

  1. *(B, C)
  2. +(1^, D)
  3. *(B, 10)
  4. –(^2, ^3)
  5. :=(A, ^4)

Тріади обчислюються послідовно одна за одною і результат  обчислення зберігається в тимчасовій пам’яті.

Тріади дуже зручні для  переведення їх кода в асемблер ний, але для тріад також потрібен алгоритм розподілу пам’яті для  зберігання проміжних результатів  обчислень, оскільки тимчасові змінні тріадами не використовуються (в цьому  відмінність тріад від тетрад). Тріади не залежать від архітектури обчислювальної системи на яку орієнтована результуюча програма. Це машинно-незалежна форма внутрішнього представлення програми.

Переваги тріад:

  1. вони є лінійною послідовністю операцій на відміну від синтаксичного дерева;
  2. займають менше пам’яті ніж тетроди і краще оптимізуються ніж зворотній польський код;
  3. явно відображають взаємодію операцій між собою;
  4. результат обчислення тріад можна зберігати в регістрах процесора, що зручно для оптимізації;

вони наближені до двоадресних машинних команд, які найбільше поширені в наборах команд більшості комп’ютерів;

 

2. Таблиця передування

 

pr.

end.

;

f

(

)

else

beg

end

rpt

until

a

c

:=

or

xor

and

<

>

=

<>

not

-

+

um

!

*

/

pr.

 

 

=

<

<

 

 

 

 

 

 

<

 

 

<

 

 

<

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

end.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

>

 

 

 

 

 

 

>

>

<

 

 

 

 

 

 

<

>

<

 

 

<

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

if

 

 

 

 

 

 

 

 

=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(

 

 

 

 

 

 

 

<

=

 

 

 

 

 

 

 

 

 

 

<

<

 

 

<

<

<

<

<

<

<

<

<

<

<

 

 

<

<

 

 

>

>

<

 

 

>

=

<

>

<

=

<

 

 

 

 

>

>

>

>

>

>

>

 

 

>

>

 

 

 

 

>

>

else

 

 

>

>

<

 

 

 

 

>

<

>

<

 

 

<

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

beg.

 

 

 

 

<

<

 

 

 

 

 

 

<

=

<

 

 

<

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

end

 

 

>

>

 

 

 

 

 

 

>

 

 

>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

repit

 

 

 

 

 

 

 

 

=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

until 

 

 

>

>

<

 

 

 

 

>

<

<

<

 

 

<

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a  

 

 

>

>

 

 

 

 

>

>

 

 

>

 

 

 

 

 

 

 

 

=

>

>

>

>

>

>

>

 

 

>

>

 

 

 

 

>

>

c  

 

 

>

>

 

 

 

 

>

>

 

 

>

 

 

 

 

 

 

 

 

 

 

>

>

>

>

>

>

>

 

 

>

>

 

 

 

 

>

>

:= 

 

 

>

>

 

 

<

 

 

>

 

 

>

 

 

 

 

<

<

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

<

<

<

 

 

<

<

or 

 

 

 

 

 

 

 

 

<

>

 

 

 

 

 

 

 

 

 

 

<

<

 

 

>

>

<

<

<

<

<

<

<

<

<

 

 

<

<

xor

 

 

 

 

 

 

 

 

<

>

 

 

 

 

 

 

 

 

 

 

<

<

 

 

>

>

<

<

<

<

<

<

<

<

<

 

 

<

<

and

 

 

 

 

 

 

 

 

<

>

 

 

 

 

 

 

 

 

 

 

<

<

 

 

>

>

>

<

<

<

<

<

<

<

<

 

 

<

<

<  

 

 

 

 

 

 

 

 

<

>

 

 

 

 

 

 

 

 

 

 

<

<

 

 

>

>

>

 

 

 

 

 

 

 

 

 

 

<

<

<

 

 

<

<

>  

 

 

 

 

 

 

 

 

<

>

 

 

 

 

 

 

 

 

 

 

<

<

 

 

>

>

>

 

 

 

 

 

 

 

 

 

 

<

<

<

 

 

<

<

=  

 

 

 

 

 

 

 

 

<

>

 

 

 

 

 

 

 

 

 

 

<

<

 

 

>

>

>

 

 

 

 

 

 

 

 

 

 

<

<

<

 

 

<

<

<> 

 

 

 

 

 

 

 

 

<

>

 

 

 

 

 

 

 

 

 

 

<

<

 

 

>

>

>

 

 

 

 

 

 

 

 

 

 

<

<

<

 

 

<

<

not

 

 

 

 

 

 

 

 

=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

-  

 

 

>

>

 

 

<

>

>

 

 

>

 

 

 

 

<

<

 

 

>

>

>

>

>

>

>

 

 

>

>

<

 

 

>

>

+  

 

 

>

>

 

 

<

>

>

 

 

>

 

 

 

 

<

<

 

 

>

>

>

>

>

>

>

 

 

>

>

<

 

 

>

>

um 

 

 

>

>

 

 

<

>

>

 

 

>

 

 

 

 

<

<

 

 

>

>

>

>

>

>

>

 

 

>

>

<

 

 

>

>

!  

<

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

*

 

 

>

>

 

 

<

>

>

 

 

>

 

 

 

 

<

<

 

 

>

>

>

>

>

>

>

 

 

>

>

<

 

 

>

>

/

 

 

>

>

 

 

<

>

>

 

 

>

 

 

 

 

<

<

 

 

>

>

>

>

>

>

>

 

 

>

>

<

 

 

>

>


3. Лістинг програм

 

1. FormLab

 

unit FormLab4;

interface

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls,

  Forms, Dialogs, StdCtrls, ComCtrls, Grids, ExtCtrls,

  LexElem, SyntSymb, Triads;

 

type

  { Типы возможных ошибок  компилятора: файловая,

    лексическая, синтаксическая, семантическая (триады)

    или ошибок  нет }

  TErrType = (ERR_FILE, ERR_LEX, ERR_SYNT,

              ERR_TRIAD, ERR_NO);

  TCursovForm = class(TForm)

    PageControl1: TPageControl;

    SheetFile: TTabSheet;

    SheetLexems: TTabSheet;

    BtnExit: TButton;

    GroupText: TGroupBox;

    ListIdents: TMemo;

    EditFile: TEdit;

    BtnFile: TButton;

    BtnLoad: TButton;

    FileOpenDlg: TOpenDialog;

    GridLex: TStringGrid;

    SheetSynt: TTabSheet;

    TreeSynt: TTreeView;

    SheetTriad: TTabSheet;

    GroupTriadAll: TGroupBox;

    Splitter1: TSplitter;

    GroupTriadSame: TGroupBox;

    Splitter2: TSplitter;

    GroupTriadConst: TGroupBox;

    ListTriadAll: TMemo;

    ListTriadConst: TMemo;

    ListTriadSame: TMemo;

    CheckDel_C: TCheckBox;

    CheckDelSame: TCheckBox;

    SheetAsm: TTabSheet;

    ListAsm: TMemo;

    CheckAsm: TCheckBox;

    procedure BtnLoadClick(Sender: TObject);

    procedure BtnFileClick(Sender: TObject);

    procedure EditFileChange(Sender: TObject);

    procedure BtnExitClick(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure FormClose(Sender: TObject;

                        var Action: TCloseAction);

   private

    { Список лексем }

    listLex: TLexList;

    { Синтаксический  стек }

    symbStack: TSymbStack;

    { Список триад  }

    listTriad: TTriadList;

    { Имена файлов: входного, результата и ошибок }

    sInpFile,sOutFile,sErrFile: string;

    { Функция записи  стартовых данных в файл ошибок }

    procedure StartInfo(const sErrF: string);

    { Функция обработки командной строки }

    procedure ProcessParams(

      var flOptC,flOptSame,flOptAsm: Boolean);

    { Процедура инициализации таблицы

      для отображения  списка лексем }

    procedure InitLexGrid;

    { Процедура отображения  синтаксического дерева }

    procedure MakeTree(nodeTree: TTreeNode;

                       symbSynt: TSymbol);

    { Процедура  информации об ошибке }

    procedure ErrInfo(const sErrF,sErr: string;

                      iPos,iLen: integer);

    { Функция запуска  компилятора }

    function CompRun(const sInF,sOutF,sErrF: string;

                    var symbRes: TSymbol;

                    flTrd,flDelC,flDelSame,flOptC,

                    flOptSame,flOptAsm: Boolean): TErrType;

   public

    { Public declarations }

  end;

 

var

  CursovForm: TCursovForm;

 

implementation

 

{$R *.DFM}

 

uses FncTree, LexType, LexAuto, TrdType, TrdMake, TrdAsm,

     TrdOpt;

 

procedure TCursovForm.InitLexGrid;

{ Процедура  инициализации таблицы

  для отображения списка лексем }

begin

  with GridLex do

  begin

    RowCount := 2;

    Cells[0,0] := '№ п/п';

    Cells[1,0] := 'Лексема';

    Cells[2,0] := 'Значение';

    Cells[0,1] := '';

    Cells[1,1] := '';

    Cells[2,1] := '';

  end;

end;

 

procedure TCursovForm.StartInfo(

          const sErrF: string{имя файла ошибок});

{ Функция записи стартовых  данных в файл ошибок }

var

  i,iCnt: integer;{счетчик параметров и переменная цикла}

  sTmp: string;{суммарная командная строка}

begin

  { Запоминаем имя файла ошибок }

  sErrFile := sErrF;

  { Записываем в файл  ошибок дату запуска компилятора  }

  ErrInfo(sErrFile,

          Format('--- %s ---',[DateTimeToStr(Now)]),0,0);

  { Берем количество входных параметров }

  iCnt := ParamCount;

  { Обнуляем  суммарную командную строку }

  sTmp := ParamStr(0);

  { Записываем  в суммарную командную строку

    все  параметры последовательно }

  for i:=1 to iCnt do

   sTmp := sTmp +' '+ ParamStr(i);

  { Записываем в файл ошибок суммарную командную строку }

  ErrInfo(sErrFile,sTmp,0,0);

end;

 

procedure TCursovForm.ProcessParams(

var flOptC,flOptSame,flOptAsm: Boolean{флаги});

{ Функция обработки командной  строки }

var

  i,iCnt,iLen: integer;

  sTmp: string;

  { Список для записи  ошибок параметров }

  listErr: TStringList;

begin

  { Устанавливаем все  флаги по умолчанию }

  flOptC    := True;

  flOptSame := True;

  flOptAsm  := True;

  { Создаем список для записи ошибок параметров }

  listErr := TStringList.Create;

  try

    { Берем количество  входных параметров }

    iCnt := ParamCount;

    { Обрабатываем  все параметры, начиная со второго  }

    for i:=2 to iCnt do

    begin

      { Берем строку параметра }

      sTmp := ParamStr(i);

      { Берем  длину строки параметра }

      iLen := Length(sTmp);

      { Если параметр слишком короткий  или не начинается

        со знака "-" - это неправильный  параметр }

      if (iLen < 3) or (sTmp[1] <> '-') then

       { Запоминаем ошибку в список }

       listErr.Add(Format('Неверный параметр %d: "%s"!',

                          [i,sTmp]))

      else

      { Иначе  обрабатываем параметр в соответствии

        с  его типом (второй символ) }

      case sTmp[2] of

        { Флаг  оптимизации ассемблера }

        'a','A': flOptAsm  := (sTmp[3] = '1');

        { Флаг оптимизации методом свертки }

        'c','C': flOptC    := (sTmp[3] = '1');

        { Флаг оптимизации исключением лишних операций }

        's','S': flOptSame := (sTmp[3] = '1');

        { Имя  выходного файла }

        'o','O': sOutFile := System.Copy(sTmp,3,iLen-2);

        { Имя  файла ошибок }

        'e','E': StartInfo(System.Copy(sTmp,3,iLen-2));

        { Параметр неизвестного типа }

        else

         { Запоминаем ошибку в список }

         listErr.Add(Format('Неверный параметр %d: "%s"!',

                            [i,sTmp]));

      end{case};

    end{for};

    { Ставим  имена файлов по умолчанию,

      если они не были указаны  в параметрах }

    if sOutFile = '' then

      sOutFile := ChangeFileExt(sInpFile,'.asm');

    if sErrFile = '' then

      StartInfo(ChangeFileExt(sInpFile,'.err'));

    { Берем количество ошибок в параметрах }

    iCnt := listErr.Count-1;

    { Запоминаем  информацию обо всех ошибках  }

    for i:=0 to iCnt do ErrInfo(sErrFile,listErr[i],0,0)

    { Освобождаем память, занятую списком ошибок }

    finally listErr.Free;

  end{try};

end;

 

procedure TCursovForm.FormCreate(Sender: TObject);

var

  flOptC,flOptSame,flOptAsm: Boolean;

  symbRes: TSymbol;

  iErr: TErrType;

begin

  symbRes := nil;

  sOutFile := '';

  sErrFile := '';

  { В начале  выполнения инициализируем список  лесем,

    таблицу  идентификаторов, синтаксический  стек

    и  список триад }

  InitTreeVar;

  listLex := TLexList.Create;

  symbStack := TSymbStack.Create;

  listTriad := TTriadList.Create;

  { Если указан  параметр - не надо открывать окно,

    надо  сразу запускать компилятор

    и  обрабатывать входной файл }

  if ParamCount > 0 then

  begin

    { Берем имя  входного файла из первого  параметра }

    sInpFile := ParamStr(1);

    { Обрабатываем  все остальные параметры }

    ProcessParams(flOptC,flOptSame,flOptAsm);

    { Запускаем компилятор }

    iErr := CompRun(

              sInpFile,sOutFile,sErrFile{входные файлы},

              symbRes{ссылка на дерево разбора},

              False{запоминать списки триад не надо},

              flOptC{флаг удаления триад "C"},

              flOptSame{флаг удаления триад "SAME"},

              flOptC{флаг оптимизации по методу

                     свертки объектного кода },

              flOptSame{флаг оптимизации исключ.

                        лишних операций},

              flOptAsm{флаг оптимизации команд

                       ассемблера});

    { Если не было  файловых ошибок,

      то надо завершать работу }

    if iErr <> ERR_FILE then Self.Close;

  end;

end;

 

procedure TCursovForm.FormClose(Sender: TObject;

                            var Action: TCloseAction);

{ В конце  выполнения очищаем список лесем,

  таблицу  идентификаторов, синтаксический  стек

  и список триад  }

begin

  listTriad.Free;

  symbStack.Free;

  listLex.Free;

  ClearTreeVar;

  Application.Terminate;

end;

 

procedure TCursovForm.EditFileChange(Sender: TObject);

begin

  { Можно читать файл, только когда его имя не  пустое }

  BtnLoad.Enabled := (EditFile.Text <> '');

end;

 

procedure TCursovForm.BtnFileClick(Sender: TObject);

begin

  if FileOpenDlg.Execute then

  { Выбор имени файла  с помощью стандартного диалога  }

  begin

    EditFile.Text := FileOpenDlg.FileName;

    BtnLoad.Enabled := (EditFile.Text <> '');

  end;

end;

 

procedure TCursovForm.ErrInfo(const sErrF,sErr: string;

                              iPos,iLen: integer);

{ Процедура  информации об ошибке }

var

{ Файл для записи информации  об ошибке }

  fileErr: TextFile;

begin

  { Если имя файла  ошибок не пустое }

  if sErrF <> '' then

  try

    { Записываем информацию об ошибке в файл }

    AssignFile(fileErr,sErrF);

Информация о работе Створення компілятора