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

interface

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

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

var
Lab3Form: TLab3Form;

implementation

{$R *.DFM}

uses FncTree, LexType, LexAuto;

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

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

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

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

procedure TLab3Form.BtnLoadClick(Sender: TObject);
{ Процедура чтения и анализа файла }
var
i,iCnt,iErr: integer;
symbRes: TSymbol;
nodeTree: TTreeNode;
begin
{ Очищаем список лексем }
listLex.Clear;
{ Очищаем синтаксический стек }
symbStack.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;
end;
end;
end;

procedure TLab3Form.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 TLab3Form.BtnExitClick(Sender: TObject);
{ Завершение работы с программой }
begin
Self.Close;
end;

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