Скачиваний:
13
Добавлен:
01.05.2014
Размер:
6.33 Кб
Скачать
// Авторы студенты группы 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.
Соседние файлы в папке SLR_Grammar
  • #
    01.05.201412.22 Кб12Udm_Action.dcu
  • #
    01.05.2014192 б12Udm_Action.dfm
  • #
    01.05.20149.98 Кб13Udm_Action.pas
  • #
    01.05.20148.28 Кб12Udm_First.dcu
  • #
    01.05.2014290 б12Udm_First.dfm
  • #
    01.05.20146.33 Кб13Udm_First.pas
  • #
    01.05.20147.27 Кб12Udm_Follow.dcu
  • #
    01.05.2014191 б12Udm_Follow.dfm
  • #
    01.05.20144.62 Кб13Udm_Follow.pas
  • #
    01.05.20149.93 Кб12Udm_Goto.dcu
  • #
    01.05.2014283 б12Udm_Goto.dfm