Ignore:
Timestamp:
Aug 9, 2017, 12:09:47 AM (7 years ago)
Author:
chronos
Message:
  • Added: RuleItem can be selected as terminal or non-terminal node.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/generator/URules.pas

    r110 r111  
    99
    1010type
     11  TRule = class;
     12  TRules = class;
     13  TGrammer = class;
     14
     15  TRuleItemType = (ritTerminal, ritNonTerminal);
    1116
    1217  { TRuleItem }
    1318
    1419  TRuleItem = class
    15     Name: string;
     20    ParentRule: TRule;
     21    RuleItemType: TRuleItemType;
     22    Terminal: string;
     23    NonTerminalName: string;
     24    NonTerminal: TRule;
     25    Grammer: TGrammer;
    1626    procedure LoadFromXmlNode(Node: TDOMNode);
    1727    procedure SaveToXmlNode(Node: TDOMNode);
     28    function GetBNF: string;
    1829  end;
    1930
     
    2132
    2233  TRuleItems = class(TFPGObjectList<TRuleItem>)
     34    Grammer: TGrammer;
    2335    procedure LoadFromXmlNode(Node: TDOMNode);
    2436    procedure SaveToXmlNode(Node: TDOMNode);
    2537  end;
    2638
     39  TRuleType = (rtAnd, rtOr);
     40
    2741  { TRule }
    2842
    2943  TRule = class
     44  private
     45    function GetGrammer: TGrammer;
     46    procedure SetGrammer(AValue: TGrammer);
     47  public
    3048    Name: string;
    3149    Items: TRuleItems;
     50    RuleType: TRuleType;
     51    property Grammer: TGrammer read GetGrammer write SetGrammer;
    3252    constructor Create;
    3353    destructor Destroy; override;
     
    4060
    4161  TRules = class(TFPGObjectList<TRule>)
    42     FileName: string;
     62    Grammer: TGrammer;
     63    function FindName(Name: string): TRule;
    4364    procedure LoadFromXmlNode(Node: TDOMNode);
    4465    procedure SaveToXmlNode(Node: TDOMNode);
     66    function GetBNF: string;
     67  end;
     68
     69  { TGrammer }
     70
     71  TGrammer = class
     72    FileName: string;
     73    Rules: TRules;
    4574    procedure LoadFromXmlFile(FileName: string);
    4675    procedure SaveToXmlFile(FileName: string);
     76    constructor Create;
     77    destructor Destroy; override;
    4778    function GetBNF: string;
    4879  end;
     
    5081implementation
    5182
    52 { TRuleItem }
    53 
    54 procedure TRuleItem.SaveToXmlNode(Node: TDOMNode);
    55 begin
    56   WriteString(Node, 'Name', Name);
    57 end;
    58 
    59 procedure TRuleItem.LoadFromXmlNode(Node: TDOMNode);
    60 begin
    61   Name := ReadString(Node, 'Name', '');
    62 end;
    63 
    64 { TRuleItems }
    65 
    66 procedure TRuleItems.SaveToXmlNode(Node: TDOMNode);
    67 var
    68   RuleItem: TRuleItem;
    69   RuleItemNode: TDOMNode;
    70 begin
    71   for RuleItem in Self do begin
    72     RuleItemNode := Node.OwnerDocument.CreateElement('RuleItem');
    73     RuleItem.SaveToXmlNode(RuleItemNode);
    74     Node.AppendChild(RuleItemNode);
    75   end;
    76 end;
    77 
    78 procedure TRuleItems.LoadFromXmlNode(Node: TDOMNode);
    79 var
    80   RuleItemNode: TDOMNode;
    81   RuleItem: TRuleItem;
    82 begin
    83   RuleItemNode := Node.FirstChild;
    84   while Assigned(RuleItemNode) do begin
    85     if RuleItemNode.NodeName = 'RuleItem' then begin
    86       RuleItem := TRuleItem.Create;
    87       RuleItem.LoadFromXmlNode(RuleItemNode);
    88       Add(RuleItem);
    89     end;
    90     RuleItemNode := RuleItemNode.NextSibling;
    91   end;
    92 end;
    93 
    94 { TRule }
    95 
    96 procedure TRule.SaveToXmlNode(Node: TDOMNode);
    97 var
    98   RuleItemsNode: TDOMNode;
    99 begin
    100   WriteString(Node, 'Name', Name);
    101 
    102   RuleItemsNode := Node.OwnerDocument.CreateElement('RuleItems');
    103   Node.AppendChild(RuleItemsNode);
    104   Items.SaveToXmlNode(RuleItemsNode);
    105 end;
    106 
    107 function TRule.GetBNF: string;
    108 var
    109   Item: TRuleItem;
    110 begin
    111   Result := Name + ' ::=';
    112   for Item in Items do begin
    113     Result := Result + ' ' + Item.Name;
    114   end;
    115 end;
    116 
    117 constructor TRule.Create;
    118 begin
    119   Items := TRuleItems.Create;
    120 end;
    121 
    122 destructor TRule.Destroy;
    123 begin
    124   FreeAndNil(Items);
    125   inherited Destroy;
    126 end;
    127 
    128 procedure TRule.LoadFromXmlNode(Node: TDOMNode);
    129 var
    130   ItemsNode: TDOMNode;
    131 begin
    132   Name := ReadString(Node, 'Name', '');
    133 
    134   ItemsNode := Node.FindNode('RuleItems');
    135   if Assigned(ItemsNode) then begin
    136     Items.LoadFromXmlNode(ItemsNode);
    137   end;
    138 end;
    139 
    140 { TRules }
    141 
    142 procedure TRules.SaveToXmlNode(Node: TDOMNode);
    143 var
    144   Rule: TRule;
    145   RuleNode: TDOMNode;
    146 begin
    147   for Rule in Self do begin
    148     RuleNode := Node.OwnerDocument.CreateElement('Rule');
    149     Rule.SaveToXmlNode(RuleNode);
    150     Node.AppendChild(RuleNode);
    151   end;
    152 end;
    153 
    154 procedure TRules.LoadFromXmlNode(Node: TDOMNode);
    155 var
    156   RuleNode: TDOMNode;
    157   Rule: TRule;
    158 begin
    159   RuleNode := Node.FirstChild;
    160   while Assigned(RuleNode) do begin
    161     if RuleNode.NodeName = 'Rule' then begin
    162       Rule := TRule.Create;
    163       Rule.LoadFromXmlNode(RuleNode);
    164       Add(Rule);
    165     end;
    166     RuleNode := RuleNode.NextSibling;
    167   end;
    168 end;
    169 
    170 procedure TRules.LoadFromXmlFile(FileName: string);
     83{ TGrammer }
     84
     85procedure TGrammer.LoadFromXmlFile(FileName: string);
    17186var
    17287  Doc: TXMLDocument;
    17388  RootNode: TDOMNode;
    17489  RulesNode: TDOMNode;
     90  Rule: TRule;
     91  RuleItem: TRuleItem;
    17592begin
    17693  Self.FileName := FileName;
    177   Clear;
     94  Rules.Clear;
    17895  try
    17996    ReadXMLFile(Doc, FileName);
     
    183100      RulesNode := RootNode.FindNode('Rules');
    184101      if Assigned(RulesNode) then begin
    185         LoadFromXmlNode(RulesNode);
     102        Rules.LoadFromXmlNode(RulesNode);
    186103      end;
    187104    end;
     
    189106    Doc.Free;
    190107  end;
    191 end;
    192 
    193 procedure TRules.SaveToXmlFile(FileName: string);
     108
     109  // Update rule references
     110  for Rule in Rules do
     111    for RuleItem in Rule.Items do
     112      if RuleItem.RuleItemType = ritNonTerminal then
     113        RuleItem.NonTerminal := Rules.FindName(RuleItem.NonTerminalName);
     114end;
     115
     116procedure TGrammer.SaveToXmlFile(FileName: string);
    194117var
    195118  Doc: TXMLDocument;
     
    205128    RulesNode := Doc.CreateElement('Rules');
    206129    RootNode.AppendChild(RulesNode);
    207     SaveToXmlNode(RulesNode);
     130    Rules.SaveToXmlNode(RulesNode);
    208131
    209132    WriteXMLFile(Doc, FileName);
     
    213136end;
    214137
     138constructor TGrammer.Create;
     139begin
     140  Rules := TRules.Create;
     141  Rules.Grammer := Self;
     142end;
     143
     144destructor TGrammer.Destroy;
     145begin
     146  FreeAndNil(Rules);
     147  inherited Destroy;
     148end;
     149
     150function TGrammer.GetBNF: string;
     151begin
     152  Result := Rules.GetBNF;
     153end;
     154
     155{ TRuleItem }
     156
     157procedure TRuleItem.SaveToXmlNode(Node: TDOMNode);
     158begin
     159  WriteInteger(Node, 'Type', Integer(RuleItemType));
     160  if RuleItemType = ritTerminal then WriteString(Node, 'Terminal', Terminal)
     161  else if RuleItemType = ritNonTerminal then WriteString(Node, 'NonTerminal', NonTerminal.Name)
     162end;
     163
     164function TRuleItem.GetBNF: string;
     165begin
     166  if RuleItemType = ritTerminal then Result := '"' + Terminal + '"'
     167    else if RuleItemType = ritNonTerminal then Result := NonTerminal.Name;
     168end;
     169
     170procedure TRuleItem.LoadFromXmlNode(Node: TDOMNode);
     171begin
     172  RuleItemType := TRuleItemType(ReadInteger(Node, 'Type', Integer(ritTerminal)));
     173  if RuleItemType = ritTerminal then Terminal := ReadString(Node, 'Terminal', '')
     174  else if RuleItemType = ritNonTerminal then
     175    NonTerminalName := ReadString(Node, 'NonTerminal', '');
     176end;
     177
     178{ TRuleItems }
     179
     180procedure TRuleItems.SaveToXmlNode(Node: TDOMNode);
     181var
     182  RuleItem: TRuleItem;
     183  RuleItemNode: TDOMNode;
     184begin
     185  for RuleItem in Self do begin
     186    RuleItemNode := Node.OwnerDocument.CreateElement('RuleItem');
     187    RuleItem.SaveToXmlNode(RuleItemNode);
     188    Node.AppendChild(RuleItemNode);
     189  end;
     190end;
     191
     192procedure TRuleItems.LoadFromXmlNode(Node: TDOMNode);
     193var
     194  RuleItemNode: TDOMNode;
     195  RuleItem: TRuleItem;
     196begin
     197  RuleItemNode := Node.FirstChild;
     198  while Assigned(RuleItemNode) do begin
     199    if RuleItemNode.NodeName = 'RuleItem' then begin
     200      RuleItem := TRuleItem.Create;
     201      RuleItem.Grammer := Grammer;
     202      RuleItem.LoadFromXmlNode(RuleItemNode);
     203      Add(RuleItem);
     204    end;
     205    RuleItemNode := RuleItemNode.NextSibling;
     206  end;
     207end;
     208
     209{ TRule }
     210
     211procedure TRule.SaveToXmlNode(Node: TDOMNode);
     212var
     213  RuleItemsNode: TDOMNode;
     214begin
     215  WriteString(Node, 'Name', Name);
     216
     217  RuleItemsNode := Node.OwnerDocument.CreateElement('RuleItems');
     218  Node.AppendChild(RuleItemsNode);
     219  Items.SaveToXmlNode(RuleItemsNode);
     220end;
     221
     222function TRule.GetBNF: string;
     223var
     224  Item: TRuleItem;
     225begin
     226  Result := Name + ' ::= ';
     227  for Item in Items do begin
     228    if Item <> Items.First then begin
     229      if RuleType = rtAnd then Result := Result + ' '
     230      else if RuleType = rtOr then Result := Result + ' | ';
     231    end;
     232    Result := Result + Item.GetBNF;
     233  end;
     234end;
     235
     236function TRule.GetGrammer: TGrammer;
     237begin
     238  Result := Items.Grammer;
     239end;
     240
     241procedure TRule.SetGrammer(AValue: TGrammer);
     242begin
     243  Items.Grammer := AValue;
     244end;
     245
     246constructor TRule.Create;
     247begin
     248  Items := TRuleItems.Create;
     249end;
     250
     251destructor TRule.Destroy;
     252begin
     253  FreeAndNil(Items);
     254  inherited Destroy;
     255end;
     256
     257procedure TRule.LoadFromXmlNode(Node: TDOMNode);
     258var
     259  ItemsNode: TDOMNode;
     260begin
     261  Name := ReadString(Node, 'Name', '');
     262
     263  ItemsNode := Node.FindNode('RuleItems');
     264  if Assigned(ItemsNode) then begin
     265    Items.LoadFromXmlNode(ItemsNode);
     266  end;
     267end;
     268
     269{ TRules }
     270
     271procedure TRules.SaveToXmlNode(Node: TDOMNode);
     272var
     273  Rule: TRule;
     274  RuleNode: TDOMNode;
     275begin
     276  for Rule in Self do begin
     277    RuleNode := Node.OwnerDocument.CreateElement('Rule');
     278    Rule.SaveToXmlNode(RuleNode);
     279    Node.AppendChild(RuleNode);
     280  end;
     281end;
     282
     283function TRules.FindName(Name: string): TRule;
     284var
     285  I: Integer;
     286begin
     287  I := 0;
     288  while (I < Count) and (Items[I].Name <> Name) do Inc(I);
     289  if I < Count then Result := Items[I]
     290    else Result := nil;
     291end;
     292
     293procedure TRules.LoadFromXmlNode(Node: TDOMNode);
     294var
     295  RuleNode: TDOMNode;
     296  Rule: TRule;
     297begin
     298  RuleNode := Node.FirstChild;
     299  while Assigned(RuleNode) do begin
     300    if RuleNode.NodeName = 'Rule' then begin
     301      Rule := TRule.Create;
     302      Rule.Grammer := Grammer;
     303      Rule.LoadFromXmlNode(RuleNode);
     304      Add(Rule);
     305    end;
     306    RuleNode := RuleNode.NextSibling;
     307  end;
     308end;
     309
    215310function TRules.GetBNF: string;
    216311var
Note: See TracChangeset for help on using the changeset viewer.