Ignore:
Timestamp:
Jan 17, 2018, 2:25:45 PM (7 years ago)
Author:
chronos
Message:
  • Modified: ParseBeginEnd method split to several other items for parsing each specific command.
File:
1 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');
Note: See TracChangeset for help on using the changeset viewer.