Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Курсовая работа2 / SLR_Grammar / Udm_Grammar
.pas // Авторы студенты группы 2382: Щербинская О. Ю., Мирошникова Н. Л., Костыгова Д. М.
unit Udm_Grammar;
{=}INTERFACE
uses SysUtils, Classes, Graphics, xmldom, XMLIntf, msxmldom, XMLDoc;
type Tdm_Grammar = class(TDataModule)
published
//--------------------------------------------------------------------------
xml_Grammar: TXMLDocument;
//--------------------------------------------------------------------------
private
//--------------------------------------------------------------------------
function GetNumByName( i_Section: IXMLNode; i_Name: string ): integer;
function ValidateType( i_Section: IXMLNode; i_Type: string ): boolean;
function ValidateProd: boolean;
procedure FillGrammar;
//--------------------------------------------------------------------------
public
//--------------------------------------------------------------------------
node_Term: IXMLNode;
node_NTerm: IXMLNode;
node_Prod: IXMLNode;
//--------------------------------------------------------------------------
procedure LoadGrammar( i_Path: string );
function GetSymbolDesc( i_Symbol: IXMLNode ): string;
//--------------------------------------------------------------------------
end;
var dm_Grammar: Tdm_Grammar;
{=}IMPLEMENTATION
uses Ufrm_Main;
{$R *.dfm}
(*
В секции i_Section ищется узел-потомок, имеющий аттрибут 'NAME',
равный i_Name. В случае отсутствия такого узла, возвращается -1.
*)
function Tdm_Grammar.GetNumByName( i_Section: IXMLNode; i_Name: string ): integer;
var I: integer;
begin
Result := -1;
for I := 0 to i_Section.ChildNodes.Count - 1 do
if (i_Section.ChildNodes[I].Attributes['NAME'] = i_Name) then Result := I;
end;
(*
Проверяет все элементы секции i_Section на предмет соответствия атрибута
TYPE равному i_Type.
*)
function Tdm_Grammar.ValidateType( i_Section: IXMLNode; i_Type: string ): boolean;
var I: integer;
begin
Result := TRUE;
for I := 0 to i_Section.ChildNodes.Count - 1 do
Result := Result and (i_Section.ChildNodes[I].Attributes['TYPE'] = i_Type);
end;
(*
Проверяет, чтобы каждый элемент продукции использовал только определённые
символы
*)
function Tdm_Grammar.ValidateProd: boolean;
var pNum,lNum: integer; CurProd, LocNode: IXMLNode;
begin
Result := TRUE;
for pNum := 0 to node_Prod.ChildNodes.Count - 1 do
begin
CurProd := node_Prod.ChildNodes[pNum];
Result := Result and (Self.GetNumByName(node_NTerm, CurProd.Attributes['START']) > -1);
for lNum := 0 to CurProd.ChildNodes.Count - 1 do
begin
if CurProd.ChildNodes[lNum].Attributes['TYPE'] = 'term' then LocNode := node_Term
else LocNode := node_NTerm;
Result := Result and (Self.GetNumByName(LocNode, CurProd.ChildNodes[lNum].Attributes['NAME']) > -1)
end;
end;
end;
(*
Построение пополненной грамматике по исходной. Добавляется самый начальный
символ и цепное правило, которое выводит из него всю грамматику
*)
procedure Tdm_Grammar.FillGrammar;
var StartSym: IXMLNode; StartRule: IXMLNode; StartRef: IXMLNode; SymName: string;
begin
StartSym := node_NTerm.AddChild( 'SYMBOL' , 0 );
StartSym.Attributes['TYPE'] := 'nterm';
StartSym.Attributes['NAME'] := 'START';
SymName := node_Prod.ChildNodes[0].Attributes['START'];
StartRule := node_Prod.AddChild( 'PRODUCTION' , 0);
StartRule.Attributes['START'] := 'START';
StartRef := StartRule.AddChild( 'SYMBOL' );
StartRef.Attributes['TYPE'] := 'nterm';
StartRef.Attributes['NAME'] := SymName;
end;
//ИНТЕРФЕЙС
//Загрузить грамматику из файла, выполняет проверку и подготавливает её к анализу
procedure Tdm_Grammar.LoadGrammar( i_Path: string );
begin
frm_Main.Log(' Проверка грамматики...', clGreen);
//загрузка грамматики
xml_Grammar.LoadFromFile( i_Path );
node_Term := xml_Grammar.DocumentElement.ChildNodes[0];
node_NTerm := xml_Grammar.DocumentElement.ChildNodes[1];
node_Prod := xml_Grammar.DocumentElement.ChildNodes[2];
//множество терминальных символов
if not Self.ValidateType( node_Term, 'term') then
frm_Main.Log('[ОШИБКА] В множестве терминальных символов обнаружены нетерминалы', clRed);
// множество нетерминальных символов
if not Self.ValidateType( node_NTerm, 'nterm') then
frm_Main.Log('[ОШИБКА] В множестве нетерминальных символов обнаружены терминалы', clRed);
if not Self.GetNumByName(node_NTerm, 'START') = -1 then
frm_Main.Log('[ОШИБКА] В множестве нетерминальных символов обнаружен символ "START"', clRed);
//множество порождающих правил
if not Self.ValidateProd then
frm_Main.Log('[ОШИБКА] В порождающих правилах обнаружены необъявленные символы', clRed);
//Построение пополненной грамматики
Self.FillGrammar;
frm_Main.Log(' ', clBlack);
end;
//Получить строковое представление символа, переданного в виде узла xml
function Tdm_Grammar.GetSymbolDesc( i_Symbol: IXMLNode ): string;
begin
Result := i_Symbol.Attributes['TYPE'] + '_' + i_Symbol.Attributes['NAME'];
end;
end.
unit Udm_Grammar;
{=}INTERFACE
uses SysUtils, Classes, Graphics, xmldom, XMLIntf, msxmldom, XMLDoc;
type Tdm_Grammar = class(TDataModule)
published
//--------------------------------------------------------------------------
xml_Grammar: TXMLDocument;
//--------------------------------------------------------------------------
private
//--------------------------------------------------------------------------
function GetNumByName( i_Section: IXMLNode; i_Name: string ): integer;
function ValidateType( i_Section: IXMLNode; i_Type: string ): boolean;
function ValidateProd: boolean;
procedure FillGrammar;
//--------------------------------------------------------------------------
public
//--------------------------------------------------------------------------
node_Term: IXMLNode;
node_NTerm: IXMLNode;
node_Prod: IXMLNode;
//--------------------------------------------------------------------------
procedure LoadGrammar( i_Path: string );
function GetSymbolDesc( i_Symbol: IXMLNode ): string;
//--------------------------------------------------------------------------
end;
var dm_Grammar: Tdm_Grammar;
{=}IMPLEMENTATION
uses Ufrm_Main;
{$R *.dfm}
(*
В секции i_Section ищется узел-потомок, имеющий аттрибут 'NAME',
равный i_Name. В случае отсутствия такого узла, возвращается -1.
*)
function Tdm_Grammar.GetNumByName( i_Section: IXMLNode; i_Name: string ): integer;
var I: integer;
begin
Result := -1;
for I := 0 to i_Section.ChildNodes.Count - 1 do
if (i_Section.ChildNodes[I].Attributes['NAME'] = i_Name) then Result := I;
end;
(*
Проверяет все элементы секции i_Section на предмет соответствия атрибута
TYPE равному i_Type.
*)
function Tdm_Grammar.ValidateType( i_Section: IXMLNode; i_Type: string ): boolean;
var I: integer;
begin
Result := TRUE;
for I := 0 to i_Section.ChildNodes.Count - 1 do
Result := Result and (i_Section.ChildNodes[I].Attributes['TYPE'] = i_Type);
end;
(*
Проверяет, чтобы каждый элемент продукции использовал только определённые
символы
*)
function Tdm_Grammar.ValidateProd: boolean;
var pNum,lNum: integer; CurProd, LocNode: IXMLNode;
begin
Result := TRUE;
for pNum := 0 to node_Prod.ChildNodes.Count - 1 do
begin
CurProd := node_Prod.ChildNodes[pNum];
Result := Result and (Self.GetNumByName(node_NTerm, CurProd.Attributes['START']) > -1);
for lNum := 0 to CurProd.ChildNodes.Count - 1 do
begin
if CurProd.ChildNodes[lNum].Attributes['TYPE'] = 'term' then LocNode := node_Term
else LocNode := node_NTerm;
Result := Result and (Self.GetNumByName(LocNode, CurProd.ChildNodes[lNum].Attributes['NAME']) > -1)
end;
end;
end;
(*
Построение пополненной грамматике по исходной. Добавляется самый начальный
символ и цепное правило, которое выводит из него всю грамматику
*)
procedure Tdm_Grammar.FillGrammar;
var StartSym: IXMLNode; StartRule: IXMLNode; StartRef: IXMLNode; SymName: string;
begin
StartSym := node_NTerm.AddChild( 'SYMBOL' , 0 );
StartSym.Attributes['TYPE'] := 'nterm';
StartSym.Attributes['NAME'] := 'START';
SymName := node_Prod.ChildNodes[0].Attributes['START'];
StartRule := node_Prod.AddChild( 'PRODUCTION' , 0);
StartRule.Attributes['START'] := 'START';
StartRef := StartRule.AddChild( 'SYMBOL' );
StartRef.Attributes['TYPE'] := 'nterm';
StartRef.Attributes['NAME'] := SymName;
end;
//ИНТЕРФЕЙС
//Загрузить грамматику из файла, выполняет проверку и подготавливает её к анализу
procedure Tdm_Grammar.LoadGrammar( i_Path: string );
begin
frm_Main.Log(' Проверка грамматики...', clGreen);
//загрузка грамматики
xml_Grammar.LoadFromFile( i_Path );
node_Term := xml_Grammar.DocumentElement.ChildNodes[0];
node_NTerm := xml_Grammar.DocumentElement.ChildNodes[1];
node_Prod := xml_Grammar.DocumentElement.ChildNodes[2];
//множество терминальных символов
if not Self.ValidateType( node_Term, 'term') then
frm_Main.Log('[ОШИБКА] В множестве терминальных символов обнаружены нетерминалы', clRed);
// множество нетерминальных символов
if not Self.ValidateType( node_NTerm, 'nterm') then
frm_Main.Log('[ОШИБКА] В множестве нетерминальных символов обнаружены терминалы', clRed);
if not Self.GetNumByName(node_NTerm, 'START') = -1 then
frm_Main.Log('[ОШИБКА] В множестве нетерминальных символов обнаружен символ "START"', clRed);
//множество порождающих правил
if not Self.ValidateProd then
frm_Main.Log('[ОШИБКА] В порождающих правилах обнаружены необъявленные символы', clRed);
//Построение пополненной грамматики
Self.FillGrammar;
frm_Main.Log(' ', clBlack);
end;
//Получить строковое представление символа, переданного в виде узла xml
function Tdm_Grammar.GetSymbolDesc( i_Symbol: IXMLNode ): string;
begin
Result := i_Symbol.Attributes['TYPE'] + '_' + i_Symbol.Attributes['NAME'];
end;
end.
Соседние файлы в папке SLR_Grammar