Ignore:
Timestamp:
Nov 29, 2017, 6:31:25 PM (7 years ago)
Author:
chronos
Message:
  • Added: Generate Parser as separate file.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/generator/URules.pas

    r124 r125  
    111111    FModified: Boolean;
    112112    procedure SetModified(AValue: Boolean);
     113    procedure BuildParser(FileName: string);
    113114    procedure BuildMain(FileName: string);
    114115    procedure BuildSource(FileName: string);
     
    137138end;
    138139
    139 procedure TGrammer.BuildMain(FileName: string);
     140procedure TGrammer.BuildParser(FileName: string);
    140141var
    141142  ParserFile: TStringList;
     143  Rule: TRule;
     144  I: Integer;
     145  Line: string;
     146  Item: TRuleItem;
    142147begin
    143148  ParserFile := TStringList.Create;
    144149  with ParserFile do begin
    145     Add('program Compiler;');
     150    Add('unit Parse;');
    146151    Add('');
    147152    Add('{$MODE Delphi}');
    148153    Add('');
    149     Add('uses');
    150     Add('  Source;');
    151     Add('');
    152     Add('procedure Compile(FileName: string);');
     154    Add('interface');
     155    Add('');
     156    Add('type');
     157    Add('  TParser = class');
     158    Add('    Content: string;');
     159    Add('    Position: Integer;');
     160    Add('    function Expect(Text: string; Required: Boolean = False): Boolean;');
     161    Add('    function ExpectRange(CharFrom, CharTo: Char; Required: Boolean = False): Boolean;');
     162    for Rule in Rules do
     163      Add('    function Parse' + Rule.Name + ': Boolean;');
     164    Add('  end;');
     165    Add('');
     166    Add('implementation');
     167    Add('');
     168    Add('function TParser.Expect(Text: string; Required: Boolean = False): Boolean;');
    153169    Add('var');
    154     Add('  SourceFile: Text;');
     170    Add('  ReadText: string;');
    155171    Add('begin');
    156     Add('  AssignFile(SourceFile, FileName);');
    157     Add('  Reset(SourceFile);');
    158     Add('  SetLength(Content, FileSize(SourceFile));');
    159     Add('  Read(SourceFile, Content);');
    160     if Assigned(TopRule) then
    161       Add('  Parse' + TopRule.Name + ';');
    162     Add('  CloseFile(SourceFile);');
     172    Add('  ReadText := Copy(Content, Position, Length(Text));');
     173    Add('  Inc(Position, Length(Text));');
     174    Add('  Result := Text = ReadText');
     175    Add('  if not Result and Required then Error(''Expected '' + Text + '' but found '' + ReadText + ''.'');');
    163176    Add('end;');
    164177    Add('');
     178    Add('function TParser.ExpectRange(CharFrom, CharTo: char; Required: Boolean = False): Boolean;');
     179    Add('var');
     180    Add('  ReadChar: Char;');
    165181    Add('begin');
    166     Add('  if ParamCount > 1 then');
    167     Add('    Compile(ParamStr(1));');
    168     Add('end.');
    169     SaveToFile(FileName);
    170   end;
    171   FreeAndNil(ParserFile);
    172 end;
    173 
    174 procedure TGrammer.BuildSource(FileName: string);
    175 var
    176   Rule: TRule;
    177   Item: TRuleItem;
    178   Line: string;
    179   I: Integer;
    180   SourceFile: TStringList;
    181 begin
    182   SourceFile := TStringList.Create;
    183   with SourceFile do begin
    184     Add('unit Source;');
    185     Add('');
    186     Add('{$MODE Delphi}');
    187     Add('');
    188     Add('interface');
    189     Add('');
    190     Add('uses');
    191     Add('  fgl;');
    192     Add('');
    193     Add('type');
    194     for Rule in Rules do
    195     if Rule.CreateSourceNode then begin
    196       Add('  T' + Rule.Name + ' = class;');
    197     end;
    198     Add('');
    199     for Rule in Rules do
    200     if Rule.CreateSourceNode then begin
    201       Add('  T' + Rule.Name + ' = class');
    202       for Item in Rule.Items do begin
    203         if Item.RuleItemType = ritNonTerminal then
    204           if Item.Repetitive then
    205           Add('    ' + Item.NonTerminal.Name + ': TFPGObjectList<T' + Item.NonTerminal.Name + '>;')
    206           else Add('    ' + Item.NonTerminal.Name + ': T' + Item.NonTerminal.Name + ';');
    207       end;
    208       Add('  end;' + LineEnding);
    209     end;
    210     Add('');
    211     Add('implementation');
     182    Add('  ReadChar := Content[Position];');
     183    Add('  Inc(Position, 1);');
     184    Add('  Result := (ReadChar >= CharFrom) and (ReadChar <= CharTo);');
     185    Add('  if not Result and Required then Error(''Expected '' + CharFrom + '' to '' + CharTo + '' but found '' + ReadChar + ''.'');');
     186    Add('end;');
    212187    Add('');
    213188    for Rule in Rules do begin
    214       Add('function Parse' + Rule.Name + ': Boolean;');
     189      Add('function TParser.Parse' + Rule.Name + ': Boolean;');
    215190      Add('begin');
    216191      I := 0;
     
    225200        end;
    226201        case Item.RuleItemType of
    227           ritTerminal: Line := Line + 'Expect(''' + Item.Terminal + ''')';
     202          ritTerminal: Line := Line + 'Expect(''' + StringReplace(Item.Terminal, '''', '''''', [rfReplaceAll]) + ''')';
    228203          ritNonTerminal: Line := Line + 'Parse' + Item.NonTerminal.Name;
    229           ritTerminalRange: Line := Line + 'Expect(''' + Item.Terminal + ''')';
     204          ritTerminalRange: Line := Line + 'ExpectRange(''' + Item.TerminalFrom + ''', ''' + Item.TerminalTo + ''')';
     205          //ritSubItems: Line := 'Parse +';
    230206        end;
    231207        if Rule.Items.RuleType = rtOr then begin
     
    244220      Add('');
    245221    end;
     222    Add('');
     223    Add('end.');
     224    SaveToFile(FileName);
     225  end;
     226  FreeAndNil(ParserFile);
     227end;
     228
     229procedure TGrammer.BuildMain(FileName: string);
     230var
     231  ParserFile: TStringList;
     232begin
     233  ParserFile := TStringList.Create;
     234  with ParserFile do begin
     235    Add('program Compiler;');
     236    Add('');
     237    Add('{$MODE Delphi}');
     238    Add('');
     239    Add('uses');
     240    Add('  Source, Parser;');
     241    Add('');
     242    Add('procedure Compile(FileName: string);');
     243    Add('var');
     244    Add('  SourceFile: Text;');
     245    Add('begin');
     246    Add('  AssignFile(SourceFile, FileName);');
     247    Add('  Reset(SourceFile);');
     248    Add('  SetLength(Content, FileSize(SourceFile));');
     249    Add('  Parser := TParser.Create;');
     250    Add('  Read(SourceFile, Parser.Content);');
     251    Add('  CloseFile(SourceFile);');
     252    if Assigned(TopRule) then
     253      Add('  Parser.Parse' + TopRule.Name + ';');
     254    Add('  Parser.Free;');
     255    Add('end;');
     256    Add('');
     257    Add('begin');
     258    Add('  if ParamCount > 1 then');
     259    Add('    Compile(ParamStr(1));');
     260    Add('end.');
     261    SaveToFile(FileName);
     262  end;
     263  FreeAndNil(ParserFile);
     264end;
     265
     266procedure TGrammer.BuildSource(FileName: string);
     267var
     268  Rule: TRule;
     269  Item: TRuleItem;
     270  SourceFile: TStringList;
     271begin
     272  SourceFile := TStringList.Create;
     273  with SourceFile do begin
     274    Add('unit Source;');
     275    Add('');
     276    Add('{$MODE Delphi}');
     277    Add('');
     278    Add('interface');
     279    Add('');
     280    Add('uses');
     281    Add('  fgl;');
     282    Add('');
     283    Add('type');
     284    for Rule in Rules do
     285    if Rule.CreateSourceNode then begin
     286      Add('  T' + Rule.Name + ' = class;');
     287    end;
     288    Add('');
     289    for Rule in Rules do
     290    if Rule.CreateSourceNode then begin
     291      Add('  T' + Rule.Name + ' = class');
     292      for Item in Rule.Items do begin
     293        if Item.RuleItemType = ritNonTerminal then
     294          if Item.Repetitive then
     295          Add('    ' + Item.NonTerminal.Name + ': TFPGObjectList<T' + Item.NonTerminal.Name + '>;')
     296          else Add('    ' + Item.NonTerminal.Name + ': T' + Item.NonTerminal.Name + ';');
     297      end;
     298      Add('  end;' + LineEnding);
     299    end;
     300    Add('');
     301    Add('implementation');
     302    Add('');
    246303
    247304    Add('end.');
     
    258315  RulesNode: TDOMNode;
    259316  Rule: TRule;
    260   TopRuleName: string;
    261317begin
    262318  Self.FileName := FileName;
     
    329385
    330386  BuildMain(OutputDir + DirectorySeparator + 'Compiler.pas');
    331   BuildSource(OutputDir + DirectorySeparator +'Source.pas');
     387  BuildSource(OutputDir + DirectorySeparator + 'Source.pas');
     388  BuildParser(OutputDir + DirectorySeparator + 'Parser.pas');
    332389end;
    333390
Note: See TracChangeset for help on using the changeset viewer.