Ignore:
Timestamp:
Nov 27, 2017, 1:09:38 PM (7 years ago)
Author:
chronos
Message:
  • Added: Rule can be set as optional or repetitive.
  • Added: Support for nested rule item sublist.
Location:
branches/generator
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/generator

    • Property svn:ignore
      •  

        old new  
        22generator.lps
        33lib
         4heaptrclog.trc
  • branches/generator/URules.pas

    r116 r117  
    1212  TRules = class;
    1313  TGrammer = class;
    14 
    15   TRuleItemType = (ritTerminal, ritNonTerminal);
     14  TRuleItems = class;
     15
     16  TRuleItemType = (ritTerminal, ritNonTerminal, ritSubItems);
    1617
    1718  { TRuleItem }
    1819
    1920  TRuleItem = class
    20     ParentRule: TRule;
     21  private
     22    FGrammer: TGrammer;
     23    FParentRule: TRule;
     24    procedure SetGrammer(AValue: TGrammer);
     25    procedure SetParentRule(AValue: TRule);
     26  public
     27    Optional: Boolean;
     28    Repetitive: Boolean;
    2129    RuleItemType: TRuleItemType;
    2230    Terminal: string;
    2331    NonTerminalName: string;
    2432    NonTerminal: TRule;
    25     Grammer: TGrammer;
     33    SubItems: TRuleItems;
    2634    procedure LoadFromXmlNode(Node: TDOMNode);
    2735    procedure SaveToXmlNode(Node: TDOMNode);
    2836    function GetBNF: string;
     37    constructor Create;
     38    destructor Destroy; override;
     39    property Grammer: TGrammer read FGrammer write SetGrammer;
     40    property ParentRule: TRule read FParentRule write SetParentRule;
    2941  end;
    3042
     
    3446
    3547  TRuleItems = class(TFPGObjectList<TRuleItem>)
    36     ParentRule: TRule;
     48  private
     49    FParentRule: TRule;
     50    procedure SetParentRule(AValue: TRule);
     51  public
    3752    Grammer: TGrammer;
    3853    RuleType: TRuleType;
    3954    procedure LoadFromXmlNode(Node: TDOMNode);
    4055    procedure SaveToXmlNode(Node: TDOMNode);
    41     function GetBNF(RuleType: TRuleType): string;
     56    procedure UpdateRuleReference;
     57    function GetBNF: string;
     58    property ParentRule: TRule read FParentRule write SetParentRule;
    4259  end;
    4360
     
    103120  RulesNode: TDOMNode;
    104121  Rule: TRule;
    105   RuleItem: TRuleItem;
    106122begin
    107123  Self.FileName := FileName;
     
    123139  // Update rule references
    124140  for Rule in Rules do
    125     for RuleItem in Rule.Items do
    126       if RuleItem.RuleItemType = ritNonTerminal then
    127         RuleItem.NonTerminal := Rules.FindName(RuleItem.NonTerminalName);
     141    Rule.Items.UpdateRuleReference;
    128142end;
    129143
     
    170184
    171185procedure TRuleItem.SaveToXmlNode(Node: TDOMNode);
     186var
     187  SubItemsNode: TDOMNode;
    172188begin
    173189  WriteInteger(Node, 'Type', Integer(RuleItemType));
    174   if RuleItemType = ritTerminal then WriteString(Node, 'Terminal', Terminal)
    175   else if RuleItemType = ritNonTerminal then WriteString(Node, 'NonTerminal', NonTerminal.Name)
     190  WriteBoolean(Node, 'Optional', Optional);
     191  WriteBoolean(Node, 'Repetitive', Repetitive);
     192
     193  case RuleItemType of
     194    ritTerminal: WriteString(Node, 'Terminal', Terminal);
     195    ritNonTerminal: WriteString(Node, 'NonTerminal', NonTerminal.Name);
     196    ritSubItems: begin
     197      SubItemsNode := Node.OwnerDocument.CreateElement('SubItems');
     198      Node.AppendChild(SubItemsNode);
     199      SubItems.SaveToXmlNode(SubItemsNode);
     200    end;
     201  end;
    176202end;
    177203
    178204function TRuleItem.GetBNF: string;
    179205begin
    180   if RuleItemType = ritTerminal then Result := '"' + Terminal + '"'
    181     else if RuleItemType = ritNonTerminal then Result := NonTerminal.Name;
     206  case RuleItemType of
     207    ritTerminal: Result := '"' + Terminal + '"';
     208    ritNonTerminal: Result := NonTerminal.Name;
     209    ritSubItems: Result := '(' + SubItems.GetBNF + ')';
     210  end;
     211  if Optional then Result := '+' + Result;
     212  if Repetitive then Result := '*' + Result;
     213end;
     214
     215constructor TRuleItem.Create;
     216begin
     217  SubItems := TRuleItems.Create;
     218  SubItems.Grammer := Grammer;
     219end;
     220
     221destructor TRuleItem.Destroy;
     222begin
     223  FreeAndNil(SubItems);
     224  inherited Destroy;
     225end;
     226
     227procedure TRuleItem.SetParentRule(AValue: TRule);
     228begin
     229  if FParentRule = AValue then Exit;
     230  FParentRule := AValue;
     231  SubItems.ParentRule := AValue;
     232end;
     233
     234procedure TRuleItem.SetGrammer(AValue: TGrammer);
     235begin
     236  if FGrammer = AValue then Exit;
     237  FGrammer := AValue;
     238  SubItems.Grammer := AValue;
    182239end;
    183240
    184241procedure TRuleItem.LoadFromXmlNode(Node: TDOMNode);
     242var
     243  SubItemsNode: TDOMNode;
    185244begin
    186245  RuleItemType := TRuleItemType(ReadInteger(Node, 'Type', Integer(ritTerminal)));
    187   if RuleItemType = ritTerminal then Terminal := ReadString(Node, 'Terminal', '')
    188   else if RuleItemType = ritNonTerminal then
    189     NonTerminalName := ReadString(Node, 'NonTerminal', '');
     246  Optional := ReadBoolean(Node, 'Optional', False);
     247  Repetitive := ReadBoolean(Node, 'Repetitive', False);
     248  case RuleItemType of
     249    ritTerminal: Terminal := ReadString(Node, 'Terminal', '');
     250    ritNonTerminal: NonTerminalName := ReadString(Node, 'NonTerminal', '');
     251    ritSubItems: begin
     252      SubItemsNode := Node.FindNode('SubItems');
     253      if Assigned(SubItemsNode) then SubItems.LoadFromXmlNode(SubItemsNode);
     254    end;
     255  end;
    190256end;
    191257
     
    206272end;
    207273
    208 function TRuleItems.GetBNF(RuleType: TRuleType): string;
     274procedure TRuleItems.UpdateRuleReference;
     275var
     276  RuleItem: TRuleItem;
     277begin
     278  for RuleItem in Self do
     279    case RuleItem.RuleItemType of
     280      ritNonTerminal: RuleItem.NonTerminal := Grammer.Rules.FindName(RuleItem.NonTerminalName);
     281      ritSubItems: RuleItem.SubItems.UpdateRuleReference;
     282    end;
     283end;
     284
     285function TRuleItems.GetBNF: string;
    209286var
    210287  Item: TRuleItem;
     
    220297end;
    221298
     299procedure TRuleItems.SetParentRule(AValue: TRule);
     300begin
     301  if FParentRule = AValue then Exit;
     302  FParentRule := AValue;
     303end;
     304
    222305procedure TRuleItems.LoadFromXmlNode(Node: TDOMNode);
    223306var
     
    232315      RuleItem := TRuleItem.Create;
    233316      RuleItem.Grammer := Grammer;
     317      RuleItem.ParentRule := ParentRule;
    234318      RuleItem.LoadFromXmlNode(RuleItemNode);
    235319      Add(RuleItem);
     
    254338function TRule.GetBNF: string;
    255339begin
    256   Result := Name + ' ::= ' + Items.GetBNF(Items.RuleType);
     340  Result := Name + ' ::= ' + Items.GetBNF;
    257341end;
    258342
Note: See TracChangeset for help on using the changeset viewer.