Changeset 119 for branches/generator/URules.pas
- Timestamp:
- Nov 29, 2017, 12:31:26 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/generator/URules.pas
r117 r119 6 6 7 7 uses 8 Classes, SysUtils, fgl, DOM, XmlRead, XmlWrite, UXMLUtils ;8 Classes, SysUtils, fgl, DOM, XmlRead, XmlWrite, UXMLUtils, Math; 9 9 10 10 type … … 32 32 NonTerminal: TRule; 33 33 SubItems: TRuleItems; 34 function GetCharLength: Integer; 34 35 procedure LoadFromXmlNode(Node: TDOMNode); 35 36 procedure SaveToXmlNode(Node: TDOMNode); 36 function Get BNF: string;37 function GetString: string; 37 38 constructor Create; 38 39 destructor Destroy; override; … … 52 53 Grammer: TGrammer; 53 54 RuleType: TRuleType; 55 function GetCharLength: Integer; 54 56 procedure LoadFromXmlNode(Node: TDOMNode); 55 57 procedure SaveToXmlNode(Node: TDOMNode); 56 58 procedure UpdateRuleReference; 57 function Get BNF: string;59 function GetString: string; 58 60 property ParentRule: TRule read FParentRule write SetParentRule; 59 61 end; … … 78 80 public 79 81 Name: string; 82 CreateSourceNode: Boolean; 80 83 Items: TRuleItems; 81 84 Links: TRuleLinks; … … 85 88 procedure LoadFromXmlNode(Node: TDOMNode); 86 89 procedure SaveToXmlNode(Node: TDOMNode); 87 function Get BNF: string;90 function GetString: string; 88 91 end; 89 92 … … 95 98 procedure LoadFromXmlNode(Node: TDOMNode); 96 99 procedure SaveToXmlNode(Node: TDOMNode); 97 function Get BNF: string;100 function GetString: string; 98 101 end; 99 102 … … 101 104 102 105 TGrammer = class 106 private 107 FModified: Boolean; 108 procedure SetModified(AValue: Boolean); 109 procedure BuildMain(FileName: string); 110 procedure BuildSource(FileName: string); 111 public 103 112 FileName: string; 104 113 Rules: TRules; … … 107 116 constructor Create; 108 117 destructor Destroy; override; 109 function GetBNF: string; 118 procedure BuildCompiler; 119 function GetString: string; 120 property Modified: Boolean read FModified write SetModified; 110 121 end; 111 122 … … 113 124 114 125 { TGrammer } 126 127 procedure TGrammer.SetModified(AValue: Boolean); 128 begin 129 if FModified = AValue then Exit; 130 FModified := AValue; 131 end; 132 133 procedure TGrammer.BuildMain(FileName: string); 134 var 135 ParserFile: TStringList; 136 begin 137 ParserFile := TStringList.Create; 138 with ParserFile do begin 139 Add('program Compiler;'); 140 Add(''); 141 Add('{$MODE Delphi}'); 142 Add(''); 143 Add('uses'); 144 Add(' Source;'); 145 Add(''); 146 Add('procedure Compile;'); 147 Add('begin'); 148 Add('end;'); 149 Add(''); 150 Add('begin'); 151 Add(' Compile;'); 152 Add('end.'); 153 SaveToFile(FileName); 154 end; 155 FreeAndNil(ParserFile); 156 end; 157 158 procedure TGrammer.BuildSource(FileName: string); 159 var 160 Rule: TRule; 161 Item: TRuleItem; 162 Line: string; 163 I: Integer; 164 SourceFile: TStringList; 165 begin 166 SourceFile := TStringList.Create; 167 with SourceFile do begin 168 Add('unit Source;'); 169 Add(''); 170 Add('{$MODE Delphi}'); 171 Add(''); 172 Add('interface'); 173 Add(''); 174 Add('uses'); 175 Add(' fgl;'); 176 Add(''); 177 Add('type'); 178 for Rule in Rules do begin 179 Add(' T' + Rule.Name + ' = class;'); 180 end; 181 Add(''); 182 for Rule in Rules do begin 183 Add(' T' + Rule.Name + ' = class'); 184 for Item in Rule.Items do begin 185 if Item.RuleItemType = ritNonTerminal then 186 if Item.Repetitive then 187 Add(' ' + Item.NonTerminal.Name + ': TFPGObjectList<T' + Item.NonTerminal.Name + '>;') 188 else Add(' ' + Item.NonTerminal.Name + ': T' + Item.NonTerminal.Name + ';'); 189 end; 190 Add(' end;' + LineEnding); 191 end; 192 Add(''); 193 Add('implementation'); 194 Add(''); 195 for Rule in Rules do 196 if Rule.CreateSourceNode then begin 197 Add('function Parse' + Rule.Name + ': Boolean;'); 198 Add('begin'); 199 I := 0; 200 for Item in Rule.Items do begin 201 Line := ' '; 202 if Rule.Items.RuleType = rtOr then begin 203 if I > 0 then Line := Line + 'else '; 204 Line := Line + 'if '; 205 end else 206 if Rule.Items.RuleType = rtAnd then begin 207 Line := Line + ''; 208 end; 209 if Item.RuleItemType = ritTerminal then 210 Line := Line + 'Expect(''' + Item.Terminal + ''')' 211 else if Item.RuleItemType = ritNonTerminal then 212 Line := Line + 'Parse' + Item.NonTerminal.Name; 213 if Rule.Items.RuleType = rtOr then begin 214 Line := Line + ' then '; 215 end else 216 if Rule.Items.RuleType = rtAnd then begin 217 Line := Line + ';'; 218 end; 219 Add(Line); 220 Inc(I); 221 end; 222 if Rule.Items.RuleType = rtOr then begin 223 Add(' else ShowError(''Unexpected token'');'); 224 end; 225 Add('end;'); 226 Add(''); 227 end; 228 229 Add('end.'); 230 231 SaveToFile(FileName); 232 end; 233 FreeAndNil(SourceFile); 234 end; 115 235 116 236 procedure TGrammer.LoadFromXmlFile(FileName: string); … … 159 279 160 280 WriteXMLFile(Doc, FileName); 281 Modified := False; 161 282 finally 162 283 Doc.Free; … … 176 297 end; 177 298 178 function TGrammer.GetBNF: string; 179 begin 180 Result := Rules.GetBNF; 299 procedure TGrammer.BuildCompiler; 300 var 301 OutputDir: string; 302 begin 303 OutputDir := 'Generated'; 304 ForceDirectories(OutputDir); 305 306 BuildMain(OutputDir + DirectorySeparator + 'Compiler.pas'); 307 BuildSource(OutputDir + DirectorySeparator +'Source.pas'); 308 end; 309 310 function TGrammer.GetString: string; 311 begin 312 Result := Rules.GetString; 181 313 end; 182 314 … … 202 334 end; 203 335 204 function TRuleItem.Get BNF: string;336 function TRuleItem.GetString: string; 205 337 begin 206 338 case RuleItemType of 207 339 ritTerminal: Result := '"' + Terminal + '"'; 208 340 ritNonTerminal: Result := NonTerminal.Name; 209 ritSubItems: Result := '(' + SubItems.Get BNF+ ')';341 ritSubItems: Result := '(' + SubItems.GetString + ')'; 210 342 end; 211 343 if Optional then Result := '+' + Result; … … 230 362 FParentRule := AValue; 231 363 SubItems.ParentRule := AValue; 364 end; 365 366 function TRuleItem.GetCharLength: Integer; 367 begin 368 case RuleItemType of 369 ritTerminal: Result := Length(Terminal); 370 ritNonTerminal: Result := Length(NonTerminal.Name); 371 ritSubItems: Result := SubItems.GetCharLength; 372 end; 232 373 end; 233 374 … … 283 424 end; 284 425 285 function TRuleItems.Get BNF: string;426 function TRuleItems.GetString: string; 286 427 var 287 428 Item: TRuleItem; … … 293 434 else if RuleType = rtOr then Result := Result + ' | '; 294 435 end; 295 Result := Result + Item.Get BNF;436 Result := Result + Item.GetString; 296 437 end; 297 438 end; … … 301 442 if FParentRule = AValue then Exit; 302 443 FParentRule := AValue; 444 end; 445 446 function TRuleItems.GetCharLength: Integer; 447 var 448 Item: TRuleItem; 449 begin 450 Result := 0; 451 if RuleType = rtOr then begin 452 for Item in Self do 453 Result := Max(Result, Item.GetCharLength); 454 end else 455 if RuleType = rtAnd then begin 456 for Item in Self do 457 Result := Result + Item.GetCharLength; 458 end; 303 459 end; 304 460 … … 330 486 begin 331 487 WriteString(Node, 'Name', Name); 488 WriteBoolean(Node, 'CreateSourceNode', CreateSourceNode); 332 489 333 490 RuleItemsNode := Node.OwnerDocument.CreateElement('RuleItems'); … … 336 493 end; 337 494 338 function TRule.Get BNF: string;339 begin 340 Result := Name + ' ::= ' + Items.Get BNF;495 function TRule.GetString: string; 496 begin 497 Result := Name + ' ::= ' + Items.GetString; 341 498 end; 342 499 … … 370 527 begin 371 528 Name := ReadString(Node, 'Name', ''); 529 CreateSourceNode := ReadBoolean(Node, 'CreateSourceNode', False); 372 530 373 531 ItemsNode := Node.FindNode('RuleItems'); … … 418 576 end; 419 577 420 function TRules.Get BNF: string;578 function TRules.GetString: string; 421 579 var 422 580 Rule: TRule; … … 424 582 Result := ''; 425 583 for Rule in Self do begin 426 Result := Result + Rule.Get BNF+ LineEnding;584 Result := Result + Rule.GetString + LineEnding; 427 585 end; 428 586 end;
Note:
See TracChangeset
for help on using the changeset viewer.