Changeset 125 for branches


Ignore:
Timestamp:
Nov 29, 2017, 6:31:25 PM (7 years ago)
Author:
chronos
Message:
  • Added: Generate Parser as separate file.
Location:
branches/generator
Files:
2 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
  • branches/generator/pascal.grm

    r124 r125  
    283283        </RuleItem>
    284284        <RuleItem>
     285          <Type>1</Type>
     286          <Optional>-1</Optional>
     287          <Repetitive>-1</Repetitive>
     288          <AnyExcept>0</AnyExcept>
     289          <NonTerminal>CaseOfState</NonTerminal>
     290        </RuleItem>
     291        <RuleItem>
     292          <Type>2</Type>
     293          <Optional>-1</Optional>
     294          <Repetitive>0</Repetitive>
     295          <AnyExcept>0</AnyExcept>
     296          <SubItems>
     297            <Type>0</Type>
     298            <RuleItem>
     299              <Type>0</Type>
     300              <Optional>0</Optional>
     301              <Repetitive>0</Repetitive>
     302              <AnyExcept>0</AnyExcept>
     303              <Terminal>else</Terminal>
     304            </RuleItem>
     305            <RuleItem>
     306              <Type>1</Type>
     307              <Optional>0</Optional>
     308              <Repetitive>0</Repetitive>
     309              <AnyExcept>0</AnyExcept>
     310              <NonTerminal>Statement</NonTerminal>
     311            </RuleItem>
     312            <RuleItem>
     313              <Type>0</Type>
     314              <Optional>0</Optional>
     315              <Repetitive>0</Repetitive>
     316              <AnyExcept>0</AnyExcept>
     317              <Terminal>;</Terminal>
     318            </RuleItem>
     319          </SubItems>
     320        </RuleItem>
     321        <RuleItem>
    285322          <Type>0</Type>
    286323          <Optional>0</Optional>
     
    14721509          <AnyExcept>0</AnyExcept>
    14731510          <Terminal>-</Terminal>
     1511        </RuleItem>
     1512        <RuleItem>
     1513          <Type>0</Type>
     1514          <Optional>0</Optional>
     1515          <Repetitive>0</Repetitive>
     1516          <AnyExcept>0</AnyExcept>
     1517          <Terminal>and</Terminal>
     1518        </RuleItem>
     1519        <RuleItem>
     1520          <Type>0</Type>
     1521          <Optional>0</Optional>
     1522          <Repetitive>0</Repetitive>
     1523          <AnyExcept>0</AnyExcept>
     1524          <Terminal>or</Terminal>
     1525        </RuleItem>
     1526        <RuleItem>
     1527          <Type>0</Type>
     1528          <Optional>0</Optional>
     1529          <Repetitive>0</Repetitive>
     1530          <AnyExcept>0</AnyExcept>
     1531          <Terminal>xor</Terminal>
     1532        </RuleItem>
     1533        <RuleItem>
     1534          <Type>0</Type>
     1535          <Optional>0</Optional>
     1536          <Repetitive>0</Repetitive>
     1537          <AnyExcept>0</AnyExcept>
     1538          <Terminal>shl</Terminal>
     1539        </RuleItem>
     1540        <RuleItem>
     1541          <Type>0</Type>
     1542          <Optional>0</Optional>
     1543          <Repetitive>0</Repetitive>
     1544          <AnyExcept>0</AnyExcept>
     1545          <Terminal>shr</Terminal>
     1546        </RuleItem>
     1547        <RuleItem>
     1548          <Type>0</Type>
     1549          <Optional>0</Optional>
     1550          <Repetitive>0</Repetitive>
     1551          <AnyExcept>0</AnyExcept>
     1552          <Terminal>in</Terminal>
     1553        </RuleItem>
     1554        <RuleItem>
     1555          <Type>0</Type>
     1556          <Optional>0</Optional>
     1557          <Repetitive>0</Repetitive>
     1558          <AnyExcept>0</AnyExcept>
     1559          <Terminal>as</Terminal>
    14741560        </RuleItem>
    14751561      </RuleItems>
     
    18321918      </RuleItems>
    18331919    </Rule>
     1920    <Rule>
     1921      <Name>CaseOfState</Name>
     1922      <CreateSourceNode>0</CreateSourceNode>
     1923      <RuleItems>
     1924        <Type>0</Type>
     1925        <RuleItem>
     1926          <Type>1</Type>
     1927          <Optional>0</Optional>
     1928          <Repetitive>0</Repetitive>
     1929          <AnyExcept>0</AnyExcept>
     1930          <NonTerminal>Identifier</NonTerminal>
     1931        </RuleItem>
     1932        <RuleItem>
     1933          <Type>0</Type>
     1934          <Optional>0</Optional>
     1935          <Repetitive>0</Repetitive>
     1936          <AnyExcept>0</AnyExcept>
     1937          <Terminal>:</Terminal>
     1938        </RuleItem>
     1939        <RuleItem>
     1940          <Type>1</Type>
     1941          <Optional>0</Optional>
     1942          <Repetitive>0</Repetitive>
     1943          <AnyExcept>0</AnyExcept>
     1944          <NonTerminal>Statement</NonTerminal>
     1945        </RuleItem>
     1946        <RuleItem>
     1947          <Type>0</Type>
     1948          <Optional>0</Optional>
     1949          <Repetitive>0</Repetitive>
     1950          <AnyExcept>0</AnyExcept>
     1951          <Terminal>;</Terminal>
     1952        </RuleItem>
     1953      </RuleItems>
     1954    </Rule>
    18341955  </Rules>
    18351956  <TopRule>Program</TopRule>
Note: See TracChangeset for help on using the changeset viewer.