Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Курсовая работа2 / SLR_Grammar / Udm_Goto
.pas // Авторы студенты группы 2382: Щербинская О. Ю., Мирошникова Н. Л., Костыгова Д. М.
unit Udm_Goto;
{=}INTERFACE
uses SysUtils, Classes, xmldom, XMLIntf, msxmldom, XMLDoc, Graphics;
type Tdm_Goto = class(TDataModule)
published
//--------------------------------------------------------------------------
xml_States: TXMLDocument;
xml_Voc: TXMLDocument;
//--------------------------------------------------------------------------
private
//---------------------------------------------------------------------------
m_StateCount: integer;
//---------------------------------------------------------------------------
procedure BuildGeneralVocabulary;
function AddState( i_Code: string ): IXMLNode;
function GetState( i_Code: string ): integer;
function ResolveTransition( i_State, i_VocSym: IXMLNode ): string;
procedure AddTransition( i_State, i_VocSym: IXMLNode; i_Code: string );
procedure BuildInitialState;
procedure BuildReachables( i_State: IXMLNode );
//---------------------------------------------------------------------------
public
//---------------------------------------------------------------------------
procedure BuildGotoFunction;
function GetStateDesc( i_State: IXMLNode ): string;
function GetTransDesc( i_Trans: IXMLNode ): string;
function IsGotoDefined( i_State: IXMLNode; i_NTermName: string): boolean;
//---------------------------------------------------------------------------
end;
var dm_Goto: Tdm_Goto;
{================================================================}IMPLEMENTATION
uses Udm_Grammar, Udm_Vpod, Ufrm_Main, Umsc_StrSetUtils;
{$R *.dfm}
{===============================================================================
ВСПОМОГАТЕЛЬНЫЕ МЕТОДЫ МОДУЛЯ
===============================================================================}
(*
Процедура строит обобщённый словарь грамматики, в который включает
сначала все нетерминалы, а затем - все терминалы
символ START включать не следует
*)
procedure Tdm_Goto.BuildGeneralVocabulary;
var nSym: integer; AddNode: IXMLNode;
begin
xml_Voc.LoadFromFile( frm_Main.GetTemplatePath + '\Template.xml' );
for nSym := 1 to dm_Grammar.node_NTerm.ChildNodes.Count - 1 do
begin
AddNode := dm_Grammar.node_NTerm.ChildNodes[nSym].CloneNode(FALSE);
xml_Voc.DocumentElement.ChildNodes.Add( AddNode );
end;
for nSym := 0 to dm_Grammar.node_Term.ChildNodes.Count - 1 do
begin
AddNode := dm_Grammar.node_Term.ChildNodes[nSym].CloneNode(FALSE);
xml_Voc.DocumentElement.ChildNodes.Add( AddNode );
end;
end;
(*
Добавляет к множеству состояний очередное состояние. Совокупность грамматических
вхождений, соответствующих состоянию, шифруется в i_Code
*)
function Tdm_Goto.AddState( i_Code: string ): IXMLNode;
var StateNode: IXMLNode;
begin
StateNode := xml_States.DocumentElement.AddChild('STATE');
StateNode.Attributes['NAME'] := 'STATE_' + IntToStr(m_StateCount);
StateNode.Attributes['CODE'] := i_Code;
inc(m_StateCount);
Result := StateNode;
end;
(*
Сканирует множество определённых состояний, пытаясь найти среди них код,
равный i_Code;
*)
function Tdm_Goto.GetState( i_Code: string ): integer;
var nState: integer;
begin
Result := -1;
for nState := 0 to xml_States.DocumentElement.ChildNodes.Count - 1 do
if xml_States.DocumentElement.ChildNodes[nState].Attributes['CODE'] = i_Code then Result := nState;
end;
(*
По текущему состоянию i_State
(представленному кодом) и символу обобщённого словаря нужно узнать
код состояния, в которое перейдёт автомат по этому символу
*)
function Tdm_Goto.ResolveTransition( i_State, i_VocSym: IXMLNode ): string;
var ParseCode, Buffer: string; nItem, nVpod: integer;
ParseSym: TStrSetIterator; VpodItem: IXMLNode;
begin
InitStrSet( Buffer );
ParseCode := i_State.Attributes['CODE'];
InitStrSetIterator( ParseSym );
while HasMoreElements( ParseCode, ParseSym ) do
begin
nItem := GetNextElement( ParseCode, ParseSym );
for nVpod := 0 to dm_Vpod.xml_Vpod.DocumentElement.ChildNodes[nItem].ChildNodes.Count - 1 do
begin
VpodItem := dm_Vpod.xml_Vpod.DocumentElement.ChildNodes[nItem].ChildNodes[nVpod];
if ( VpodItem.Attributes['TYPE'] = i_VocSym.Attributes['TYPE'] ) and
( VpodItem.Attributes['NAME'] = i_VocSym.Attributes['NAME'] ) then
Umsc_StrSetUtils.AddElement( Buffer, dm_Vpod.GetItemNum( VpodItem ) );
end;
end;
Result := Buffer;
end;
(*
Добавляет в состояние i_State переход по символу i_VocSym в состояние,
обозначенное кодом i_Code
*)
procedure Tdm_Goto.AddTransition( i_State, i_VocSym: IXMLNode; i_Code: string );
var TranNode: IXMLNode;
begin
TranNode := i_State.AddChild( 'TRANSITION' );
TranNode.Attributes['TYPE'] := i_VocSym.Attributes['TYPE'];
TranNode.Attributes['NAME'] := i_VocSym.Attributes['NAME'];
TranNode.Attributes['STNAME'] := i_Code;
end;
(*
Прооцедура формирует начальное состояние из символа конца магазина
*)
procedure Tdm_Goto.BuildInitialState;
var InitSet: string;
begin
xml_States.LoadFromFile( frm_Main.GetTemplatePath + '\Template.xml' );
m_StateCount := 0;
InitStrSet( InitSet );
AddElement( InitSet, 0 );
Self.AddState( InitSet );
end;
(*
рурсивно строит таблицу переходов управляющего автомата
Надо её только вызвать для начального состояния.
*)
procedure Tdm_Goto.BuildReachables( i_State: IXMLNode );
var nVoc,nStat: integer; VocNode: IXMLNode; Code,Name: string; NewState: IXMLNode;
begin
for nVoc := 0 to xml_Voc.DocumentElement.ChildNodes.Count - 1 do
begin
VocNode := xml_Voc.DocumentElement.ChildNodes[nVoc];
Code := ResolveTransition( i_State, VocNode );
if ( IsEmpty( Code ) ) then Continue;
NewState := NIL;
nStat := Self.GetState(Code);
if ( nStat = -1 ) then
begin
NewState := AddState(Code);
nStat := m_StateCount - 1;
end;
Name := 'STATE_' + IntToStr(nStat);
Self.AddTransition( i_State, VocNode, Name );
if ( NewState <> NIL ) then Self.BuildReachables( NewState );
end;
end;
//ИНТЕРФЕЙС
// построение функции свёртки
procedure Tdm_Goto.BuildGotoFunction;
begin
try
//Построение обобщённого словаря грамматики
Self.BuildGeneralVocabulary;
//Формирование начального состояния автомата
Self.BuildInitialState;
//Поиск достижимых состояний автомата
Self.BuildReachables( xml_States.DocumentElement.ChildNodes[0] );
frm_Main.Log( '', clBlack );
except
frm_Main.Log( '[ОШИБКА] Обнаружена ошибка', clRed );
end;
end;
(*
Возвращает строковое представление состояния, однако не распарсивает
его грамматические вхождения
*)
function Tdm_Goto.GetStateDesc( i_State: IXMLNode ): string;
begin
Result := i_State.Attributes['NAME'];
end;
(*
Возвращает строковое представление перехода состояния по символу словаря
*)
function Tdm_Goto.GetTransDesc( i_Trans: IXMLNode ): string;
begin
Result := dm_Grammar.GetSymbolDesc( i_Trans ) + '(' + i_Trans.Attributes['STNAME'] + ')';
end;
(*
Проверяет для заданного состояния: определен ли на нём переход по нетерминалу
с именем i_NTermName. Это нужно при построении функции действий
*)
function Tdm_Goto.IsGotoDefined( i_State: IXMLNode; i_NTermName: string): boolean;
var nGoto: integer; GotoNode: IXMLNode;
begin
Result := FALSE;
for nGoto := 0 to i_State.ChildNodes.Count - 1 do
begin
GotoNode := i_State.ChildNodes[nGoto];
if ( GotoNode.Attributes['TYPE'] = 'nterm' ) and
( GotoNode.Attributes['NAME'] = i_NTermName ) then
Result := TRUE;
end;
end;
end.
unit Udm_Goto;
{=}INTERFACE
uses SysUtils, Classes, xmldom, XMLIntf, msxmldom, XMLDoc, Graphics;
type Tdm_Goto = class(TDataModule)
published
//--------------------------------------------------------------------------
xml_States: TXMLDocument;
xml_Voc: TXMLDocument;
//--------------------------------------------------------------------------
private
//---------------------------------------------------------------------------
m_StateCount: integer;
//---------------------------------------------------------------------------
procedure BuildGeneralVocabulary;
function AddState( i_Code: string ): IXMLNode;
function GetState( i_Code: string ): integer;
function ResolveTransition( i_State, i_VocSym: IXMLNode ): string;
procedure AddTransition( i_State, i_VocSym: IXMLNode; i_Code: string );
procedure BuildInitialState;
procedure BuildReachables( i_State: IXMLNode );
//---------------------------------------------------------------------------
public
//---------------------------------------------------------------------------
procedure BuildGotoFunction;
function GetStateDesc( i_State: IXMLNode ): string;
function GetTransDesc( i_Trans: IXMLNode ): string;
function IsGotoDefined( i_State: IXMLNode; i_NTermName: string): boolean;
//---------------------------------------------------------------------------
end;
var dm_Goto: Tdm_Goto;
{================================================================}IMPLEMENTATION
uses Udm_Grammar, Udm_Vpod, Ufrm_Main, Umsc_StrSetUtils;
{$R *.dfm}
{===============================================================================
ВСПОМОГАТЕЛЬНЫЕ МЕТОДЫ МОДУЛЯ
===============================================================================}
(*
Процедура строит обобщённый словарь грамматики, в который включает
сначала все нетерминалы, а затем - все терминалы
символ START включать не следует
*)
procedure Tdm_Goto.BuildGeneralVocabulary;
var nSym: integer; AddNode: IXMLNode;
begin
xml_Voc.LoadFromFile( frm_Main.GetTemplatePath + '\Template.xml' );
for nSym := 1 to dm_Grammar.node_NTerm.ChildNodes.Count - 1 do
begin
AddNode := dm_Grammar.node_NTerm.ChildNodes[nSym].CloneNode(FALSE);
xml_Voc.DocumentElement.ChildNodes.Add( AddNode );
end;
for nSym := 0 to dm_Grammar.node_Term.ChildNodes.Count - 1 do
begin
AddNode := dm_Grammar.node_Term.ChildNodes[nSym].CloneNode(FALSE);
xml_Voc.DocumentElement.ChildNodes.Add( AddNode );
end;
end;
(*
Добавляет к множеству состояний очередное состояние. Совокупность грамматических
вхождений, соответствующих состоянию, шифруется в i_Code
*)
function Tdm_Goto.AddState( i_Code: string ): IXMLNode;
var StateNode: IXMLNode;
begin
StateNode := xml_States.DocumentElement.AddChild('STATE');
StateNode.Attributes['NAME'] := 'STATE_' + IntToStr(m_StateCount);
StateNode.Attributes['CODE'] := i_Code;
inc(m_StateCount);
Result := StateNode;
end;
(*
Сканирует множество определённых состояний, пытаясь найти среди них код,
равный i_Code;
*)
function Tdm_Goto.GetState( i_Code: string ): integer;
var nState: integer;
begin
Result := -1;
for nState := 0 to xml_States.DocumentElement.ChildNodes.Count - 1 do
if xml_States.DocumentElement.ChildNodes[nState].Attributes['CODE'] = i_Code then Result := nState;
end;
(*
По текущему состоянию i_State
(представленному кодом) и символу обобщённого словаря нужно узнать
код состояния, в которое перейдёт автомат по этому символу
*)
function Tdm_Goto.ResolveTransition( i_State, i_VocSym: IXMLNode ): string;
var ParseCode, Buffer: string; nItem, nVpod: integer;
ParseSym: TStrSetIterator; VpodItem: IXMLNode;
begin
InitStrSet( Buffer );
ParseCode := i_State.Attributes['CODE'];
InitStrSetIterator( ParseSym );
while HasMoreElements( ParseCode, ParseSym ) do
begin
nItem := GetNextElement( ParseCode, ParseSym );
for nVpod := 0 to dm_Vpod.xml_Vpod.DocumentElement.ChildNodes[nItem].ChildNodes.Count - 1 do
begin
VpodItem := dm_Vpod.xml_Vpod.DocumentElement.ChildNodes[nItem].ChildNodes[nVpod];
if ( VpodItem.Attributes['TYPE'] = i_VocSym.Attributes['TYPE'] ) and
( VpodItem.Attributes['NAME'] = i_VocSym.Attributes['NAME'] ) then
Umsc_StrSetUtils.AddElement( Buffer, dm_Vpod.GetItemNum( VpodItem ) );
end;
end;
Result := Buffer;
end;
(*
Добавляет в состояние i_State переход по символу i_VocSym в состояние,
обозначенное кодом i_Code
*)
procedure Tdm_Goto.AddTransition( i_State, i_VocSym: IXMLNode; i_Code: string );
var TranNode: IXMLNode;
begin
TranNode := i_State.AddChild( 'TRANSITION' );
TranNode.Attributes['TYPE'] := i_VocSym.Attributes['TYPE'];
TranNode.Attributes['NAME'] := i_VocSym.Attributes['NAME'];
TranNode.Attributes['STNAME'] := i_Code;
end;
(*
Прооцедура формирует начальное состояние из символа конца магазина
*)
procedure Tdm_Goto.BuildInitialState;
var InitSet: string;
begin
xml_States.LoadFromFile( frm_Main.GetTemplatePath + '\Template.xml' );
m_StateCount := 0;
InitStrSet( InitSet );
AddElement( InitSet, 0 );
Self.AddState( InitSet );
end;
(*
рурсивно строит таблицу переходов управляющего автомата
Надо её только вызвать для начального состояния.
*)
procedure Tdm_Goto.BuildReachables( i_State: IXMLNode );
var nVoc,nStat: integer; VocNode: IXMLNode; Code,Name: string; NewState: IXMLNode;
begin
for nVoc := 0 to xml_Voc.DocumentElement.ChildNodes.Count - 1 do
begin
VocNode := xml_Voc.DocumentElement.ChildNodes[nVoc];
Code := ResolveTransition( i_State, VocNode );
if ( IsEmpty( Code ) ) then Continue;
NewState := NIL;
nStat := Self.GetState(Code);
if ( nStat = -1 ) then
begin
NewState := AddState(Code);
nStat := m_StateCount - 1;
end;
Name := 'STATE_' + IntToStr(nStat);
Self.AddTransition( i_State, VocNode, Name );
if ( NewState <> NIL ) then Self.BuildReachables( NewState );
end;
end;
//ИНТЕРФЕЙС
// построение функции свёртки
procedure Tdm_Goto.BuildGotoFunction;
begin
try
//Построение обобщённого словаря грамматики
Self.BuildGeneralVocabulary;
//Формирование начального состояния автомата
Self.BuildInitialState;
//Поиск достижимых состояний автомата
Self.BuildReachables( xml_States.DocumentElement.ChildNodes[0] );
frm_Main.Log( '', clBlack );
except
frm_Main.Log( '[ОШИБКА] Обнаружена ошибка', clRed );
end;
end;
(*
Возвращает строковое представление состояния, однако не распарсивает
его грамматические вхождения
*)
function Tdm_Goto.GetStateDesc( i_State: IXMLNode ): string;
begin
Result := i_State.Attributes['NAME'];
end;
(*
Возвращает строковое представление перехода состояния по символу словаря
*)
function Tdm_Goto.GetTransDesc( i_Trans: IXMLNode ): string;
begin
Result := dm_Grammar.GetSymbolDesc( i_Trans ) + '(' + i_Trans.Attributes['STNAME'] + ')';
end;
(*
Проверяет для заданного состояния: определен ли на нём переход по нетерминалу
с именем i_NTermName. Это нужно при построении функции действий
*)
function Tdm_Goto.IsGotoDefined( i_State: IXMLNode; i_NTermName: string): boolean;
var nGoto: integer; GotoNode: IXMLNode;
begin
Result := FALSE;
for nGoto := 0 to i_State.ChildNodes.Count - 1 do
begin
GotoNode := i_State.ChildNodes[nGoto];
if ( GotoNode.Attributes['TYPE'] = 'nterm' ) and
( GotoNode.Attributes['NAME'] = i_NTermName ) then
Result := TRUE;
end;
end;
end.
Соседние файлы в папке SLR_Grammar