Ignore:
Timestamp:
Oct 15, 2012, 2:10:48 PM (12 years ago)
Author:
chronos
Message:
  • Upraveno: Překlad rozdělen do fáze zpracování maker a druhé fáze zpracování instrukcí.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/AS8051toC/UCompiler.pas

    r25 r26  
    66
    77uses
    8   Classes, SysUtils;
     8  Classes, SysUtils, UParser, SpecializedList;
    99
    1010type
     11
     12  { TCompilerMacro }
     13
     14  TCompilerMacro = class
     15  private
     16    Output: string;
     17    function ParseString: string;
     18  public
     19    Macros: TStringList;
     20    Parser: TParserASM51;
     21    procedure ParseLine;
     22    function ParseMacro: Boolean;
     23    function ParseMacroUsage: Boolean;
     24    procedure ParseExpression;
     25    procedure ParseIfExpression;
     26    procedure Emit(Text: string);
     27    function ParseComment: Boolean;
     28    constructor Create;
     29    destructor Destroy; override;
     30    function Compile(Source: string): string;
     31  end;
     32
     33  { TCompiler }
     34
    1135  TCompiler = class
    12 
     36  private
     37    Output: string;
     38  public
     39    Parser: TParserASM51;
     40    Symbols: TListObject;
     41    procedure Emit(Text: string);
     42    function IsHexNumber(Text: string): Boolean;
     43    function CheckIdentificator: Boolean;
     44    function CheckInstructionParameter: Boolean;
     45    function ParseComment: Boolean;
     46    procedure ParseDbExpression;
     47    function ParseInstruction: Boolean;
     48    function ParseKeywords: Boolean;
     49    procedure ParseLine;
     50    function ParseString: string;
     51    function Compile(Source: string): string;
     52    constructor Create;
     53    destructor Destroy; override;
    1354  end;
    1455
    1556implementation
    1657
     58{ TCompilerMacro }
     59
     60procedure TCompilerMacro.ParseLine;
     61begin
     62  with Parser do begin
     63    if GetNext = '%' then begin
     64      if ParseComment then
     65      if ParseMacroUsage then Emit(ReadNext)
     66      else if ParseMacro then Emit(ReadNext)
     67      else ;
     68    end else begin
     69      Output := Output + ReadNext;
     70    end;
     71  end;
     72end;
     73
     74procedure TCompilerMacro.ParseExpression;
     75begin
     76  with Parser do begin
     77
     78    if ParseMacroUsage then
     79    else if GetNext = '$' then begin
     80      Expect('$');
     81      Emit('$');
     82    end
     83    else if GetNext = '(' then begin
     84      Expect('(');
     85      Emit('(');
     86      ParseExpression;
     87      Expect(')');
     88      Emit(')');
     89    end
     90    else if GetNext = '''' then Emit('"' + ParseString + '"')
     91    else Error('Unknown IF parameter "' + GetNext + '"');
     92
     93    if GetNext = '+' then begin
     94      Expect('+');
     95      Emit('+');
     96      ParseExpression;
     97    end else
     98    if GetNext = '-' then begin
     99      Expect('-');
     100      Emit('-');
     101      ParseExpression;
     102    end else
     103    if GetNext = '*' then begin
     104      Expect('*');
     105      Emit('*');
     106      ParseExpression;
     107    end else
     108    if GetNext = '/' then begin
     109      Expect('/');
     110      Emit('/');
     111      ParseExpression;
     112    end else
     113    if GetNext = 'shl' then begin
     114      Expect('shl');
     115      Emit('<< ');
     116      ParseExpression;
     117    end else
     118    if GetNext = 'shr' then begin
     119      Expect('shr');
     120      Emit('>> ');
     121      ParseExpression;
     122    end else
     123    if GetNext = 'or' then begin
     124      Expect('or');
     125      Emit('|| ');
     126      ParseExpression;
     127    end else
     128    if GetNext = 'and' then begin
     129      Expect('and');
     130      Emit('&& ');
     131      ParseExpression;
     132    end;
     133  end;
     134end;
     135
     136procedure TCompilerMacro.Emit(Text: string);
     137begin
     138  Output := Output + Text;
     139end;
     140
     141function TCompilerMacro.ParseComment: Boolean;
     142begin
     143  with Parser do begin
     144    if GetNext = ';' then begin
     145      Result := True;
     146      Expect(';');
     147      Emit('//');
     148      Emit(ReadEol);
     149    end else Result := False;
     150  end;
     151end;
     152
     153constructor TCompilerMacro.Create;
     154begin
     155  Macros := TStringList.Create;
     156  Parser := TParserASM51.Create;
     157end;
     158
     159destructor TCompilerMacro.Destroy;
     160begin
     161  FreeAndNil(Parser);
     162  FreeAndNil(Macros);
     163  inherited Destroy;
     164end;
     165
     166function TCompilerMacro.ParseString: string;
     167begin
     168  with Parser do begin
     169    Result := '';
     170    Expect('''');
     171    while GetNext <> '''' do begin
     172      Result := Result + ReadNext;
     173    end;
     174    Expect('''');
     175  end;
     176end;
     177
     178function TCompilerMacro.Compile(Source: string): string;
     179var
     180  OldPos: Integer;
     181begin
     182  Output := '';
     183  Parser.Position := 1;
     184  Parser.Source := Source;
     185  while not Parser.Eof do begin
     186    OldPos := Parser.Position;
     187    ParseLine;
     188    if Parser.GetNext = 'end' then Break;
     189    if OldPos = Parser.Position then Break;
     190  end;
     191  Result := Output;
     192end;
     193
     194{ TCompiler }
     195
     196function TCompiler.Compile(Source: string): string;
     197begin
     198  Output := '';
     199  Parser.Position := 1;
     200  Parser.Source := Source;
     201  while not Parser.Eof do begin
     202    ParseLine;
     203    if Parser.GetNext = 'end' then Break;
     204  end;
     205  Result := Output;
     206end;
     207
     208constructor TCompiler.Create;
     209begin
     210  Parser := TParserASM51.Create;
     211  Symbols := TListObject.Create;
     212end;
     213
     214destructor TCompiler.Destroy;
     215begin
     216  FreeAndNil(Symbols);
     217  FreeAndNil(Parser);
     218  inherited;
     219end;
     220
     221procedure TCompiler.ParseLine;
     222var
     223  Part: string;
     224  OutLine: string;
     225  Instruction: string;
     226  Macro: string;
     227  Variable: string;
     228begin
     229  with Parser do begin
     230    if GetNext = '$' then begin
     231      Expect('$');
     232      if GetNext = 'include' then begin
     233        Expect('include');
     234        Expect('(');
     235        Emit('#include ''');
     236        Emit(ReadNext);
     237        Expect('.');
     238        Emit('.');
     239        Emit(ReadNext);
     240        Emit('''');
     241        Expect(')');
     242      end else Error('Unknown token "' + GetNext + '"');
     243    end
     244    else if GetNext = ')' then begin
     245      Expect(')');
     246      if GetNext = 'else' then begin
     247        Expect('else');
     248        Emit('#else ');
     249        Expect('(');
     250      end else
     251      if GetNext = 'fi' then begin
     252        Expect('fi');
     253        Emit('#endif ');
     254      end; // else Error('Unknown token "' + GetNext + '"');
     255    end
     256    else if ParseComment then
     257    else if ParseKeywords then
     258    else if ParseInstruction then
     259    else if IsIdentificator(GetNext) then CheckIdentificator
     260    else Error('Unexpected token "' + GetNext + '"');
     261    Emit(LineEnding);
     262  end;
     263end;
     264
     265function TCompilerMacro.ParseMacro: Boolean;
     266var
     267  MacroName: string;
     268  OldPos: Integer;
     269begin
     270  with Parser do begin
     271    OldPos := Position;
     272    if GetNext = '%' then begin
     273      Result := True;
     274      Expect('%');
     275      if GetNext = 'define' then begin
     276        Expect('define');
     277        Emit('#define ');
     278        Expect('(');
     279        MacroName := ReadNext;
     280        Emit(MacroName);
     281        Expect(')');
     282        Emit(' ');
     283        Expect('(');
     284        while GetNext <> ')' do begin
     285          Emit(ReadNext);
     286        end;
     287        Expect(')');
     288        Emit(';');
     289      end else
     290      if GetNext = 'if' then begin
     291        Expect('if');
     292        Emit('#if ');
     293        Expect('(');
     294        ParseIfExpression;
     295        Expect(')');
     296        Expect('then');
     297        Expect('(');
     298      end else
     299      if GetNext = 'set' then begin
     300        Expect('set');
     301        Emit('#define ');
     302        Expect('(');
     303        Emit(ReadNext + ' ');
     304        Expect(',');
     305        ParseExpression;
     306        Expect(')');
     307        Emit(';');
     308      end else
     309      if GetNext = '*' then begin
     310        Expect('*');
     311        if GetNext = 'define' then begin
     312          Expect('define');
     313          Emit('#define ');
     314          Expect('(');
     315          Emit(ReadNext);
     316          Expect('(');
     317          Emit('(' + ReadNext);
     318          while GetNext = ',' do begin
     319            Expect(',');
     320            Emit(', ' + ReadNext);
     321          end;
     322          Expect(')');
     323          Emit(')');
     324          Expect(')');
     325          if GetNext = 'local' then begin
     326            Expect('local');
     327            ReadNext;
     328          end;
     329          Expect('(');
     330        end;
     331      end else begin
     332        Position := OldPos;
     333        Result := False;
     334      end;
     335    end else Result := False;
     336  end;
     337end;
     338
     339procedure TCompiler.Emit(Text: string);
     340begin
     341  Output := Output + Text;
     342end;
     343
     344function TCompiler.ParseComment: Boolean;
     345begin
     346  with Parser do begin
     347    if GetNext = ';' then begin
     348      Result := True;
     349      Expect(';');
     350      Emit('//');
     351      Emit(ReadEol);
     352    end else Result := False;
     353  end;
     354end;
     355
     356function TCompilerMacro.ParseMacroUsage: Boolean;
     357var
     358  MacroName: string;
     359begin
     360  with Parser do begin
     361    if GetNext = '%' then begin
     362      Result := True;
     363      Expect('%');
     364      MacroName := ReadNext;
     365      Emit(MacroName);
     366      if GetNext = '(' then begin
     367        Expect('(');
     368        Emit('(');
     369        ParseExpression;
     370        //else Emit(ReadNext);
     371        while GetNext = ',' do begin
     372          Expect(',');
     373          Emit(',');
     374          ParseExpression;
     375          //if ParseMacroUsage then
     376          //else if GetNext <> ')' then Emit(ReadNext);
     377        end;
     378        Emit(')');
     379        Expect(')');
     380      end;
     381    end else Result := False;
     382  end;
     383end;
     384
     385function TCompiler.ParseKeywords: Boolean;
     386var
     387  Value: string;
     388begin
     389  with Parser do begin
     390    if GetNext = 'extrn' then begin
     391      Expect('extrn');
     392      Result := True;
     393      ReadNext;
     394      Expect('(');
     395      ReadNext;
     396      while GetNext = ',' do begin
     397        Expect(',');
     398        ReadNext;
     399      end;
     400      Expect(')');
     401    end else
     402    if GetNext = 'public' then begin
     403      Result := True;
     404      Expect('public');
     405      ReadNext;
     406      while GetNext = ',' do begin
     407        Expect(',');
     408        ReadNext;
     409      end;
     410    end else
     411    if GetNext = 'using' then begin
     412      Result := True;
     413      Expect('using');
     414      Value := ReadNext;
     415      Emit('// using reg bank ' + Value);
     416    end else
     417    if GetNext = 'cseg' then begin
     418      Result := True;
     419      Expect('cseg');
     420      Expect('at');
     421      Value := ReadNext;
     422      if GetNext = 'h' then begin
     423        Expect('h');
     424        //Emit('0x' + Value);
     425      end; // else Emit(Value);
     426    end else
     427    if GetNext = 'rseg' then begin
     428      Result := True;
     429      Expect('rseg');
     430      Value := ReadNext;
     431      if GetNext = 'h' then begin
     432        Expect('h');
     433        //Emit('0x' + Value);
     434      end; // else Emit(Value);
     435    end else
     436    if GetNext = 'dbit' then begin
     437      Result := True;
     438      Expect('dbit');
     439      Emit('char ');
     440      Emit(ReadNext);
     441    end else
     442    if GetNext = 'db' then begin
     443      Result := True;
     444      Expect('db');
     445      Emit('char ');
     446      ParseDbExpression;
     447      while GetNext = ',' do begin
     448        Expect(',');
     449        Emit(',');
     450        ParseDbExpression;
     451      end;
     452    end else
     453    if GetNext = 'dw' then begin
     454      Result := True;
     455      Expect('dw');
     456      Emit('char ');
     457      ParseDbExpression;
     458      while GetNext = ',' do begin
     459        Expect(',');
     460        Emit(',');
     461        ParseDbExpression;
     462      end;
     463    end else
     464    if GetNext = 'ds' then begin
     465      Result := True;
     466      Expect('ds');
     467      Emit('char* ');
     468      ParseDbExpression;
     469      while GetNext = ',' do begin
     470        Expect(',');
     471        Emit(',');
     472        ParseDbExpression;
     473      end;
     474    end else Result := False;
     475  end;
     476end;
     477
     478function TCompiler.ParseInstruction: Boolean;
     479begin
     480  with Parser do begin
     481    if GetNext = 'jmp' then begin
     482      Expect('jmp');
     483      Result := True;
     484      Emit('goto ');
     485      Emit(ReadNext);
     486      Emit(';');
     487    end else
     488    if GetNext = 'mov' then begin
     489      Expect('mov');
     490      Result := True;
     491      Emit('MOV(');
     492      ParseDbExpression;
     493      Expect(',');
     494      Emit(',');
     495      ParseDbExpression;
     496      Emit(');');
     497    end else
     498    if GetNext = 'reti' then begin
     499      Result := True;
     500      Expect('reti');
     501    end else Result := False;
     502  end;
     503end;
     504
     505procedure TCompilerMAcro.ParseIfExpression;
     506begin
     507  with Parser do begin
     508    if ParseMacroUsage then
     509    else if IsNumber(GetNext) then Emit(ReadNext)
     510    else Error('Unknown IF parameter "' + GetNext + '"');
     511    if GetNext <> ')' then begin
     512      if GetNext = 'eq' then begin
     513        Expect('eq');
     514        Emit('= ');
     515      end else
     516      if GetNext = 'ne' then begin
     517        Expect('ne');
     518        Emit('!= ');
     519      end else
     520      if GetNext = 'gt' then begin
     521        Expect('gt');
     522        Emit('> ');
     523      end else
     524      if GetNext = 'ge' then begin
     525        Expect('ge');
     526        Emit('>= ');
     527      end else
     528      if GetNext = 'lt' then begin
     529        Expect('lt');
     530        Emit('< ');
     531      end else
     532      if GetNext = 'le' then begin
     533        Expect('le');
     534        Emit('<= ');
     535      end else
     536      if GetNext = 'or' then begin
     537        Expect('or');
     538        Emit('|| ');
     539      end else
     540      if GetNext = 'and' then begin
     541        Expect('and');
     542        Emit('&& ');
     543      end else
     544        Error('Unknown operand "' + ReadNext + '"');
     545      if ParseMacroUsage then
     546      else if IsNumber(GetNext) then Emit(ReadNext)
     547      else Error('Unknown IF parameter "' + GetNext + '"');
     548    end;
     549  end;
     550end;
     551
     552procedure TCompiler.ParseDbExpression;
     553begin
     554  with Parser do begin
     555
     556    if GetNext = '$' then begin
     557      Expect('$');
     558      Emit('$');
     559    end
     560    else if GetNext = '(' then begin
     561      Expect('(');
     562      Emit('(');
     563      ParseDbExpression;
     564      Expect(')');
     565      Emit(')');
     566    end
     567    else if GetNext = '''' then Emit('"' + ParseString + '"')
     568    else if CheckInstructionParameter then
     569    else if IsIdentificator(GetNext) then begin
     570      Emit(ReadNext);
     571    end else Error('Unknown IF parameter "' + GetNext + '"');
     572
     573    if GetNext = '+' then begin
     574      Expect('+');
     575      Emit('+');
     576      ParseDbExpression;
     577    end else
     578    if GetNext = '-' then begin
     579      Expect('-');
     580      Emit('-');
     581      ParseDbExpression;
     582    end else
     583    if GetNext = '*' then begin
     584      Expect('*');
     585      Emit('*');
     586      ParseDbExpression;
     587    end else
     588    if GetNext = '/' then begin
     589      Expect('/');
     590      Emit('/');
     591      ParseDbExpression;
     592    end else
     593    if GetNext = 'shl' then begin
     594      Expect('shl');
     595      Emit('<< ');
     596      ParseDbExpression;
     597    end else
     598    if GetNext = 'shr' then begin
     599      Expect('shr');
     600      Emit('>> ');
     601      ParseDbExpression;
     602    end else
     603    if GetNext = 'or' then begin
     604      Expect('or');
     605      Emit('|| ');
     606      ParseDbExpression;
     607    end else
     608    if GetNext = 'and' then begin
     609      Expect('and');
     610      Emit('&& ');
     611      ParseDbExpression;
     612    end;
     613  end;
     614end;
     615
     616function TCompiler.ParseString: string;
     617begin
     618  with Parser do begin
     619    Result := '';
     620    Expect('''');
     621    while GetNext <> '''' do begin
     622      Result := Result + ReadNext;
     623    end;
     624    Expect('''');
     625  end;
     626end;
     627
     628function TCompiler.IsHexNumber(Text: string): Boolean;
     629begin
     630  Result := (LowerCase(Copy(Text, Length(Text), 1)) = 'h') and
     631    (Parser.IsHexNumber(Copy(Text, 1, Length(Text) - 1)));
     632end;
     633
     634function TCompiler.CheckInstructionParameter: Boolean;
     635var
     636  Text: string;
     637begin
     638  Text := Parser.GetNext;
     639  Result := False;
     640  if Parser.IsNumber(Text) then Result := True
     641  else if Text = '#' then begin
     642    Result := True;
     643    Parser.Expect('#');
     644    if IsHexNumber(Parser.GetNext) then Emit(Parser.ReadNext)
     645    else if Parser.IsNumber(Parser.GetNext) then Emit(Parser.ReadNext)
     646    else Parser.Error('Invalid parameter');
     647  end
     648  else if Copy(Text, 1, 1) = '@' then begin
     649    if IsHexNumber(Copy(Text, 2, Length(Text))) then Result := True;
     650    Emit(Parser.ReadNext);
     651  end;
     652end;
     653
     654function TCompiler.CheckIdentificator: Boolean;
     655var
     656  Variable: string;
     657begin
     658  with Parser do begin
     659        Variable := ReadNext;
     660        if GetNext = '%' then begin
     661          Expect('%');
     662          Variable := Variable + '##' + ReadNext;
     663        end;
     664        if GetNext = ':' then begin
     665          Expect(':');
     666          Emit(Variable + ':');
     667        end else
     668        if GetNext = 'equ' then begin
     669          Expect('equ');
     670          Emit('#define ' + Variable + ' ');
     671          ParseDbExpression;
     672          Emit(';');
     673        end else
     674        if GetNext = 'segment' then begin
     675          Expect('segment');
     676          ReadNext;
     677        end else Error('Unexpected token "' + Variable + '"');
     678  end;
     679end;
     680
     681
    17682end.
    18683
Note: See TracChangeset for help on using the changeset viewer.