Changeset 129 for branches/generator/UGrammer.pas
- Timestamp:
- Dec 19, 2017, 4:56:34 PM (7 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
branches/generator/UGrammer.pas
r128 r129 1 unit U Rules;1 unit UGrammer; 2 2 3 3 {$mode delphi}{$H+} … … 75 75 end; 76 76 77 TRuleLevel = (rlParser, rlTokenizer); 78 77 79 { TRule } 78 80 … … 84 86 Name: string; 85 87 CreateSourceNode: Boolean; 88 Level: TRuleLevel; 86 89 Items: TRuleItems; 87 90 Links: TRuleLinks; … … 110 113 private 111 114 FModified: Boolean; 112 function GetItemString(Item: TRuleItem; Required: Boolean): string;113 115 procedure SetModified(AValue: Boolean); 114 procedure BuildParser(FileName: string);115 procedure BuildMain(FileName: string);116 procedure BuildSource(FileName: string);117 116 public 118 117 FileName: string; … … 124 123 constructor Create; 125 124 destructor Destroy; override; 126 procedure BuildCompiler;127 125 procedure GetUsedByRule(RefRule: TRule; UsedByRules: TStrings); 128 126 function GetString: string; … … 130 128 end; 131 129 130 const 131 RuleLevelText: array[TRuleLevel] of string = ('Parser', 'Tokenizer'); 132 RuleTypeText: array[TRuleType] of string = ('and', 'or'); 133 134 132 135 implementation 133 136 134 const135 BooleanText: array[Boolean] of string = ('False', 'True');136 137 137 { TGrammer } 138 139 function TGrammer.GetItemString(Item: TRuleItem; Required: Boolean): string;140 begin141 Result := '';142 case Item.RuleItemType of143 ritTerminal: Result := 'Expect(''' +144 StringReplace(Item.Terminal, '''', '''''', [rfReplaceAll]) + ''', ' + BooleanText[Required] + ')';145 ritNonTerminal: Result := 'Parse' + Item.NonTerminal.Name + '(' + BooleanText[Required] + ')';146 ritTerminalRange: Result := 'ExpectRange(''' +147 StringReplace(Item.TerminalFrom, '''', '''''', [rfReplaceAll]) + ''', ''' +148 StringReplace(Item.TerminalTo, '''', '''''', [rfReplaceAll]) + ''', ' + BooleanText[Required] + ')';149 //ritSubItems: Line := 'Parse +';150 end;151 end;152 138 153 139 procedure TGrammer.SetModified(AValue: Boolean); … … 155 141 if FModified = AValue then Exit; 156 142 FModified := AValue; 157 end;158 159 procedure TGrammer.BuildParser(FileName: string);160 var161 ParserFile: TStringList;162 Rule: TRule;163 I: Integer;164 Line: string;165 Item: TRuleItem;166 Required: Boolean;167 begin168 ParserFile := TStringList.Create;169 with ParserFile do begin170 Add('unit Parser;');171 Add('');172 Add('{$MODE Delphi}');173 Add('');174 Add('interface');175 Add('');176 Add('uses');177 Add(' SysUtils;');178 Add('');179 Add('type');180 Add(' TParser = class');181 Add(' Content: string;');182 Add(' FileName: string;');183 Add(' Position: Integer;');184 Add(' procedure Error(Text: string);');185 Add(' function Expect(Text: string; Required: Boolean = False): Boolean;');186 Add(' function ExpectRange(CharFrom, CharTo: Char; Required: Boolean = False): Boolean;');187 for Rule in Rules do188 Add(' function Parse' + Rule.Name + '(Required: Boolean = False): Boolean;');189 Add(' constructor Create;');190 Add(' end;');191 Add('');192 Add('implementation');193 Add('');194 Add('constructor TParser.Create;');195 Add('begin');196 Add(' Position := 1;');197 Add('end;');198 Add('');199 Add('procedure TParser.Error(Text: string);');200 Add('begin');201 Add(' WriteLn(FileName + ''('' + IntToStr(Position) + '') Error: '' + Text);');202 Add('end;');203 Add('');204 Add('function TParser.Expect(Text: string; Required: Boolean = False): Boolean;');205 Add('var');206 Add(' ReadText: string;');207 Add(' StartPos: Integer;');208 Add('begin');209 Add(' StartPos := Position;');210 Add(' ReadText := Copy(Content, Position, Length(Text));');211 Add(' Inc(Position, Length(Text));');212 Add(' Result := Text = ReadText;');213 Add(' if not Result then begin');214 Add(' Position := StartPos;');215 Add(' if Required then Error(''Expected "'' + Text + ''" but found "'' + ReadText + ''".'');');216 Add(' end;');217 Add('end;');218 Add('');219 Add('function TParser.ExpectRange(CharFrom, CharTo: char; Required: Boolean = False): Boolean;');220 Add('var');221 Add(' ReadChar: Char;');222 Add(' StartPos: Integer;');223 Add('begin');224 Add(' StartPos := Position;');225 Add(' ReadChar := Content[Position];');226 Add(' Inc(Position, 1);');227 Add(' Result := (ReadChar >= CharFrom) and (ReadChar <= CharTo);');228 Add(' if not Result then begin');229 Add(' Position := StartPos;');230 Add(' if Required then Error(''Expected "'' + CharFrom + ''" to "'' + CharTo + ''" but found "'' + ReadChar + ''".'');');231 Add(' end;');232 Add('end;');233 Add('');234 for Rule in Rules do begin235 Add('function TParser.Parse' + Rule.Name + '(Required: Boolean = False): Boolean;');236 Add('begin');237 Add(' Result := True;');238 I := 0;239 for Item in Rule.Items do begin240 Required := not Item.Optional;241 Line := ' ';242 case Rule.Items.RuleType of243 rtOr: begin244 if I > 0 then Line := Line + 'else ';245 Line := Line + 'if ' + GetItemString(Item, False);246 Line := Line + ' then Exit';247 end;248 rtAnd: begin249 Line := Line + 'Result := Result and ';250 if Item.Optional then Line := Line + 'True;' + LineEnding;251 if Item.Repetitive then begin252 if not Item.Optional then253 Line := Line + ' ' + GetItemString(Item, Required) + ';' + LineEnding;254 Line := Line + ' repeat' + LineEnding + ' if not ';255 Required := False;256 end;257 Line := Line + GetItemString(Item, Required);258 if Item.Repetitive then Line := Line + ' then Break;' + LineEnding + ' until False';259 Line := Line + ';' + LineEnding + ' if not Result then Exit;';260 end;261 end;262 Add(Line);263 Inc(I);264 end;265 case Rule.Items.RuleType of266 rtOr: begin267 Add(' else begin');268 Add(' Error(''Unexpected token'');');269 Add(' Result := False;');270 Add(' end;');271 end;272 //rtAnd: Add(' if not Result then ShowError('''')');273 end;274 Add('end;');275 Add('');276 end;277 Add('');278 Add('end.');279 SaveToFile(FileName);280 end;281 FreeAndNil(ParserFile);282 end;283 284 procedure TGrammer.BuildMain(FileName: string);285 var286 ParserFile: TStringList;287 begin288 ParserFile := TStringList.Create;289 with ParserFile do begin290 Add('program Compiler;');291 Add('');292 Add('{$MODE Delphi}');293 Add('');294 Add('uses');295 Add(' Source, Parser, SysUtils;');296 Add('');297 Add('procedure Compile(FileName: string);');298 Add('var');299 Add(' SourceFile: file of Char;');300 Add(' Parser: TParser;');301 Add(' I: Integer;');302 Add('begin');303 Add(' AssignFile(SourceFile, FileName);');304 Add(' Reset(SourceFile);');305 Add(' Parser := TParser.Create;');306 Add(' Parser.FileName := ExtractFileName(FileName);');307 Add(' SetLength(Parser.Content, FileSize(SourceFile));');308 Add(' I := 1;');309 Add(' while not Eof(SourceFile) do begin');310 Add(' Read(SourceFile, Parser.Content[I]);');311 Add(' Inc(I);');312 Add(' end;');313 Add(' CloseFile(SourceFile);');314 if Assigned(TopRule) then315 Add(' Parser.Parse' + TopRule.Name + ';');316 Add(' Parser.Free;');317 Add('end;');318 Add('');319 Add('begin');320 Add(' if ParamCount > 0 then');321 Add(' Compile(ParamStr(1))');322 Add(' else WriteLn(''File name not specified as parameter.'');');323 Add('end.');324 SaveToFile(FileName);325 end;326 FreeAndNil(ParserFile);327 end;328 329 procedure TGrammer.BuildSource(FileName: string);330 var331 Rule: TRule;332 Item: TRuleItem;333 SourceFile: TStringList;334 TypeSectionStarted: Boolean;335 begin336 SourceFile := TStringList.Create;337 with SourceFile do begin338 Add('unit Source;');339 Add('');340 Add('{$MODE Delphi}');341 Add('');342 Add('interface');343 Add('');344 Add('uses');345 Add(' fgl;');346 Add('');347 TypeSectionStarted := False;348 for Rule in Rules do349 if Rule.CreateSourceNode then begin350 if not TypeSectionStarted then begin351 Add('type');352 TypeSectionStarted := True;353 end;354 Add(' T' + Rule.Name + ' = class;');355 end;356 Add('');357 for Rule in Rules do358 if Rule.CreateSourceNode then begin359 Add(' T' + Rule.Name + ' = class');360 for Item in Rule.Items do begin361 if Item.RuleItemType = ritNonTerminal then362 if Item.Repetitive then363 Add(' ' + Item.NonTerminal.Name + ': TFPGObjectList<T' + Item.NonTerminal.Name + '>;')364 else Add(' ' + Item.NonTerminal.Name + ': T' + Item.NonTerminal.Name + ';');365 end;366 Add(' end;' + LineEnding);367 end;368 Add('');369 Add('implementation');370 Add('');371 372 Add('end.');373 374 SaveToFile(FileName);375 end;376 FreeAndNil(SourceFile);377 143 end; 378 144 … … 449 215 FreeAndNil(Rules); 450 216 inherited Destroy; 451 end;452 453 procedure TGrammer.BuildCompiler;454 var455 OutputDir: string;456 begin457 OutputDir := 'Generated';458 ForceDirectories(OutputDir);459 460 BuildMain(OutputDir + DirectorySeparator + 'Compiler.pas');461 BuildSource(OutputDir + DirectorySeparator + 'Source.pas');462 BuildParser(OutputDir + DirectorySeparator + 'Parser.pas');463 217 end; 464 218 … … 666 420 WriteString(Node, 'Name', Name); 667 421 WriteBoolean(Node, 'CreateSourceNode', CreateSourceNode); 422 WriteInteger(Node, 'Level', Integer(Level)); 668 423 669 424 RuleItemsNode := Node.OwnerDocument.CreateElement('RuleItems'); … … 715 470 Name := ReadString(Node, 'Name', ''); 716 471 CreateSourceNode := ReadBoolean(Node, 'CreateSourceNode', False); 472 Level := TRuleLevel(ReadInteger(Node, 'Level', 0)); 717 473 718 474 ItemsNode := Node.FindNode('RuleItems');
Note:
See TracChangeset
for help on using the changeset viewer.