Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Курсовая работа2 / SLR_Grammar / Udm_First
.pas // Авторы студенты группы 2382: Щербинская О. Ю., Мирошникова Н. Л., Костыгова Д. М.
unit Udm_First;
{=}INTERFACE
uses SysUtils, Classes, xmldom, XMLIntf, msxmldom, XMLDoc, Graphics;
type Tdm_First = class(TDataModule)
published
xml_First: TXMLDocument;
xml_XTerms: TXMLDocument;
private
m_Modified: boolean;
procedure BuildXtendedTerms;
procedure InitFirstRelation;
procedure GenerateFirstRelation;
public
function MergeToRelation( i_Relation: IXMLNode; i_NTermName: string; i_Code: string ): boolean;
function GetCurrentRelation( i_Relation: IXMLNode; i_NTermName: string ): string;
function GetXTermIndex( i_XTerm: IXMLNode ): integer;
procedure BuildFirstRelation;
end;
var dm_First: Tdm_First;
{=}IMPLEMENTATION
uses Ufrm_Main, Udm_Grammar, Umsc_StrSetUtils;
{$R *.dfm}
//Построит расширенный словарь терминалов, добавляя в него символ пустой строки
procedure Tdm_First.BuildXtendedTerms;
var nSym: integer; AddNode: IXMLNode;
begin
xml_XTerms.LoadFromFile( frm_Main.GetTemplatePath + '\Template.xml' );
for nSym := 0 to dm_Grammar.node_Term.ChildNodes.Count - 1 do
begin
AddNode := dm_Grammar.node_Term.ChildNodes[nSym].CloneNode(FALSE);
xml_XTerms.DocumentElement.ChildNodes.Add( AddNode );
end;
AddNode := xml_XTerms.DocumentElement.AddChild('SYMBOL', 0);
AddNode.Attributes['TYPE'] := 'sys';
AddNode.Attributes['NAME'] := 'TKN_EPS';
end;
// Ининциализация отношения "ПЕРВ" пустыми символами для всех нетерминалов.
// Символ START игнорируем
procedure Tdm_First.InitFirstRelation;
var nNterm: integer; AddNode,NTermNode: IXMLNode; InitSet: string;
begin
xml_First.LoadFromFile( frm_Main.GetTemplatePath + '\Template.xml' );
InitStrSet( InitSet );
for nNTerm := 1 to dm_Grammar.node_NTerm.ChildNodes.Count - 1 do
begin
NTermNode := dm_Grammar.node_NTerm.ChildNodes[nNterm];
AddNode := xml_First.DocumentElement.AddChild('SYMBOL');
AddNode.Attributes['NAME'] := NTermNode.Attributes['NAME'];
AddNode.Attributes['TYPE'] := NTermNode.Attributes['TYPE'];
AddNode.Attributes['CODE'] := InitSet;
end;
end;
(*
По очереди просматривает правила, добавляя к множеству "ПЕРВ" различные терминалы.
Работа прекращается, если после просмотра всех правил
нельзя добавить больше ни одного терминала
*)
procedure Tdm_First.GenerateFirstRelation;
var nProd,nSym: integer; ProdNode, SymNode: IXMLNode; LeftProd: string;
MergeClient: string;
begin
m_Modified := TRUE;
while m_Modified do
begin
m_Modified := FALSE;
for nProd := 1 to dm_Grammar.node_Prod.ChildNodes.Count - 1 do
begin
ProdNode := dm_Grammar.node_Prod.ChildNodes[ nProd ];
LeftProd := ProdNode.Attributes['START'];
InitStrSet(MergeClient);
if ProdNode.ChildNodes.Count = 0 then begin
AddElement(MergeClient,0);
m_Modified := MergeToRelation( xml_First.DocumentElement, LeftProd, MergeClient ) or m_Modified;
continue;
end;
nSym := 0;
while ( nSym < ProdNode.ChildNodes.Count ) do
begin
SymNode := ProdNode.ChildNodes[nSym];
if SymNode.Attributes['TYPE'] = 'term' then break;
MergeClient := GetCurrentRelation( xml_First.DocumentElement, SymNode.Attributes['NAME'] );
m_Modified := MergeToRelation( xml_First.DocumentElement, LeftProd, MergeClient ) or m_Modified;
inc( nSym );
if not HasElement( MergeClient, 0 ) then break;
end;
if SymNode.Attributes['TYPE'] = 'term' then
begin
AddElement(MergeClient, GetXTermIndex( SymNode ));
m_Modified := MergeToRelation( xml_First.DocumentElement, LeftProd, MergeClient ) or m_Modified;
continue;
end;
end;
end;
end;
//ИНТЕРФЕЙС
//Генерация отношение "ПЕРВ" на множестве символов грамматики
procedure Tdm_First.BuildFirstRelation;
begin
try
//Построение расширенного словаря терминалов
Self.BuildXtendedTerms;
Self.InitFirstRelation;
frm_Main.Log( 'Отношения FIRST', clBlack );
Self.GenerateFirstRelation;
frm_Main.Log( ' ', clBlack );
except
frm_Main.Log( '[ОШИБКА] Обнаружена ошибка', clRed );
end;
end;
// По заданному терминалу возвращает его индекс в словаре расширенных терминалов
function Tdm_First.GetXTermIndex( i_XTerm: IXMLNode ): integer;
var nXTerm: integer; XTermNode: IXMLNode;
begin
Result := -1;
for nXTerm := 0 to xml_XTerms.DocumentElement.ChildNodes.Count - 1 do
begin
XTermNode := xml_XTerms.DocumentElement.ChildNodes[nXTerm];
if ( XTermNode.Attributes['NAME'] = i_XTerm.Attributes['NAME'] ) and
( XTermNode.Attributes['TYPE'] = i_XTerm.Attributes['TYPE'] ) then
Result := nXTerm;
end;
end;
// Получает текущее состояние множества "ПЕРВ" для заданного нетерминала
// потом его добавим в основывающий символ правила)
function Tdm_First.GetCurrentRelation( i_Relation: IXMLNode; i_NTermName: string ): string;
var nSym: integer; SymNode: IXMLNode;
begin
Result := '';
for nSym := 0 to i_Relation.ChildNodes.Count - 1 do
begin
SymNode := i_Relation.ChildNodes[nSym];
if SymNode.Attributes['NAME'] = i_NTermName then Result := SymNode.Attributes['CODE'];
end;
end;
//Доливает к множеству "ПЕРВ" заданного нетерминала множество символов i_Code.
//Возвращает, изменилось ли от этого множество "ПЕРВ" этого нетерминала
function Tdm_First.MergeToRelation( i_Relation: IXMLNode; i_NTermName: string; i_Code: string ): boolean;
var nSym: integer; SymNode: IXMLNode; TempCode: string;
begin
Result := FALSE;
for nSym := 0 to i_Relation.ChildNodes.Count - 1 do
begin
SymNode := i_Relation.ChildNodes[nSym];
if SymNode.Attributes['NAME'] = i_NTermName then
begin
TempCode := SymNode.Attributes['CODE'];
Result := MergeSet( TempCode, i_Code );
SymNode.Attributes['CODE'] := TempCode;
end;
end;
end;
end.
unit Udm_First;
{=}INTERFACE
uses SysUtils, Classes, xmldom, XMLIntf, msxmldom, XMLDoc, Graphics;
type Tdm_First = class(TDataModule)
published
xml_First: TXMLDocument;
xml_XTerms: TXMLDocument;
private
m_Modified: boolean;
procedure BuildXtendedTerms;
procedure InitFirstRelation;
procedure GenerateFirstRelation;
public
function MergeToRelation( i_Relation: IXMLNode; i_NTermName: string; i_Code: string ): boolean;
function GetCurrentRelation( i_Relation: IXMLNode; i_NTermName: string ): string;
function GetXTermIndex( i_XTerm: IXMLNode ): integer;
procedure BuildFirstRelation;
end;
var dm_First: Tdm_First;
{=}IMPLEMENTATION
uses Ufrm_Main, Udm_Grammar, Umsc_StrSetUtils;
{$R *.dfm}
//Построит расширенный словарь терминалов, добавляя в него символ пустой строки
procedure Tdm_First.BuildXtendedTerms;
var nSym: integer; AddNode: IXMLNode;
begin
xml_XTerms.LoadFromFile( frm_Main.GetTemplatePath + '\Template.xml' );
for nSym := 0 to dm_Grammar.node_Term.ChildNodes.Count - 1 do
begin
AddNode := dm_Grammar.node_Term.ChildNodes[nSym].CloneNode(FALSE);
xml_XTerms.DocumentElement.ChildNodes.Add( AddNode );
end;
AddNode := xml_XTerms.DocumentElement.AddChild('SYMBOL', 0);
AddNode.Attributes['TYPE'] := 'sys';
AddNode.Attributes['NAME'] := 'TKN_EPS';
end;
// Ининциализация отношения "ПЕРВ" пустыми символами для всех нетерминалов.
// Символ START игнорируем
procedure Tdm_First.InitFirstRelation;
var nNterm: integer; AddNode,NTermNode: IXMLNode; InitSet: string;
begin
xml_First.LoadFromFile( frm_Main.GetTemplatePath + '\Template.xml' );
InitStrSet( InitSet );
for nNTerm := 1 to dm_Grammar.node_NTerm.ChildNodes.Count - 1 do
begin
NTermNode := dm_Grammar.node_NTerm.ChildNodes[nNterm];
AddNode := xml_First.DocumentElement.AddChild('SYMBOL');
AddNode.Attributes['NAME'] := NTermNode.Attributes['NAME'];
AddNode.Attributes['TYPE'] := NTermNode.Attributes['TYPE'];
AddNode.Attributes['CODE'] := InitSet;
end;
end;
(*
По очереди просматривает правила, добавляя к множеству "ПЕРВ" различные терминалы.
Работа прекращается, если после просмотра всех правил
нельзя добавить больше ни одного терминала
*)
procedure Tdm_First.GenerateFirstRelation;
var nProd,nSym: integer; ProdNode, SymNode: IXMLNode; LeftProd: string;
MergeClient: string;
begin
m_Modified := TRUE;
while m_Modified do
begin
m_Modified := FALSE;
for nProd := 1 to dm_Grammar.node_Prod.ChildNodes.Count - 1 do
begin
ProdNode := dm_Grammar.node_Prod.ChildNodes[ nProd ];
LeftProd := ProdNode.Attributes['START'];
InitStrSet(MergeClient);
if ProdNode.ChildNodes.Count = 0 then begin
AddElement(MergeClient,0);
m_Modified := MergeToRelation( xml_First.DocumentElement, LeftProd, MergeClient ) or m_Modified;
continue;
end;
nSym := 0;
while ( nSym < ProdNode.ChildNodes.Count ) do
begin
SymNode := ProdNode.ChildNodes[nSym];
if SymNode.Attributes['TYPE'] = 'term' then break;
MergeClient := GetCurrentRelation( xml_First.DocumentElement, SymNode.Attributes['NAME'] );
m_Modified := MergeToRelation( xml_First.DocumentElement, LeftProd, MergeClient ) or m_Modified;
inc( nSym );
if not HasElement( MergeClient, 0 ) then break;
end;
if SymNode.Attributes['TYPE'] = 'term' then
begin
AddElement(MergeClient, GetXTermIndex( SymNode ));
m_Modified := MergeToRelation( xml_First.DocumentElement, LeftProd, MergeClient ) or m_Modified;
continue;
end;
end;
end;
end;
//ИНТЕРФЕЙС
//Генерация отношение "ПЕРВ" на множестве символов грамматики
procedure Tdm_First.BuildFirstRelation;
begin
try
//Построение расширенного словаря терминалов
Self.BuildXtendedTerms;
Self.InitFirstRelation;
frm_Main.Log( 'Отношения FIRST', clBlack );
Self.GenerateFirstRelation;
frm_Main.Log( ' ', clBlack );
except
frm_Main.Log( '[ОШИБКА] Обнаружена ошибка', clRed );
end;
end;
// По заданному терминалу возвращает его индекс в словаре расширенных терминалов
function Tdm_First.GetXTermIndex( i_XTerm: IXMLNode ): integer;
var nXTerm: integer; XTermNode: IXMLNode;
begin
Result := -1;
for nXTerm := 0 to xml_XTerms.DocumentElement.ChildNodes.Count - 1 do
begin
XTermNode := xml_XTerms.DocumentElement.ChildNodes[nXTerm];
if ( XTermNode.Attributes['NAME'] = i_XTerm.Attributes['NAME'] ) and
( XTermNode.Attributes['TYPE'] = i_XTerm.Attributes['TYPE'] ) then
Result := nXTerm;
end;
end;
// Получает текущее состояние множества "ПЕРВ" для заданного нетерминала
// потом его добавим в основывающий символ правила)
function Tdm_First.GetCurrentRelation( i_Relation: IXMLNode; i_NTermName: string ): string;
var nSym: integer; SymNode: IXMLNode;
begin
Result := '';
for nSym := 0 to i_Relation.ChildNodes.Count - 1 do
begin
SymNode := i_Relation.ChildNodes[nSym];
if SymNode.Attributes['NAME'] = i_NTermName then Result := SymNode.Attributes['CODE'];
end;
end;
//Доливает к множеству "ПЕРВ" заданного нетерминала множество символов i_Code.
//Возвращает, изменилось ли от этого множество "ПЕРВ" этого нетерминала
function Tdm_First.MergeToRelation( i_Relation: IXMLNode; i_NTermName: string; i_Code: string ): boolean;
var nSym: integer; SymNode: IXMLNode; TempCode: string;
begin
Result := FALSE;
for nSym := 0 to i_Relation.ChildNodes.Count - 1 do
begin
SymNode := i_Relation.ChildNodes[nSym];
if SymNode.Attributes['NAME'] = i_NTermName then
begin
TempCode := SymNode.Attributes['CODE'];
Result := MergeSet( TempCode, i_Code );
SymNode.Attributes['CODE'] := TempCode;
end;
end;
end;
end.
Соседние файлы в папке SLR_Grammar