Ignore:
Timestamp:
Nov 25, 2020, 12:18:45 AM (3 years ago)
Author:
chronos
Message:
  • Added: Support for more expression operators.
  • Added: Support for brackets in expressions.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/interpreter2/Parsers/UParserPascal.pas

    r221 r222  
    99
    1010type
     11
     12  { TParserPascal }
     13
    1114  TParserPascal = class(TParser)
    1215  protected
     
    2124    function ParseFunctionParameter(Block: TBlock; out Parameter: TFunctionParameter): Boolean;
    2225    function ParseAssignment(Block: TBlock; out Assignment: TAssignment): Boolean;
    23     function ParseExpression(Block: TBlock; out Expression: TExpression): Boolean;
     26    function ParseExpression(Block: TBlock; out Expression: TExpression;
     27      WithOperation: Boolean = True): Boolean;
    2428    function ParseExpressionOperation(Block: TBlock; out ExpressionOperation: TExpressionOperation): Boolean;
    2529    function ParseExpressionOperand(Block: TBlock; out ExpressionOperand: TExpressionOperand): Boolean;
     30    function ParseExpressionBrackets(Block: TBlock; out ExpressionBrackets: TExpressionBrackets): Boolean;
    2631    function ParseConstantRef(Block: TBlock; out ConstantRef: TConstant): Boolean;
    2732    function ParseConstant(Block: TBlock; out ConstantRef: TConstant): Boolean;
     
    4247  Command: TCommand;
    4348begin
    44   if Tokenizer.CheckNext('begin', tkKeyword) then begin
    45     Tokenizer.Expect('begin', tkKeyword);
     49  if Tokenizer.CheckNextAndRead('begin', tkKeyword) then begin
    4650    BeginEnd := TBeginEnd.Create;
    4751    Result := True;
     
    7781      FunctionCall := TFunctionCall.Create;
    7882      FunctionCall.FunctionDef := FunctionDef;
    79       if Tokenizer.CheckNext('(', tkSpecialSymbol) then begin
    80         Tokenizer.Expect('(', tkSpecialSymbol);
     83      if Tokenizer.CheckNextAndRead('(', tkSpecialSymbol) then begin
    8184        for I := 0 to FunctionDef.Params.Count - 1 do begin
    8285          if I > 0 then Tokenizer.Expect(',', tkSpecialSymbol);
     
    160163  Prog.SystemBlock.Free;
    161164  Prog.SystemBlock := SystemBlock;
    162   if Tokenizer.CheckNext('program', tkKeyword) then begin
    163     Tokenizer.Expect('program', tkKeyword);
     165  if Tokenizer.CheckNextAndRead('program', tkKeyword) then begin
    164166    Token := Tokenizer.GetNext;
    165167    if Token.Kind = tkIdentifier then
     
    216218  TypeRef: TType;
    217219begin
    218   if Tokenizer.CheckNext('var', tkKeyword) then begin
    219     Result := True;
    220     Tokenizer.Expect('var', tkKeyword);
     220  if Tokenizer.CheckNextAndRead('var', tkKeyword) then begin
     221    Result := True;
    221222    while Tokenizer.CheckNextKind(tkIdentifier) do begin
    222223      Token := Tokenizer.GetNext;
     
    251252  TypeRef: TType;
    252253begin
    253   if Tokenizer.CheckNext('const', tkKeyword) then begin
    254     Result := True;
    255     Tokenizer.Expect('const', tkKeyword);
     254  if Tokenizer.CheckNextAndRead('const', tkKeyword) then begin
     255    Result := True;
    256256    while Tokenizer.CheckNextKind(tkIdentifier) do begin
    257257      Token := Tokenizer.GetNext;
     
    300300begin
    301301  Result := False;
    302   if Tokenizer.CheckNext('function', tkKeyword) then begin
    303     Tokenizer.Expect('function', tkKeyword);
     302  if Tokenizer.CheckNextAndRead('function', tkKeyword) then begin
    304303    Result := True;
    305304    Func := TFunction.Create;
     
    307306    if Token.Kind = tkIdentifier then begin
    308307      Func.Name := Token.Text;
    309       if Tokenizer.CheckNext('(', tkSpecialSymbol) then begin
    310         Tokenizer.Expect('(', tkSpecialSymbol);
     308      if Tokenizer.CheckNextAndRead('(', tkSpecialSymbol) then begin
    311309        while not Tokenizer.CheckNext(')', tkSpecialSymbol) do begin
    312310          if Func.Params.Count > 0 then Tokenizer.Expect(',', tkSpecialSymbol);
     
    324322        end;
    325323      end;
    326       if Tokenizer.CheckNext(':', tkSpecialSymbol) then begin
    327         Tokenizer.Expect(':', tkSpecialSymbol);
     324      if Tokenizer.CheckNextAndRead(':', tkSpecialSymbol) then begin
    328325        Token := Tokenizer.GetNext;
    329326        if Token.Kind = tkIdentifier then begin
     
    402399end;
    403400
    404 function TParserPascal.ParseExpression(Block: TBlock; out Expression: TExpression
    405   ): Boolean;
     401function TParserPascal.ParseExpression(Block: TBlock; out Expression: TExpression;
     402  WithOperation: Boolean = True): Boolean;
    406403var
    407404  ExpressionOperation: TExpressionOperation;
    408405  ExpressionOperand: TExpressionOperand;
    409 begin
    410   Result := False;
    411   if ParseExpressionOperation(Block, ExpressionOperation) then begin
     406  ExpressionBrackets: TExpressionBrackets;
     407begin
     408  Result := False;
     409  if WithOperation and ParseExpressionOperation(Block, ExpressionOperation) then begin
    412410    Result := True;
    413411    Expression := ExpressionOperation;
     412  end else
     413  if ParseExpressionBrackets(Block, ExpressionBrackets) then begin
     414    Result := True;
     415    Expression := ExpressionBrackets;
    414416  end else
    415417  if ParseExpressionOperand(Block, ExpressionOperand) then begin
     
    422424  ExpressionOperation: TExpressionOperation): Boolean;
    423425var
    424   Operand: TExpressionOperand;
    425   Token: TToken;
    426426  Expression: TExpression;
     427  Token: TToken;
    427428  LastPos: TTokenizerPos;
    428429  I: Integer;
     
    431432  Result := False;
    432433  LastPos := Tokenizer.Pos;
    433   if ParseExpressionOperand(Block, Operand) then begin
     434  if ParseExpression(Block, Expression, False) then begin
    434435    Token := Tokenizer.GetNext;
    435     if (Token.Kind = tkSpecialSymbol) and Tokenizer.IsOperator(Token.Text) then begin
     436    if Tokenizer.IsOperator(Token.Text) then begin
    436437      Result := True;
    437438      ExpressionOperation := TExpressionOperation.Create;
    438       ExpressionOperation.TypeRef := Operand.GetType;
    439       if Token.Text = '+' then ExpressionOperation.Operation := eoAdd
    440       else if Token.Text = '-' then ExpressionOperation.Operation := eoSub
    441       else if Token.Text = '=' then ExpressionOperation.Operation := eoEqual
    442       else if Token.Text = '<>' then ExpressionOperation.Operation := eoNotEqual
    443       else Error('Unsupported operator ' + Token.Text);
     439      ExpressionOperation.Items.Add(Expression);
     440      ExpressionOperation.TypeRef := Expression.GetType;
     441      ExpressionOperation.Operation := GetOperatorByName(Token.Text);
     442      if ExpressionOperation.Operation = eoNone then
     443        Error('Unsupported operator ' + Token.Text);
    444444      ExpressionOperation.FunctionRef := ExpressionOperation.TypeRef.Functions.SearchByName(ExpressionOperation.GetFunctionName);
    445       if not Assigned(ExpressionOperation.FunctionRef.ResultType) then
    446         raise Exception.Create('Missing result type for function');
    447       ExpressionOperation.TypeRef := ExpressionOperation.FunctionRef.ResultType;
    448       ExpressionOperation.Items.Add(Operand);
    449       I := 1;
    450       if ParseExpression(Block, Expression) then begin
    451         ExpectedType := TFunctionParameter(ExpressionOperation.FunctionRef.Params[I]).TypeRef;
    452         if Expression.GetType = ExpectedType then
    453           ExpressionOperation.Items.Add(Expression)
    454           else Error('Expression operands needs to be same type. Expected ' + ExpectedType.Name + ' but found ' + Expression.GetType.Name);
    455       end else Error('Missing operand.');
    456     end else Operand.Free;
     445      if Assigned(ExpressionOperation.FunctionRef) then begin
     446        if not Assigned(ExpressionOperation.FunctionRef.ResultType) then
     447          raise Exception.Create('Missing result type for function');
     448        ExpressionOperation.TypeRef := ExpressionOperation.FunctionRef.ResultType;
     449        I := 1;
     450        if ParseExpression(Block, Expression) then begin
     451          ExpectedType := TFunctionParameter(ExpressionOperation.FunctionRef.Params[I]).TypeRef;
     452          if Expression.GetType = ExpectedType then
     453            ExpressionOperation.Items.Add(Expression)
     454            else Error('Expression operands needs to be same type. Expected ' + ExpectedType.Name + ' but found ' + Expression.GetType.Name);
     455        end else Error('Missing operand.');
     456      end else Error('Operator ' + Token.Text + ' not defind for type ' + ExpressionOperation.TypeRef.Name + '.');
     457    end else Expression.Free;
    457458  end;
    458459  if not Result then Tokenizer.Pos := LastPos;
     
    490491    ExpressionOperand.VariableRef := Variable;
    491492    ExpressionOperand.OperandType := otVariableRef;
    492   end else Error('Expected expression operand.');
     493  end else
     494    Error('Expected expression operand.');
     495end;
     496
     497function TParserPascal.ParseExpressionBrackets(Block: TBlock; out
     498  ExpressionBrackets: TExpressionBrackets): Boolean;
     499var
     500  Expression: TExpression;
     501begin
     502  Result := False;
     503  if Tokenizer.CheckNextAndRead('(', tkSpecialSymbol) then begin
     504    Result := True;
     505    if ParseExpression(Block, Expression) then begin
     506      ExpressionBrackets := TExpressionBrackets.Create;
     507      ExpressionBrackets.Expression := Expression;
     508    end;
     509    Tokenizer.Expect(')', tkSpecialSymbol);
     510  end;
    493511end;
    494512
     
    562580begin
    563581  Result := False;
    564   if Tokenizer.CheckNext('if', tkKeyword) then begin
    565     Tokenizer.Expect('if', tkKeyword);
     582  if Tokenizer.CheckNextAndRead('if', tkKeyword) then begin
    566583    Result := True;
    567584    IfThenElse := TIfThenElse.Create;
     
    574591        IfThenElse.CommandThen := Command;
    575592        Command.Parent := IfThenElse;
    576         if Tokenizer.CheckNext('else', tkKeyword) then begin
    577           Tokenizer.Expect('else', tkKeyword);
     593        if Tokenizer.CheckNextAndRead('else', tkKeyword) then begin
    578594          if ParseCommand(Block, Command) then begin
    579595            IfThenElse.CommandElse.Free;
     
    593609begin
    594610  Result := False;
    595   if Tokenizer.CheckNext('while', tkKeyword) then begin
    596     Tokenizer.Expect('while', tkKeyword);
     611  if Tokenizer.CheckNextAndRead('while', tkKeyword) then begin
    597612    Result := True;
    598613    WhileDo := TWhileDo.Create;
     
    617632begin
    618633  Result := False;
    619   if Tokenizer.CheckNext('repeat', tkKeyword) then begin
    620     Tokenizer.Expect('repeat', tkKeyword);
     634  if Tokenizer.CheckNextAndRead('repeat', tkKeyword) then begin
    621635    RepeatUntil := TRepeatUntil.Create;
    622636    Result := True;
     
    647661begin
    648662  Result := False;
    649   if Tokenizer.CheckNext('for', tkKeyword) then begin
    650     Tokenizer.Expect('for', tkKeyword);
     663  if Tokenizer.CheckNextAndRead('for', tkKeyword) then begin
    651664    Result := True;
    652665    ForToDo := TForToDo.Create;
     
    676689begin
    677690  Result := False;
    678   if Tokenizer.CheckNext('break', tkKeyword) then begin
    679     Tokenizer.Expect('break', tkKeyword);
     691  if Tokenizer.CheckNextAndRead('break', tkKeyword) then begin
    680692    Result := True;
    681693    BreakCmd := TBreak.Create;
     
    687699begin
    688700  Result := False;
    689   if Tokenizer.CheckNext('continue', tkKeyword) then begin
    690     Tokenizer.Expect('continue', tkKeyword);
     701  if Tokenizer.CheckNextAndRead('continue', tkKeyword) then begin
    691702    Result := True;
    692703    ContinueCmd := TContinue.Create;
Note: See TracChangeset for help on using the changeset viewer.