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

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ComCtrls, Grids, ExtCtrls,
LexElem, SyntSymb, Triads;

type
TLab4Form = 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;
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;
{ Процедура инициализации таблицы
для отображения списка лексем }
procedure InitLexGrid;
{ Процедура отображения синтаксического дерева }
procedure MakeTree(nodeTree: TTreeNode;
symbSynt: TSymbol);
public
{ Public declarations }
end;

var
Lab4Form: TLab4Form;

implementation

{$R *.DFM}

uses FncTree, LexType, LexAuto, TrdType, TrdMake, TrdOpt;

procedure TLab4Form.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 TLab4Form.FormCreate(Sender: TObject);
{ В начале выполнения инициализируем список лесем,
таблицу идентификаторов, синтаксический стек
и список триад }
begin
InitTreeVar;
listLex := TLexList.Create;
symbStack := TSymbStack.Create;
listTriad := TTriadList.Create;
end;

procedure TLab4Form.FormClose(Sender: TObject;
var Action: TCloseAction);
{ В конце выполнения очищаем список лесем,
таблицу идентификаторов, синтаксический стек
и список триад }
begin
listTriad.Free;
symbStack.Free;
listLex.Free;
ClearTreeVar
end;

procedure TLab4Form.EditFileChange(Sender: TObject);
begin
{ Можно читать файл, только когда его имя не пустое }
BtnLoad.Enabled := (EditFile.Text <> '');
end;

procedure TLab4Form.BtnFileClick(Sender: TObject);
begin
if FileOpenDlg.Execute then
{ Выбор имени файла с помощью стандартного диалога }
begin
EditFile.Text := FileOpenDlg.FileName;
BtnLoad.Enabled := (EditFile.Text <> '');
end;
end;

procedure TLab4Form.BtnLoadClick(Sender: TObject);
{ Процедура чтения и анализа файла }
var
i,iCnt,iErr: integer;
symbRes: TSymbol;
nodeTree: TTreeNode;
lexTmp: TLexem;
begin
{ Очищаем список лексем }
listLex.Clear;
{ Очищаем синтаксический стек }
symbStack.Clear;
{ Очищаем список триад }
listTriad.Clear;
{ Очищаем таблицу отображения списка лексем
и синтаксическое дерево }
InitLexGrid;
TreeSynt.Items.Clear;
try
{ Чтение файла в список строк }
ListIdents.Lines.LoadFromFile(EditFile.Text);
except
MessageDlg('Ошибка чтения файла!',mtError,[mbOk],0);
Exit;
end;
{ Анализ списка строк и заполнение списка лексем }
iErr := MakeLexList(ListIdents.Lines,listLex);
if iErr <> 0 then
{ Если анализ не успешный, выводим сообщение об ошибке }
begin
MessageDlg(Format('Неверная лексема "%s" в строке %d!',
[listLex[0].LexInfoStr,iErr]),
mtWarning,[mbOk],0);
{ Берем позицию ошибочной лексемы из фиктивной лексемы
в начале списка и позиционируем на нее список строк }
ListIdents.SelStart := listLex[0].PosAll;
ListIdents.SelLength := listLex[0].PosNum;
{ Отображаем позицию ошибки в списке строк }
ListIdents.SetFocus;
end
else
{ Если анализ успешный,
отображаем список лексем в таблице }
begin
{ Цикл по всем прочитанным лексемам }
GridLex.RowCount := listLex.Count+1;
iCnt := listLex.Count-1;
for i:=0 to iCnt do
begin
{ Первая колонка - номер }
GridLex.Cells[0,i+1] := IntToStr(i+1);
{ Вторая колонка - тип лексемы }
GridLex.Cells[1,i+1] :=
LexTypeName(listLex[i].LexType);
{ Третья колонка - значение лексемы }
GridLex.Cells[2,i+1] := listLex[i].LexInfoStr;
end;
{ Добавляем в конец списка лексем информационную
лексему "конец строки" }
with ListIdents do
listLex.Add(TLexem.CreateInfo('Конец строки',
Length(Text),Lines.Count-1,0));
{ Строим дерево синтаксического разбора и
получаем ссылку на его корень }
symbRes := BuildSyntList(listLex,symbStack);
{ Если эта ссылка содержит лексические данные,
значит была ошибка в месте, указанном лексемой }
if symbRes.SymbType = SYMB_LEX then
begin
MessageDlg(
Format('Синтаксическая ошибка в строке %d!',
[symbRes.Lexem.StrNum+1]),
mtWarning,[mbOk],0);
{ Берем позицию ошибочной лексемы по ссылке
и позиционируем на нее список строк }
ListIdents.SelStart := symbRes.Lexem.PosAll;
ListIdents.SetFocus;
{ Освобождаем ссылку на лексему }
symbRes.Free;
end
else
{ Если не было синтаксической ошибки,
заполняем дерево синтаксического разбора }
begin
{ Записываем данные в корень дерева }
nodeTree := TreeSynt.Items.Add(nil,
symbRes.SymbolStr);
{ Строим остальные элементы дерева от его корня }
MakeTree(nodeTree,symbRes);
{ Раскрываем всё дерево }
nodeTree.Expand(True);
{ Позиционируем указатель на корневой элемент }
TreeSynt.Selected := nodeTree;
{ Строим список триад по синтаксическому дереву }
lexTmp := MakeTriadList(symbRes,listTriad);
{ Если есть ссылка на лексему, значит была
семантическая ошибка }
if lexTmp <> nil then
begin
MessageDlg(
Format('Семантическая ошибка в строке %d!',
[lexTmp.StrNum+1]),
mtWarning,[mbOk],0);
{ Берем позицию ошибочной лексемы по ссылке
и позиционируем на нее список строк }
ListIdents.SelStart := lexTmp.PosAll;
ListIdents.SetFocus;
end
else
{ Если есть ссылка пуста, значит триады построены }
begin
{ Сохраняем общий список триад }
listTriad.WriteToList(ListTriadAll.Lines);
{ Выполняем оптимизацию методом
свертки объектного кода }
OptimizeConst(listTriad);
{ Если указан флаг, удаляем триады типа "C" }
if CheckDel_C.Checked then
DelTriadTypes(listTriad,TRD_CONST);
{ Сохраняем общий список после оптимизации }
listTriad.WriteToList(ListTriadConst.Lines);
{ Выполняем оптимизацию методом
исключения лишних операций }
OptimizeSame(listTriad);
{ Если указан флаг, удаляем триады типа "SAME" }
if CheckDelSame.Checked then
DelTriadTypes(listTriad,TRD_SAME);
{ Сохраняем общий список после оптимизации }
listTriad.WriteToList(ListTriadSame.Lines);
end;
end;
end;
end;

procedure TLab4Form.MakeTree(
{ Процедура отображения синтаксического дерева }
nodeTree: TTreeNode;
{ссылка на корневой элемент отображаемой
части дерева на экране}
symbSynt: TSymbol
{ссылка на синтаксический символ, связанный
с корневым элементом этой части дерева});
var
i,iCnt: integer;
nodeTmp: TTreeNode;
begin
{ Берем количество дочерних вершин для текущей }
iCnt := symbSynt.Count-1;
{ Цикл по всем дочерним вершинам }
for i:=0 to iCnt do
begin
{ Добавляем к дереву на экране вершину и
запоминаем ссылку на нее }
nodeTmp := TreeSynt.Items.AddChild(nodeTree,
symbSynt[i].SymbolStr);
{ Если эта вершина связана с нетерминальным символом,
рекурсивно вызываем процедуру построения дерева
для нее }
if symbSynt[i].SymbType = SYMB_SYNT then
MakeTree(nodeTmp,symbSynt[i]);
end;
end;

procedure TLab4Form.BtnExitClick(Sender: TObject);
{ Завершение работы с программой }
begin
Self.Close;
end;

end.
Соседние файлы в папке Labs