Скачиваний:
14
Добавлен:
01.05.2014
Размер:
6 Кб
Скачать
//  Авторы студенты группы 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 Кб13Udm_Action.dcu
  • #
    01.05.2014192 б13Udm_Action.dfm
  • #
    01.05.201410 Кб14Udm_Action.pas
  • #
    01.05.20148 Кб13Udm_First.dcu
  • #
    01.05.2014290 б13Udm_First.dfm
  • #
    01.05.20146 Кб14Udm_First.pas
  • #
    01.05.20147 Кб13Udm_Follow.dcu
  • #
    01.05.2014191 б13Udm_Follow.dfm
  • #
    01.05.20145 Кб14Udm_Follow.pas
  • #
    01.05.201410 Кб13Udm_Goto.dcu
  • #
    01.05.2014283 б13Udm_Goto.dfm