Ignore:
Timestamp:
Nov 30, 2017, 5:19:57 PM (7 years ago)
Author:
chronos
Message:
  • Fixed: Correctly set filename in open/save dialog.
  • Modified: Improved generation of compiler code.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/generator/URules.pas

    r126 r127  
    110110  private
    111111    FModified: Boolean;
     112    function GetItemString(Item: TRuleItem; Required: Boolean): string;
    112113    procedure SetModified(AValue: Boolean);
    113114    procedure BuildParser(FileName: string);
     
    131132implementation
    132133
     134const
     135  BooleanText: array[Boolean] of string = ('False', 'True');
     136
    133137{ TGrammer }
     138
     139function TGrammer.GetItemString(Item: TRuleItem; Required: Boolean): string;
     140begin
     141  Result := '';
     142  case Item.RuleItemType of
     143    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;
     151end;
    134152
    135153procedure TGrammer.SetModified(AValue: Boolean);
     
    146164  Line: string;
    147165  Item: TRuleItem;
     166  Required: Boolean;
    148167begin
    149168  ParserFile := TStringList.Create;
     
    155174    Add('interface');
    156175    Add('');
     176    Add('uses');
     177    Add('  SysUtils;');
     178    Add('');
    157179    Add('type');
    158180    Add('  TParser = class');
    159181    Add('    Content: string;');
     182    Add('    FileName: string;');
    160183    Add('    Position: Integer;');
    161184    Add('    procedure Error(Text: string);');
     
    163186    Add('    function ExpectRange(CharFrom, CharTo: Char; Required: Boolean = False): Boolean;');
    164187    for Rule in Rules do
    165       Add('    function Parse' + Rule.Name + ': Boolean;');
     188      Add('    function Parse' + Rule.Name + '(Required: Boolean = False): Boolean;');
    166189    Add('    constructor Create;');
    167190    Add('  end;');
     
    176199    Add('procedure TParser.Error(Text: string);');
    177200    Add('begin');
    178     Add('  WriteLn(''Error: '' + Text);');
     201    Add('  WriteLn(FileName + ''('' + IntToStr(Position) + '') Error: '' + Text);');
    179202    Add('end;');
    180203    Add('');
     
    182205    Add('var');
    183206    Add('  ReadText: string;');
     207    Add('  StartPos: Integer;');
    184208    Add('begin');
     209    Add('  StartPos := Position;');
    185210    Add('  ReadText := Copy(Content, Position, Length(Text));');
    186211    Add('  Inc(Position, Length(Text));');
    187212    Add('  Result := Text = ReadText;');
    188     Add('  if not Result and Required then Error(''Expected '' + Text + '' but found '' + 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;');
    189217    Add('end;');
    190218    Add('');
     
    192220    Add('var');
    193221    Add('  ReadChar: Char;');
     222    Add('  StartPos: Integer;');
    194223    Add('begin');
     224    Add('  StartPos := Position;');
    195225    Add('  ReadChar := Content[Position];');
    196226    Add('  Inc(Position, 1);');
    197227    Add('  Result := (ReadChar >= CharFrom) and (ReadChar <= CharTo);');
    198     Add('  if not Result and Required then Error(''Expected '' + CharFrom + '' to '' + CharTo + '' but found '' + ReadChar + ''.'');');
     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;');
    199232    Add('end;');
    200233    Add('');
    201234    for Rule in Rules do begin
    202       Add('function TParser.Parse' + Rule.Name + ': Boolean;');
     235      Add('function TParser.Parse' + Rule.Name + '(Required: Boolean = False): Boolean;');
    203236      Add('begin');
     237      Add('  Result := True;');
    204238      I := 0;
    205239      for Item in Rule.Items do begin
     240        Required := not Item.Optional;
    206241        Line := '  ';
    207         if Rule.Items.RuleType = rtOr then begin
    208           if I > 0 then Line := Line + 'else ';
    209           Line := Line + 'if ';
    210         end else
    211         if Rule.Items.RuleType = rtAnd then begin
    212           Line := Line + '';
    213         end;
    214         case Item.RuleItemType of
    215           ritTerminal: Line := Line + 'Expect(''' + StringReplace(Item.Terminal, '''', '''''', [rfReplaceAll]) + ''')';
    216           ritNonTerminal: Line := Line + 'Parse' + Item.NonTerminal.Name;
    217           ritTerminalRange: Line := Line + 'ExpectRange(''' + Item.TerminalFrom + ''', ''' + Item.TerminalTo + ''')';
    218           //ritSubItems: Line := 'Parse +';
    219         end;
    220         if Rule.Items.RuleType = rtOr then begin
    221           Line := Line + ' then ';
    222         end else
    223         if Rule.Items.RuleType = rtAnd then begin
    224           Line := Line + ';';
     242        case Rule.Items.RuleType of
     243          rtOr: begin
     244            if I > 0 then Line := Line + 'else ';
     245            Line := Line + 'if ' + GetItemString(Item, False);
     246            Line := Line + ' then Exit';
     247          end;
     248          rtAnd: begin
     249            Line := Line + 'Result := Result and ';
     250            if Item.Optional then Line := Line + 'True;' + LineEnding;
     251            if Item.Repetitive then begin
     252              if not Item.Optional then
     253                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;
    225261        end;
    226262        Add(Line);
    227263        Inc(I);
    228264      end;
    229       if Rule.Items.RuleType = rtOr then begin
    230         Add('  else ShowError(''Unexpected token'');');
     265      case Rule.Items.RuleType of
     266        rtOr: begin
     267          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('''')');
    231273      end;
    232274      Add('end;');
     
    251293    Add('');
    252294    Add('uses');
    253     Add('  Source, Parser;');
     295    Add('  Source, Parser, SysUtils;');
    254296    Add('');
    255297    Add('procedure Compile(FileName: string);');
     
    262304    Add('  Reset(SourceFile);');
    263305    Add('  Parser := TParser.Create;');
     306    Add('  Parser.FileName := ExtractFileName(FileName);');
    264307    Add('  SetLength(Parser.Content, FileSize(SourceFile));');
    265308    Add('  I := 1;');
Note: See TracChangeset for help on using the changeset viewer.