Changeset 146


Ignore:
Timestamp:
Jan 17, 2018, 2:25:45 PM (6 years ago)
Author:
chronos
Message:
  • Modified: ParseBeginEnd method split to several other items for parsing each specific command.
Location:
branches/easy compiler
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/easy compiler/UCompiler.pas

    r145 r146  
    3333    function IsKeyword(Text: string): Boolean;
    3434    function GetNext(Kind: TSourceTokenKind = stNone): TSourceToken;
     35    function CheckNext(Text: string; Kind: TSourceTokenKind): Boolean;
    3536    procedure Tokenize(Text: string; Tokens: TSourceTokens);
    3637  end;
     
    4243    Tokenizer: TTokenizer;
    4344    procedure Parse(Code: TSourceCode);
    44     procedure ParseBeginEnd(BeginEnd: TSourceBeginEnd);
     45    function ParseBeginEnd(SourceCode: TSourceCode; out BeginEnd: TCommandBeginEnd): Boolean;
     46    function ParseFunctionCall(SourceCode: TSourceCode; out FunctionCall: TCommandFunctionCall): Boolean;
     47    function ParseIfZero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean;
     48    function ParseReference(SourceCode: TSourceCode): TSourceReference;
     49    function ParseReferenceVariable(SourceCode: TSourceCode): TSourceReference;
     50    function ParseVar(SourceCode: TSourceCode): Boolean;
    4551  public
    4652    procedure Compile(Source: string; SourceCode: TSourceCode);
     
    99105  if (Kind <> stNone) and (Result.Kind <> Kind) then
    100106    raise Exception.Create('Unexpected token type');
     107end;
     108
     109function TTokenizer.CheckNext(Text: string; Kind: TSourceTokenKind): Boolean;
     110var
     111  Index: Integer;
     112  Token: TSourceToken;
     113begin
     114  Index := TokenIndex;
     115  Token := GetNext;
     116  Result := (LowerCase(Token.Text) = Text) and (Token.Kind = Kind);
     117  TokenIndex := Index;
    101118end;
    102119
     
    172189begin
    173190  Tokenizer.TokenIndex := 0;
    174   ParseBeginEnd(Code.Main);
    175 end;
    176 
    177 procedure TCompiler.ParseBeginEnd(BeginEnd: TSourceBeginEnd);
     191  ParseBeginEnd(Code, Code.Main);
     192end;
     193
     194function TCompiler.ParseVar(SourceCode: TSourceCode): Boolean;
    178195var
    179196  Token: TSourceToken;
    180197  Token2: TSourceToken;
    181   Keyword: string;
    182   Instruction: TSourceInstruction;
    183   NewReference: TSourceReference;
    184   Funct: TSourceFunction;
    185   Param: TSourceFunctionParameter;
    186198  Variable: TSourceVariable;
    187199  ValueType: TSourceType;
    188 
    189 function ParseReference: TSourceReference;
     200  TokenIndex: Integer;
     201begin
     202  Result := False;
     203  TokenIndex := Tokenizer.TokenIndex;
     204  Token := Tokenizer.GetNext;
     205  if LowerCase(Token.Text) = 'var' then begin
     206    Token := Tokenizer.GetNext;
     207    Token2 := Tokenizer.GetNext;
     208    if Token2.Kind <> stIdentifier then
     209      raise Exception.Create('Expected type parameter');
     210    Variable := SourceCode.Variables.Search(Token.Text);
     211    if not Assigned(Variable) then begin
     212      ValueType := SourceCode.Types.Search(Token2.Text);
     213      if not Assigned(ValueType) then
     214        raise Exception.Create('Unsupported type: ' + Token2.Text);
     215      Variable := SourceCode.Variables.AddNew(Token.Text,
     216        ValueType);
     217    end else raise Exception.Create('Variable redefined: ' + Token.Text);
     218    Result := True;
     219  end;
     220  if not Result then Tokenizer.TokenIndex := TokenIndex;
     221end;
     222
     223function TCompiler.ParseReference(SourceCode: TSourceCode): TSourceReference;
     224var
     225  Token: TSourceToken;
     226  NewReference: TSourceReference;
    190227begin
    191228  Token := Tokenizer.GetNext;
     
    193230    NewReference := TSourceReferenceConstant.Create;
    194231    TSourceReferenceConstant(NewReference).Constant :=
    195       BeginEnd.SourceCode.Constants.AddNewString(Token.Text);
     232      SourceCode.Constants.AddNewString(Token.Text);
    196233  end else
    197234  if Token.Kind = stIdentifier then begin
    198235    NewReference := TSourceReferenceVariable.Create;
    199236    TSourceReferenceVariable(NewReference).Variable :=
    200       BeginEnd.SourceCode.Variables.Search(Token.Text);
     237      SourceCode.Variables.Search(Token.Text);
    201238    if TSourceReferenceVariable(NewReference).Variable = nil then
    202239      raise Exception.Create('Variable not found: ' + Token.Text);
     
    205242    NewReference := TSourceReferenceConstant.Create;
    206243    TSourceReferenceConstant(NewReference).Constant :=
    207       BeginEnd.SourceCode.Constants.AddNewInteger(StrToInt(Token.Text));
     244      SourceCode.Constants.AddNewInteger(StrToInt(Token.Text));
    208245  end else
    209246  raise Exception.Create('Unexpected parameter');
     
    211248end;
    212249
    213 function ParseReferenceVariable(Initialize: Boolean = False): TSourceReference;
     250function TCompiler.ParseReferenceVariable(SourceCode: TSourceCode): TSourceReference;
     251var
     252  Token: TSourceToken;
     253  NewReference: TSourceReference;
    214254begin
    215255  Token := Tokenizer.GetNext;
     
    217257    NewReference := TSourceReferenceVariable.Create;
    218258    TSourceReferenceVariable(NewReference).Variable :=
    219       BeginEnd.SourceCode.Variables.Search(Token.Text);
     259      SourceCode.Variables.Search(Token.Text);
    220260    if TSourceReferenceVariable(NewReference).Variable = nil then
    221261      raise Exception.Create('Variable not found: ' + Token.Text);
     
    225265end;
    226266
    227 begin
    228   while True do begin
     267function TCompiler.ParseFunctionCall(SourceCode: TSourceCode; out FunctionCall: TCommandFunctionCall): Boolean;
     268var
     269  Funct: TSourceFunction;
     270  Param: TSourceFunctionParameter;
     271  Token: TSourceToken;
     272  TokenIndex: Integer;
     273  Keyword: string;
     274begin
     275  Result := False;
     276  TokenIndex := Tokenizer.TokenIndex;
     277  Token := Tokenizer.GetNext;
     278  Keyword := LowerCase(Token.Text);
     279  Funct := SourceCode.Functions.Search(Keyword);
     280  if Assigned(Funct) then begin
     281    FunctionCall := TCommandFunctionCall.Create;
     282    FunctionCall.Name := Keyword;
     283    for Param in Funct.Parameters do
     284    if Param.Kind = pkString then begin
     285      FunctionCall.Parameters.Add(ParseReference(SourceCode))
     286    end else
     287    if Param.Kind = pkVariable then begin
     288      FunctionCall.Parameters.Add(ParseReferenceVariable(SourceCode));
     289    end else
     290    raise Exception.Create('Unsupported parameter type.');
     291    Result := True;
     292  end;
     293  if not Result then Tokenizer.TokenIndex := TokenIndex;
     294end;
     295
     296function TCompiler.ParseIfZero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean;
     297var
     298  Token: TSourceToken;
     299  TokenIndex: Integer;
     300  Keyword: string;
     301begin
     302  Result := False;
     303  TokenIndex := Tokenizer.TokenIndex;
     304  Token := Tokenizer.GetNext;
     305  Keyword := LowerCase(Token.Text);
     306  if Keyword = 'ifzero' then begin
     307    IfZero := TCommandIfZero.Create;
     308    IfZero.Variable := TSourceReferenceVariable(ParseReferenceVariable(SourceCode)).Variable;
     309    Result := True;
     310  end;
     311  if not Result then Tokenizer.TokenIndex := TokenIndex;
     312end;
     313
     314function TCompiler.ParseBeginEnd(SourceCode: TSourceCode; out BeginEnd: TCommandBeginEnd): Boolean;
     315var
     316  Token: TSourceToken;
     317  Keyword: string;
     318  TokenIndex: Integer;
     319  CommandBeginEnd: TCommandBeginEnd;
     320  CommandIfZero: TCommandIfZero;
     321  CommandFunctionCall: TCommandFunctionCall;
     322begin
     323  Result := False;
     324  TokenIndex := Tokenizer.TokenIndex;
     325  Token := Tokenizer.GetNext;
     326  Keyword := LowerCase(Token.Text);
     327  if Keyword = 'begin' then begin
     328    BeginEnd := TCommandBeginEnd.Create;
     329    BeginEnd.SourceCode := SourceCode;
     330    while True do begin
     331      if ParseVar(SourceCode) then
     332      else if ParseBeginEnd(SourceCode, CommandBeginEnd) then
     333        BeginEnd.Instructions.Add(CommandBeginEnd)
     334      else if ParseIfZero(SourceCode, CommandIfZero) then
     335        BeginEnd.Instructions.Add(CommandIfZero)
     336      else if ParseFunctionCall(SourceCode, CommandFunctionCall) then
     337        BeginEnd.Instructions.Add(CommandFunctionCall)
     338      else if Tokenizer.CheckNext('end', stIdentifier) then begin
     339        Break;
     340      end
     341      else raise Exception.Create('Unknown token: ' + Keyword);
     342    end;
    229343    Token := Tokenizer.GetNext;
    230     if Token.Kind = stEof then Break
    231     else
    232     if Token.Kind = stIdentifier then begin
    233       Keyword := LowerCase(Token.Text);
    234       if Keyword = 'var' then begin
    235         Token := Tokenizer.GetNext;
    236         Token2 := Tokenizer.GetNext;
    237         if Token2.Kind <> stIdentifier then
    238           raise Exception.Create('Expected type parameter');
    239         Variable := BeginEnd.SourceCode.Variables.Search(Token.Text);
    240         if not Assigned(Variable) then begin
    241           ValueType := BeginEnd.SourceCode.Types.Search(Token2.Text);
    242           if not Assigned(ValueType) then
    243             raise Exception.Create('Unsupported type: ' + Token2.Text);
    244           Variable := BeginEnd.SourceCode.Variables.AddNew(Token.Text,
    245             ValueType);
    246         end else raise Exception.Create('Variable redefined: ' + Token.Text);
    247       end else
    248       if Keyword = 'begin' then begin
    249         Instruction := TSourceBeginEnd.Create;
    250         BeginEnd.Instructions.Add(Instruction);
    251         TSourceBeginEnd(Instruction).SourceCode := BeginEnd.SourceCode;
    252         ParseBeginEnd(TSourceBeginEnd(Instruction));
    253       end else
    254       if Keyword = 'end' then begin
    255         Break;
    256       end else
    257       begin
    258         Funct := BeginEnd.SourceCode.Functions.Search(Keyword);
    259         if Assigned(Funct) then begin
    260           Instruction := TSourceFunctionCall.Create;
    261           TSourceFunctionCall(Instruction).Name := Keyword;
    262           for Param in Funct.Parameters do
    263           if Param.Kind = pkString then begin
    264             TSourceFunctionCall(Instruction).Parameters.Add(ParseReference)
    265           end else
    266           if Param.Kind = pkVariable then begin
    267             TSourceFunctionCall(Instruction).Parameters.Add(ParseReferenceVariable(True));
    268           end else
    269           raise Exception.Create('Unsupported parameter type.');
    270           BeginEnd.Instructions.Add(Instruction);
    271         end else raise Exception.Create('Unsupported keyword: ' + Token.Text);
    272       end;
    273     end else raise Exception.Create('Unsupported token kind.');
    274   end;
     344    if LowerCase(Token.Text) <> 'end' then
     345      raise Exception.Create('Expected end keyword');
     346    Result := True;
     347  end;
     348  if not Result then Tokenizer.TokenIndex := TokenIndex;
    275349end;
    276350
     
    292366var
    293367  I: Integer;
    294   Instruction: TSourceInstruction;
     368  Instruction: TSourceCommand;
    295369  TargetInstruction: TTargetInstruction;
    296370begin
    297371{  Target.Instructions.Count := 0;
    298372  for I := 0 to SourceCode.Instructions.Count - 1 do begin
    299     Instruction := TSourceInstruction(SourceCode.Instructions[I]);
    300     if Instruction is TSourceFunctionCall then begin
     373    Instruction := TSourceCommand(SourceCode.Instructions[I]);
     374    if Instruction is TCommandFunctionCall then begin
    301375      TargetInstruction := TTargetInstruction.Create;
    302376      TargetInstruction.Kind := tiFunction;
    303       TargetInstruction.Name := TSourceFunctionCall(Instruction).Name;
     377      TargetInstruction.Name := TCommandFunctionCall(Instruction).Name;
    304378      Target.Instructions.Add(TargetInstruction)
    305379    end else raise Exception.Create('Unsupported source instruction');
  • branches/easy compiler/UFormMain.pas

    r145 r146  
    5151procedure TForm1.FormShow(Sender: TObject);
    5252begin
    53 {  with MemoSource.Lines do begin
     53  with MemoSource.Lines do begin
     54    Add('Begin');
    5455    Add('var I Integer');
    5556    Add('Assign I 10');
    56     Add('Repeat');
     57    //Add('Repeat');
    5758    Add('Begin');
    58     Add('Decrement I 1');
     59    //Add('Decrement I 1');
    5960    Add('IfZero I');
    60     Add('Break');
     61    Add('Print ''condition''');
     62    //Add('Break');
    6163    Add('End');
    62   end;
    63  } with MemoSource.Lines do begin
     64    Add('End');
     65  end;
     66{  with MemoSource.Lines do begin
    6467    Add('PrintLn ''Super Calculator''');
    6568    Add('var Value1 Integer');
     
    7881    Add('PrintLn Result');
    7982  end;
    80 {  with MemoSource.Lines do begin
     83  with MemoSource.Lines do begin
    8184    Add('PrintLn ''Hello World!''');
    8285    Add('print ''Hello'' PRINT '' World!''');
  • branches/easy compiler/USourceCode.pas

    r145 r146  
    99
    1010type
    11   TSourceInstruction = class
     11  TSourceCommand = class
    1212  end;
    1313
     
    125125  end;
    126126
    127   { TSourceFunctionCall }
    128 
    129   TSourceFunctionCall = class(TSourceInstruction)
     127  { TCommandFunctionCall }
     128
     129  TCommandFunctionCall = class(TSourceCommand)
    130130    Name: string;
    131131    Parameters: TSourceReferences;
     
    136136  TSourceCode = class;
    137137
    138   { TSourceBeginEnd }
    139 
    140   TSourceBeginEnd = class(TSourceInstruction)
     138  { TCommandBeginEnd }
     139
     140  TCommandBeginEnd = class(TSourceCommand)
    141141    SourceCode: TSourceCode;
    142142    Instructions: TSourceInstructions;
    143143    constructor Create;
    144144    destructor Destroy; override;
     145  end;
     146
     147  TCommandIfZero = class(TSourceCommand)
     148    Variable: TSourceVariable;
    145149  end;
    146150
     
    155159    Variables: TSourceVariables;
    156160    Constants: TSourceConstants;
    157     Main: TSourceBeginEnd;
     161    Main: TCommandBeginEnd;
    158162    constructor Create;
    159163    destructor Destroy; override;
     
    171175end;
    172176
    173 { TSourceFunctionCall }
    174 
    175 constructor TSourceFunctionCall.Create;
     177{ TCommandFunctionCall }
     178
     179constructor TCommandFunctionCall.Create;
    176180begin
    177181  Parameters := TSourceReferences.Create;
    178182end;
    179183
    180 destructor TSourceFunctionCall.Destroy;
     184destructor TCommandFunctionCall.Destroy;
    181185begin
    182186  Parameters.Free;
     
    184188end;
    185189
    186 { TSourceBeginEnd }
    187 
    188 constructor TSourceBeginEnd.Create;
     190{ TCommandBeginEnd }
     191
     192constructor TCommandBeginEnd.Create;
    189193begin
    190194  Instructions := TSourceInstructions.Create;
    191195end;
    192196
    193 destructor TSourceBeginEnd.Destroy;
     197destructor TCommandBeginEnd.Destroy;
    194198begin
    195199  Instructions.Free;
     
    351355end;
    352356
    353 { TSourceFunctionCall }
     357{ TCommandFunctionCall }
    354358
    355359{ TSourceCode }
     
    394398  Constants := TSourceConstants.Create;
    395399  Functions := TSourceFunctions.Create;
    396   Main := TSourceBeginEnd.Create;
     400  Main := TCommandBeginEnd.Create;
    397401  Main.SourceCode := Self;
    398402  InitFunctions;
  • branches/easy compiler/USourceExecutor.pas

    r145 r146  
    3131    FOnOutput: TOutputEvent;
    3232    Variables: TExecutorVariables;
    33     procedure ExecuteBeginEnd(BeginEnd: TSourceBeginEnd);
     33    procedure ExecuteBeginEnd(BeginEnd: TCommandBeginEnd);
    3434  public
    3535    constructor Create;
     
    8484end;
    8585
    86 procedure TSourceExecutor.ExecuteBeginEnd(BeginEnd: TSourceBeginEnd);
     86procedure TSourceExecutor.ExecuteBeginEnd(BeginEnd: TCommandBeginEnd);
    8787var
    8888  IP: Integer;
    89   Instruction: TSourceInstruction;
     89  Instruction: TSourceCommand;
    9090  Variable: TSourceVariable;
    9191  Value: TSourceValue;
     
    9393  Text: string;
    9494  IntValue: Integer;
     95  SkipNext: Boolean;
    9596
    9697function ReadValueReference(Reference: TSourceReference): TSourceValue;
     
    114115
    115116begin
     117  SkipNext := False;
    116118  IP := 0;
    117119  while IP < BeginEnd.Instructions.Count do begin
    118     Instruction := TSourceInstruction(BeginEnd.Instructions[IP]);
    119     if Instruction is TSourceFunctionCall then
    120     with TSourceFunctionCall(Instruction) do begin
     120    if SkipNext then begin
     121      SkipNext := False;
     122      Inc(IP);
     123      Continue;
     124    end;
     125    Instruction := TSourceCommand(BeginEnd.Instructions[IP]);
     126    if Instruction is TCommandFunctionCall then
     127    with TCommandFunctionCall(Instruction) do begin
    121128      if Name = 'print' then begin
    122129        if Assigned(FOnOutput) then begin
     
    178185        else raise Exception.Create('Wrong type for increment');
    179186      end else
    180       raise Exception.Create('Unsupported function: ' + TSourceFunctionCall(Instruction).Name);
     187      raise Exception.Create('Unsupported function: ' + TCommandFunctionCall(Instruction).Name);
    181188    end else
    182     if Instruction is TSourceBeginEnd then begin
    183       ExecuteBeginEnd(TSourceBeginEnd(Instruction));
     189    if Instruction is TCommandBeginEnd then begin
     190      ExecuteBeginEnd(TCommandBeginEnd(Instruction));
     191    end else
     192    if Instruction is TCommandIfZero then begin
     193      ExecutorVar := Variables.Search(TCommandIfZero(Instruction).Variable);
     194      if Assigned(ExecutorVar) then begin
     195        if ExecutorVar.Variable.ValueType.Name = 'Integer' then begin
     196          if TSourceValueInteger(ExecutorVar.Value).Value = 0 then SkipNext := True;
     197        end else
     198        raise Exception.Create('Can compare only integers');
     199      end else
     200      raise Exception.Create('Variable not found');
    184201    end else
    185202    raise Exception.Create('Unsupported instruction');
  • branches/easy compiler/USourceGenerator.pas

    r145 r146  
    1414  private
    1515    Indent: Integer;
    16     function GenerateBeginEnd(BeginEnd: TSourceBeginEnd): string;
     16    function GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string;
    1717    function IndentStr: string;
    1818  public
     
    4949end;
    5050
    51 function TSourceGenerator.GenerateBeginEnd(BeginEnd: TSourceBeginEnd): string;
     51function TSourceGenerator.GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string;
    5252var
    53   Instruction: TSourceInstruction;
     53  Instruction: TSourceCommand;
    5454  I: Integer;
    5555  Value: TSourceValue;
     
    7777  with BeginEnd do
    7878  for I := 0 to Instructions.Count - 1 do begin
    79     Instruction := TSourceInstruction(Instructions[I]);
    80     if Instruction is TSourceFunctionCall then
    81     with TSourceFunctionCall(Instruction) do begin
     79    Instruction := TSourceCommand(Instructions[I]);
     80    if Instruction is TCommandFunctionCall then
     81    with TCommandFunctionCall(Instruction) do begin
    8282      if Name = 'print' then begin
    8383        Result := Result + IndentStr + 'Write(' + GenerateRef(TSourceReference(Parameters[0])) + ');' +
     
    101101      raise Exception.Create('Unsupported instruction name.');
    102102    end else
    103     if Instruction is TSourceBeginEnd then begin
    104       Result := Result + GenerateBeginEnd(TSourceBeginEnd(Instruction)) +
     103    if Instruction is TCommandBeginEnd then begin
     104      Result := Result + GenerateBeginEnd(TCommandBeginEnd(Instruction)) +
    105105        ';' + LineEnding;
     106    end else
     107    if Instruction is TCommandIfZero then begin
     108      Result := Result + IndentStr + 'if ' + TCommandIfZero(Instruction).Variable.Name + ' = 0 then ';
    106109    end else
    107110    raise Exception.Create('Unsupported instruction');
Note: See TracChangeset for help on using the changeset viewer.