Ignore:
Timestamp:
Jun 26, 2023, 6:08:23 PM (17 months ago)
Author:
chronos
Message:
  • Added: Support for procedures.
  • Added: Project pascal file can be opened from main menu. Last file name is remembered.
  • Modified: Improved XML output of source structure.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/xpascal/Parsers/ParserPascal.pas

    r230 r233  
    1414    function ParseBeginEnd(Block: TBlock; out BeginEnd: TBeginEnd): Boolean;
    1515    function ParseFunctionCall(Block: TBlock; out FunctionCall: TFunctionCall): Boolean;
     16    function ParseProcedureCall(Block: TBlock; out ProcedureCall: TProcedureCall): Boolean;
    1617    function ParseCommand(Block: TBlock; out Command: TCommand): Boolean;
    1718    function ParseProgram(SystemBlock: TBlock; out Prog: TProgram): Boolean; override;
     
    2021    function ParseBlockConst(Block: TBlock): Boolean;
    2122    function ParseFunction(Block: TBlock; out Func: TFunction): Boolean;
     23    function ParseFunctionParameters(Block: TBlock; out Params: TFunctionParameters): Boolean;
    2224    function ParseFunctionParameter(Block: TBlock; out Parameter: TFunctionParameter): Boolean;
     25    function ParseProcedure(Block: TBlock; out Proc: TProcedure): Boolean;
    2326    function ParseAssignment(Block: TBlock; out Assignment: TAssignment): Boolean;
    2427    function ParseExpression(Block: TBlock; out Expression: TExpression;
     
    101104end;
    102105
     106function TParserPascal.ParseProcedureCall(Block: TBlock; out
     107  ProcedureCall: TProcedureCall): Boolean;
     108var
     109  Token: TToken;
     110  LastPos: TTokenizerPos;
     111  ProcedureDef: TProcedure;
     112  Expression: TExpression;
     113  I: Integer;
     114begin
     115  LastPos := Tokenizer.Pos;
     116  Token := Tokenizer.GetNext;
     117  if Token.Kind = tkIdentifier then begin
     118    ProcedureDef := Block.GetProcedure(Token.Text);
     119    if Assigned(ProcedureDef) then begin
     120      ProcedureCall := TProcedureCall.Create;
     121      ProcedureCall.ProcedureDef := ProcedureDef;
     122      if Tokenizer.CheckNextAndRead('(', tkSpecialSymbol) then begin
     123        for I := 0 to ProcedureDef.Params.Count - 1 do begin
     124          if I > 0 then Tokenizer.Expect(',', tkSpecialSymbol);
     125          if ParseExpression(Block, Expression) then begin
     126            if Expression.GetType = TFunctionParameter(ProcedureDef.Params[I]).TypeRef then
     127              ProcedureCall.Params.Add(Expression)
     128              else Error('Function parameter mismatch.');
     129          end else Error('Expected procedure parameter.');
     130        end;
     131        Tokenizer.Expect(')', tkSpecialSymbol);
     132      end;
     133      Result := True;
     134    end else begin
     135      Result := False;
     136      Tokenizer.Pos := LastPos;
     137    end;
     138  end else begin
     139    Result := False;
     140    Tokenizer.Pos := LastPos;
     141  end;
     142end;
     143
    103144function TParserPascal.ParseCommand(Block: TBlock; out Command: TCommand): Boolean;
    104145var
    105146  BeginEnd: TBeginEnd;
    106147  FunctionCall: TFunctionCall;
     148  ProcedureCall: TProcedureCall;
    107149  Assignment: TAssignment;
    108150  IfThenElse: TIfThenElse;
     
    132174    Result := True;
    133175    Command := FunctionCall;
     176  end else
     177  if ParseProcedureCall(Block, ProcedureCall) then begin
     178    Result := True;
     179    Command := ProcedureCall;
    134180  end else
    135181  if ParseRepeatUntil(Block, RepeatUntil) then begin
     
    183229  BeginEnd: TBeginEnd;
    184230  Func: TFunction;
     231  Proc: TProcedure;
    185232begin
    186233  Result := False;
     
    195242    if ParseFunction(Block, Func) then begin
    196243      Block.Functions.Add(Func);
    197     end else begin
     244    end else
     245    if ParseProcedure(Block, Proc) then begin
     246      Block.Procedures.Add(Proc);
     247    end else
     248    begin
    198249      Break;
    199250    end;
     
    291342var
    292343  Token: TToken;
    293   FunctionParameter: TFunctionParameter;
    294344  NewBlock: TBlock;
    295345  TypeRef: TType;
    296346  Variable: TVariable;
    297   I: Integer;
     347  FunctionParameters: TFunctionParameters;
    298348begin
    299349  Result := False;
     
    304354    if Token.Kind = tkIdentifier then begin
    305355      Func.Name := Token.Text;
    306       if Tokenizer.CheckNextAndRead('(', tkSpecialSymbol) then begin
    307         while not Tokenizer.CheckNext(')', tkSpecialSymbol) do begin
    308           if Func.Params.Count > 0 then Tokenizer.Expect(',', tkSpecialSymbol);
    309           if ParseFunctionParameter(Block, FunctionParameter) then begin
    310             Func.Params.Add(FunctionParameter);
    311           end else Error('Expected function parameter.');
    312         end;
    313         Tokenizer.Expect(')', tkSpecialSymbol);
    314         for I := 0 to Func.Params.Count - 1 do begin
    315           Variable := TVariable.Create;
    316           Variable.Name := TFunctionParameter(Func.Params[I]).Name;
    317           Variable.TypeRef := TFunctionParameter(Func.Params[I]).TypeRef;
    318           Variable.Internal := True;
    319           Func.Block.Variables.Add(Variable);
    320         end;
    321       end;
     356      Func.Block.ParentBlock := Block;
     357      if ParseFunctionParameters(Func.Block, FunctionParameters) then begin
     358        Func.Params.Free;
     359        Func.Params := FunctionParameters;
     360      end;
     361
    322362      if Tokenizer.CheckNextAndRead(':', tkSpecialSymbol) then begin
    323363        Token := Tokenizer.GetNext;
     
    339379      end else Error('Expected function block');
    340380    end else Error('Expected function name');
     381  end;
     382end;
     383
     384function TParserPascal.ParseFunctionParameters(Block: TBlock;
     385  out Params: TFunctionParameters): Boolean;
     386var
     387  FunctionParameter: TFunctionParameter;
     388  I: Integer;
     389  Variable: TVariable;
     390begin
     391  Result := False;
     392  Params := TFunctionParameters.Create;
     393  if Tokenizer.CheckNextAndRead('(', tkSpecialSymbol) then begin
     394    while not Tokenizer.CheckNext(')', tkSpecialSymbol) do begin
     395      if Params.Count > 0 then Tokenizer.Expect(',', tkSpecialSymbol);
     396      if ParseFunctionParameter(Block, FunctionParameter) then begin
     397        Params.Add(FunctionParameter);
     398      end else Error('Expected function parameter.');
     399    end;
     400    Tokenizer.Expect(')', tkSpecialSymbol);
     401    for I := 0 to Params.Count - 1 do begin
     402      Variable := TVariable.Create;
     403      Variable.Name := Params[I].Name;
     404      Variable.TypeRef := Params[I].TypeRef;
     405      Variable.Internal := True;
     406      Block.Variables.Add(Variable);
     407    end;
     408    Result := True;
    341409  end;
    342410end;
     
    368436    end else Error('Expected parameter type');
    369437  end else Error('Expected parameter name');
     438end;
     439
     440function TParserPascal.ParseProcedure(Block: TBlock; out Proc: TProcedure
     441  ): Boolean;
     442var
     443  Token: TToken;
     444  NewBlock: TBlock;
     445  FunctionParameters: TFunctionParameters;
     446begin
     447  Result := False;
     448  if Tokenizer.CheckNextAndRead('procedure', tkKeyword) then begin
     449    Result := True;
     450    Proc := TProcedure.Create;
     451    Token := Tokenizer.GetNext;
     452    if Token.Kind = tkIdentifier then begin
     453      Proc.Name := Token.Text;
     454      Proc.Block.ParentBlock := Block;
     455      if ParseFunctionParameters(Proc.Block, FunctionParameters) then begin
     456        Proc.Params.Free;
     457        Proc.Params := FunctionParameters;
     458      end;
     459
     460      Tokenizer.Expect(';', tkSpecialSymbol);
     461      if ParseBlock(Block, NewBlock, Proc.Block) then begin
     462        Tokenizer.Expect(';', tkSpecialSymbol);
     463      end else Error('Expected procedure block');
     464    end else Error('Expected procedure name');
     465  end;
    370466end;
    371467
Note: See TracChangeset for help on using the changeset viewer.