Changeset 221


Ignore:
Timestamp:
Nov 24, 2020, 6:19:17 PM (3 years ago)
Author:
chronos
Message:
  • Fixed: Resolved remaining memory leaks.
  • Modified: Generators moved to Generators subdirectory.
  • Modified: PascalParser moved to Parsers subdirectory.
Location:
branches/interpreter2
Files:
3 added
7 edited
4 moved

Legend:

Unmodified
Added
Removed
  • branches/interpreter2/Forms/UFormMain.lfm

    r213 r221  
    1313  OnDestroy = FormDestroy
    1414  OnShow = FormShow
    15   LCLVersion = '2.0.2.0'
     15  LCLVersion = '2.0.10.0'
    1616  object PanelMessages: TPanel
    1717    Left = 0
     
    4848  end
    4949  object MainMenu1: TMainMenu
    50     left = 790
    51     top = 753
     50    Left = 790
     51    Top = 753
    5252    object MenuItemFile: TMenuItem
    5353      Caption = 'File'
     
    8282  end
    8383  object ActionList1: TActionList
    84     left = 901
    85     top = 759
     84    Left = 901
     85    Top = 759
    8686    object AGeneratePascal: TAction
    8787      Caption = 'Generate Pascal'
  • branches/interpreter2/Forms/UFormMain.pas

    r213 r221  
    7070uses
    7171  UParser, UExecutor, UGeneratorPascal, UGeneratorPhp, UFormMessages, UFormSource,
    72   UGeneratorCSharp, UGeneratorXml, UFormOutput;
     72  UGeneratorCSharp, UGeneratorXml, UFormOutput, UParserPascal;
    7373
    7474{ TFormMain }
     
    111111begin
    112112  FormMessages.Clear;
    113   Parser := TParser.Create;
     113  Parser := TParserPascal.Create;
    114114  Parser.OnError := InterpreterError;
    115115  Parser.Source := FormSource.SynEditSource.Lines.Text;
  • branches/interpreter2/UExecutor.pas

    r214 r221  
    138138destructor TExecutorFunction.Destroy;
    139139begin
    140   Block.Free;
    141   inherited Destroy;
     140  FreeAndNil(Block);
     141  inherited;
    142142end;
    143143
     
    151151destructor TExecutorVariable.Destroy;
    152152begin
    153   Value.Free;
    154   inherited Destroy;
     153  FreeAndNil(Value);
     154  inherited;
    155155end;
    156156
     
    164164destructor TExecutorType.Destroy;
    165165begin
    166   Functions.Free;
    167   inherited Destroy;
     166  FreeAndNil(Functions);
     167  inherited;
    168168end;
    169169
     
    273273destructor TExecutorBlock.Destroy;
    274274begin
    275   Variables.Free;
    276   Functions.Free;
    277   Types.Free;
    278   inherited Destroy;
     275  FreeAndNil(Variables);
     276  FreeAndNil(Functions);
     277  FreeAndNil(Types);
     278  inherited;
    279279end;
    280280
     
    513513var
    514514  Value: TValue;
     515  BoolValue: Boolean;
    515516begin
    516517  while True do begin
    517518    Value := ExecuteExpression(Block, WhileDo.Expression);
    518519    if Value is TValueBoolean then begin
    519       if not TValueBoolean(Value).Value then Break;
     520      BoolValue := TValueBoolean(Value).Value;
     521      Value.Free;
     522      if not BoolValue then Break;
    520523      ExecuteCommand(Block, WhileDo.Command);
    521524      if WhileDo.DoContinue then begin
     
    528531      end;
    529532    end else raise Exception.Create('Expected boolean value.');
    530     Value.Free;
    531533  end;
    532534end;
     
    537539  Value: TValue;
    538540  I: Integer;
     541  BoolValue: Boolean;
    539542begin
    540543  while True do begin
     
    552555    Value := ExecuteExpression(Block, RepeatUntil.Expression);
    553556    if Value is TValueBoolean then begin
    554       if TValueBoolean(Value).Value then Break;
     557      BoolValue := TValueBoolean(Value).Value;
     558      Value.Free;
     559      if BoolValue then Break;
    555560    end else raise Exception.Create('Expected boolean value.');
    556     Value.Free;
    557561  end;
    558562end;
     
    654658      ExecuteBlock(Block, FunctionCall.FunctionDef.Block, ExecutorFunction.Block);
    655659      ExecutorVariable := ExecutorFunction.Block.Variables.SearchByVariable(TVariable(FunctionCall.FunctionDef.Block.Variables.SearchByName('Result')));
    656       Result := ExecutorVariable.Value;
     660      Result := ExecutorVariable.Value.Clone;
    657661    end;
    658662  end else raise Exception.Create('No executor for ' + FunctionCall.FunctionDef.Name + ' function.');
     
    706710    raise Exception.Create('Missing operator function ' + FuncName + ' for type ' + Expression.TypeRef.Name);
    707711
    708   Result := Expression.TypeRef.ValueClass.Create;
    709 
    710712  SetLength(Params, Expression.Items.Count);
    711713  for I := 0 to Expression.Items.Count - 1 do begin
  • branches/interpreter2/UParser.pas

    r212 r221  
    1515  private
    1616    FOnError: TErrorEvent;
    17     Tokenizer: TTokenizer;
    18     function ParseBeginEnd(Block: TBlock; out BeginEnd: TBeginEnd): Boolean;
    19     function ParseFunctionCall(Block: TBlock; out FunctionCall: TFunctionCall): Boolean;
    20     function ParseCommand(Block: TBlock; out Command: TCommand): Boolean;
    21     function ParseProgram(SystemBlock: TBlock; out Prog: TProgram): Boolean;
    22     function ParseBlock(ParentBlock: TBlock; out Block: TBlock; ExistingBlock: TBlock = nil): Boolean;
    23     function ParseBlockVar(Block: TBlock): Boolean;
    24     function ParseBlockConst(Block: TBlock): Boolean;
    25     function ParseFunction(Block: TBlock; out Func: TFunction): Boolean;
    26     function ParseFunctionParameter(Block: TBlock; out Parameter: TFunctionParameter): Boolean;
    27     function ParseAssignment(Block: TBlock; out Assignment: TAssignment): Boolean;
    28     function ParseExpression(Block: TBlock; out Expression: TExpression): Boolean;
    29     function ParseExpressionOperation(Block: TBlock; out ExpressionOperation: TExpressionOperation): Boolean;
    30     function ParseExpressionOperand(Block: TBlock; out ExpressionOperand: TExpressionOperand): Boolean;
    31     function ParseConstantRef(Block: TBlock; out ConstantRef: TConstant): Boolean;
    32     function ParseConstant(Block: TBlock; out ConstantRef: TConstant): Boolean;
    33     function ParseVariable(Block: TBlock; out VariableRef: TVariable): Boolean;
    34     function ParseIfThenElse(Block: TBlock; out IfThenElse: TIfThenElse): Boolean;
    35     function ParseWhileDo(Block: TBlock; out WhileDo: TWhileDo): Boolean;
    36     function ParseRepeatUntil(Block: TBlock; out RepeatUntil: TRepeatUntil): Boolean;
    37     function ParseForToDo(Block: TBlock; out ForToDo: TForToDo): Boolean;
    38     function ParseBreak(Block: TBlock; out BreakCmd: TBreak): Boolean;
    39     function ParseContinue(Block: TBlock; out ContinueCmd: TContinue): Boolean;
    4017    procedure TokenizerError(Pos: TPoint; Text: string);
    4118    procedure InitSystemBlock(Block: TBlock);
     19  protected
     20    Tokenizer: TTokenizer;
     21    function ParseProgram(SystemBlock: TBlock; out Prog: TProgram): Boolean; virtual;
    4222  public
    4323    Source: string;
     
    5434
    5535{ TParser }
    56 
    57 function TParser.ParseBeginEnd(Block: TBlock; out BeginEnd: TBeginEnd): Boolean;
    58 var
    59   Command: TCommand;
    60 begin
    61   if Tokenizer.CheckNext('begin', tkKeyword) then begin
    62     Tokenizer.Expect('begin', tkKeyword);
    63     BeginEnd := TBeginEnd.Create;
    64     Result := True;
    65     while not Tokenizer.CheckNext('end', tkKeyword) do begin
    66       if ParseCommand(Block, Command) then begin
    67         Command.Parent := BeginEnd;
    68         BeginEnd.Commands.Add(Command);
    69         Tokenizer.Expect(';', tkSpecialSymbol);
    70       end else begin
    71         Error('Unexpected token ' + Tokenizer.GetNext.Text);
    72         Result := False;
    73         Break;
    74       end;
    75     end;
    76     Tokenizer.Expect('end', tkKeyword);
    77   end else Result := False;
    78 end;
    79 
    80 function TParser.ParseFunctionCall(Block: TBlock; out FunctionCall: TFunctionCall
    81   ): Boolean;
    82 var
    83   Token: TToken;
    84   LastPos: TTokenizerPos;
    85   FunctionDef: TFunction;
    86   Expression: TExpression;
    87   I: Integer;
    88 begin
    89   LastPos := Tokenizer.Pos;
    90   Token := Tokenizer.GetNext;
    91   if Token.Kind = tkIdentifier then begin
    92     FunctionDef := Block.GetFunction(Token.Text);
    93     if Assigned(FunctionDef) then begin
    94       FunctionCall := TFunctionCall.Create;
    95       FunctionCall.FunctionDef := FunctionDef;
    96       if Tokenizer.CheckNext('(', tkSpecialSymbol) then begin
    97         Tokenizer.Expect('(', tkSpecialSymbol);
    98         for I := 0 to FunctionDef.Params.Count - 1 do begin
    99           if I > 0 then Tokenizer.Expect(',', tkSpecialSymbol);
    100           if ParseExpression(Block, Expression) then begin
    101             if Expression.GetType = TFunctionParameter(FunctionDef.Params[I]).TypeRef then
    102               FunctionCall.Params.Add(Expression)
    103               else Error('Function parameter mismatch.');
    104           end else Error('Expected function parameter.');
    105         end;
    106         Tokenizer.Expect(')', tkSpecialSymbol);
    107       end;
    108       Result := True;
    109     end else begin
    110       Result := False;
    111       Tokenizer.Pos := LastPos;
    112     end;
    113   end else begin
    114     Result := False;
    115     Tokenizer.Pos := LastPos;
    116   end;
    117 end;
    118 
    119 function TParser.ParseCommand(Block: TBlock; out Command: TCommand): Boolean;
    120 var
    121   BeginEnd: TBeginEnd;
    122   FunctionCall: TFunctionCall;
    123   Assignment: TAssignment;
    124   IfThenElse: TIfThenElse;
    125   WhileDo: TWhileDo;
    126   ForToDo: TForToDo;
    127   RepeatUntil: TRepeatUntil;
    128   BreakCmd: TBreak;
    129   ContinueCmd: TContinue;
    130 begin
    131   if ParseIfThenElse(Block, IfThenElse) then begin
    132     Result := True;
    133     Command := IfThenElse;
    134   end else
    135   if ParseWhileDo(Block, WhileDo) then begin
    136     Result := True;
    137     Command := WhileDo;
    138   end else
    139   if ParseForToDo(Block, ForToDo) then begin
    140     Result := True;
    141     Command := ForToDo;
    142   end else
    143   if ParseBeginEnd(Block, BeginEnd) then begin
    144     Result := True;
    145     Command := BeginEnd;
    146   end else
    147   if ParseFunctionCall(Block, FunctionCall) then begin
    148     Result := True;
    149     Command := FunctionCall;
    150   end else
    151   if ParseRepeatUntil(Block, RepeatUntil) then begin
    152     Result := True;
    153     Command := RepeatUntil;
    154   end else
    155   if ParseAssignment(Block, Assignment) then begin
    156     Result := True;
    157     Command := Assignment;
    158   end else
    159   if ParseBreak(Block, BreakCmd) then begin
    160     Result := True;
    161     Command := BreakCmd;
    162   end else
    163   if ParseContinue(Block, ContinueCmd) then begin
    164     Result := True;
    165     Command := ContinueCmd;
    166   end else
    167     Result := False;
    168 end;
    169 
    170 function TParser.ParseProgram(SystemBlock: TBlock; out Prog: TProgram): Boolean;
    171 var
    172   Block: TBlock;
    173   Token: TToken;
    174 begin
    175   Result := False;
    176   Prog := TProgram.Create;
    177   Prog.SystemBlock.Free;
    178   Prog.SystemBlock := SystemBlock;
    179   if Tokenizer.CheckNext('program', tkKeyword) then begin
    180     Tokenizer.Expect('program', tkKeyword);
    181     Token := Tokenizer.GetNext;
    182     if Token.Kind = tkIdentifier then
    183       Prog.Name := Token.Text;
    184     Tokenizer.Expect(';', tkSpecialSymbol);
    185   end;
    186   if ParseBlock(SystemBlock, Block) then begin
    187     Result := True;
    188     Prog.Block.Free;
    189     Prog.Block := Block;
    190     Block.Parent := Prog;
    191     Tokenizer.Expect('.', tkSpecialSymbol);
    192   end else begin
    193     FreeAndNil(Prog);
    194     Error('Expected begin-end block.');
    195   end;
    196 end;
    197 
    198 function TParser.ParseBlock(ParentBlock: TBlock; out Block: TBlock; ExistingBlock: TBlock = nil): Boolean;
    199 var
    200   BeginEnd: TBeginEnd;
    201   Func: TFunction;
    202 begin
    203   Result := False;
    204   if Assigned(ExistingBlock) then Block := ExistingBlock
    205     else Block := TBlock.Create;
    206   Block.ParentBlock := ParentBlock;
    207   while True do begin
    208     if ParseBlockVar(Block) then begin
    209     end else
    210     if ParseBlockConst(Block) then begin
    211     end else
    212     if ParseFunction(Block, Func) then begin
    213       Block.Functions.Add(Func);
    214     end else begin
    215       Break;
    216     end;
    217   end;
    218   if ParseBeginEnd(Block, BeginEnd) then begin
    219     Result := True;
    220     Block.BeginEnd.Free;
    221     Block.BeginEnd := BeginEnd;
    222     BeginEnd.Parent := Block;
    223   end else begin
    224     if not Assigned(ExistingBlock) then Block.Free;
    225     Block := nil;
    226   end;
    227 end;
    228 
    229 function TParser.ParseBlockVar(Block: TBlock): Boolean;
    230 var
    231   Token: TToken;
    232   Variable: TVariable;
    233   TypeRef: TType;
    234 begin
    235   if Tokenizer.CheckNext('var', tkKeyword) then begin
    236     Result := True;
    237     Tokenizer.Expect('var', tkKeyword);
    238     while Tokenizer.CheckNextKind(tkIdentifier) do begin
    239       Token := Tokenizer.GetNext;
    240       if Token.Kind = tkIdentifier then begin
    241         Variable := Block.Variables.SearchByName(Token.Text);
    242         if not Assigned(Variable) then begin
    243           Variable := TVariable.Create;
    244           Variable.Name := Token.Text;
    245           Block.Variables.Add(Variable);
    246           Tokenizer.Expect(':', tkSpecialSymbol);
    247           Token := Tokenizer.GetNext;
    248           if Token.Kind = tkIdentifier then begin
    249             TypeRef := Block.GetType(Token.Text);
    250             if Assigned(TypeRef) then begin
    251               Variable.TypeRef := TypeRef;
    252             end else Error('Type ' + Token.Text + ' not found.');
    253           end;
    254         end else Error('Variable ' + Token.Text + ' redefined.');
    255         Tokenizer.Expect(';', tkSpecialSymbol);
    256       end else begin
    257         Error('Expected variable name but ' + Token.Text + ' found.');
    258         Break;
    259       end;
    260     end;
    261   end else Result := False;
    262 end;
    263 
    264 function TParser.ParseBlockConst(Block: TBlock): Boolean;
    265 var
    266   Token: TToken;
    267   Constant: TConstant;
    268   TypeRef: TType;
    269 begin
    270   if Tokenizer.CheckNext('const', tkKeyword) then begin
    271     Result := True;
    272     Tokenizer.Expect('const', tkKeyword);
    273     while Tokenizer.CheckNextKind(tkIdentifier) do begin
    274       Token := Tokenizer.GetNext;
    275       if Token.Kind = tkIdentifier then begin
    276         Constant := Block.Constants.SearchByName(Token.Text);
    277         if not Assigned(Constant) then begin
    278           Constant := TConstant.Create;
    279           Constant.Name := Token.Text;
    280           Block.Constants.Add(Constant);
    281           Tokenizer.Expect(':', tkSpecialSymbol);
    282           Token := Tokenizer.GetNext;
    283           if Token.Kind = tkIdentifier then begin
    284             TypeRef := Block.GetType(Token.Text);
    285             if Assigned(TypeRef) then begin
    286               Constant.TypeRef := TypeRef;
    287             end else Error('Type ' + Token.Text + ' not found.');
    288           end;
    289           Tokenizer.Expect('=', tkSpecialSymbol);
    290           Token := Tokenizer.GetNext;
    291           if Token.Kind = tkNumber then begin
    292             Constant.Value := TValueInteger.Create;
    293             TValueInteger(Constant.Value).Value := StrToInt(Token.Text);
    294           end else
    295           if Token.Kind = tkString then begin
    296             Constant.Value := TValueString.Create;
    297             TValueString(Constant.Value).Value := Token.Text;
    298           end else Error('Expected string or number.');
    299         end else Error('Constant ' + Token.Text + ' redefined.');
    300         Tokenizer.Expect(';', tkSpecialSymbol);
    301       end else begin
    302         Error('Expected constant name but ' + Token.Text + ' found.');
    303         Break;
    304       end;
    305     end;
    306   end else Result := False;
    307 end;
    308 
    309 function TParser.ParseFunction(Block: TBlock; out Func: TFunction): Boolean;
    310 var
    311   Token: TToken;
    312   FunctionParameter: TFunctionParameter;
    313   NewBlock: TBlock;
    314   TypeRef: TType;
    315   Variable: TVariable;
    316   I: Integer;
    317 begin
    318   Result := False;
    319   if Tokenizer.CheckNext('function', tkKeyword) then begin
    320     Tokenizer.Expect('function', tkKeyword);
    321     Result := True;
    322     Func := TFunction.Create;
    323     Token := Tokenizer.GetNext;
    324     if Token.Kind = tkIdentifier then begin
    325       Func.Name := Token.Text;
    326       if Tokenizer.CheckNext('(', tkSpecialSymbol) then begin
    327         Tokenizer.Expect('(', tkSpecialSymbol);
    328         while not Tokenizer.CheckNext(')', tkSpecialSymbol) do begin
    329           if Func.Params.Count > 0 then Tokenizer.Expect(',', tkSpecialSymbol);
    330           if ParseFunctionParameter(Block, FunctionParameter) then begin
    331             Func.Params.Add(FunctionParameter);
    332           end else Error('Expected function parameter.');
    333         end;
    334         Tokenizer.Expect(')', tkSpecialSymbol);
    335         for I := 0 to Func.Params.Count - 1 do begin
    336           Variable := TVariable.Create;
    337           Variable.Name := TFunctionParameter(Func.Params[I]).Name;
    338           Variable.TypeRef := TFunctionParameter(Func.Params[I]).TypeRef;
    339           Variable.Internal := True;
    340           Func.Block.Variables.Add(Variable);
    341         end;
    342       end;
    343       if Tokenizer.CheckNext(':', tkSpecialSymbol) then begin
    344         Tokenizer.Expect(':', tkSpecialSymbol);
    345         Token := Tokenizer.GetNext;
    346         if Token.Kind = tkIdentifier then begin
    347           TypeRef := Block.GetType(Token.Text);
    348           if Assigned(TypeRef) then begin
    349             Func.ResultType := TypeRef;
    350             Variable := TVariable.Create;
    351             Variable.Name := 'Result';
    352             Variable.TypeRef := TypeRef;
    353             Variable.Internal := True;
    354             Func.Block.Variables.Add(Variable);
    355           end else Error('Type ' + Token.Text + ' not found');
    356         end;
    357       end;
    358       Tokenizer.Expect(';', tkSpecialSymbol);
    359       if ParseBlock(Block, NewBlock, Func.Block) then begin
    360         Tokenizer.Expect(';', tkSpecialSymbol);
    361       end else Error('Expected function block');
    362     end else Error('Expected function name');
    363   end;
    364 end;
    365 
    366 function TParser.ParseFunctionParameter(Block: TBlock; out Parameter: TFunctionParameter
    367   ): Boolean;
    368 var
    369   Token: TToken;
    370   TypeRef: TType;
    371 begin
    372   Result := True;
    373   Token := Tokenizer.GetNext;
    374   if Token.Kind = tkIdentifier then begin
    375     Parameter := TFunctionParameter.Create;
    376     Parameter.Name := Token.Text;
    377     Tokenizer.Expect(':', tkSpecialSymbol);
    378     Token := Tokenizer.GetNext;
    379     if Token.Kind = tkIdentifier then begin
    380       TypeRef := Block.GetType(Token.Text);
    381       if Assigned(TypeRef) then begin
    382         Parameter.TypeRef := TypeRef;
    383       end else Error('Type ' + Token.Text + ' not found');
    384     end else Error('Expected parameter type');
    385   end else Error('Expected parameter name');
    386 end;
    387 
    388 function TParser.ParseAssignment(Block: TBlock; out Assignment: TAssignment): Boolean;
    389 var
    390   Token: TToken;
    391   Variable: TVariable;
    392   Expression: TExpression;
    393   LastPos: TTokenizerPos;
    394 begin
    395   LastPos := Tokenizer.Pos;
    396   Result := False;
    397   Token := Tokenizer.GetNext;
    398   if Token.Kind = tkIdentifier then begin
    399     Variable := Block.GetVariable(Token.Text);
    400     if Assigned(Variable) then begin
    401       Result := True;
    402       Assignment := TAssignment.Create;
    403       Assignment.Variable := Variable;
    404       Tokenizer.Expect(':=', tkSpecialSymbol);
    405       if ParseExpression(Block, Expression) then begin
    406         if Expression.GetType = Variable.TypeRef then begin
    407           Assignment.Expression.Free;
    408           Assignment.Expression := Expression;
    409           Expression.Parent := Assignment;
    410         end else begin
    411           Result := False;
    412           Error('Assignment type mismatch. Expected ' + Variable.TypeRef.Name + ' but got ' + Expression.GetType.Name);
    413         end;
    414       end;
    415       if not Result then Assignment.Free;
    416     end else Error('Variable ' + Token.Text + ' not defined.');
    417   end;
    418   if not Result then Tokenizer.Pos := LastPos;
    419 end;
    420 
    421 function TParser.ParseExpression(Block: TBlock; out Expression: TExpression
    422   ): Boolean;
    423 var
    424   ExpressionOperation: TExpressionOperation;
    425   ExpressionOperand: TExpressionOperand;
    426 begin
    427   Result := False;
    428   if ParseExpressionOperation(Block, ExpressionOperation) then begin
    429     Result := True;
    430     Expression := ExpressionOperation;
    431   end else
    432   if ParseExpressionOperand(Block, ExpressionOperand) then begin
    433     Result := True;
    434     Expression := ExpressionOperand;
    435   end;
    436 end;
    437 
    438 function TParser.ParseExpressionOperation(Block: TBlock; out
    439   ExpressionOperation: TExpressionOperation): Boolean;
    440 var
    441   Operand: TExpressionOperand;
    442   Token: TToken;
    443   Expression: TExpression;
    444   LastPos: TTokenizerPos;
    445   I: Integer;
    446   ExpectedType: TType;
    447 begin
    448   Result := False;
    449   LastPos := Tokenizer.Pos;
    450   if ParseExpressionOperand(Block, Operand) then begin
    451     Token := Tokenizer.GetNext;
    452     if (Token.Kind = tkSpecialSymbol) and Tokenizer.IsOperator(Token.Text) then begin
    453       Result := True;
    454       ExpressionOperation := TExpressionOperation.Create;
    455       ExpressionOperation.TypeRef := Operand.GetType;
    456       if Token.Text = '+' then ExpressionOperation.Operation := eoAdd
    457       else if Token.Text = '-' then ExpressionOperation.Operation := eoSub
    458       else if Token.Text = '=' then ExpressionOperation.Operation := eoEqual
    459       else if Token.Text = '<>' then ExpressionOperation.Operation := eoNotEqual
    460       else Error('Unsupported operator ' + Token.Text);
    461       ExpressionOperation.FunctionRef := ExpressionOperation.TypeRef.Functions.SearchByName(ExpressionOperation.GetFunctionName);
    462       if not Assigned(ExpressionOperation.FunctionRef.ResultType) then
    463         raise Exception.Create('Missing result type for function');
    464       ExpressionOperation.TypeRef := ExpressionOperation.FunctionRef.ResultType;
    465       ExpressionOperation.Items.Add(Operand);
    466       I := 1;
    467       if ParseExpression(Block, Expression) then begin
    468         ExpectedType := TFunctionParameter(ExpressionOperation.FunctionRef.Params[I]).TypeRef;
    469         if Expression.GetType = ExpectedType then
    470           ExpressionOperation.Items.Add(Expression)
    471           else Error('Expression operands needs to be same type. Expected ' + ExpectedType.Name + ' but found ' + Expression.GetType.Name);
    472       end else Error('Missing operand.');
    473     end else Operand.Free;
    474   end;
    475   if not Result then Tokenizer.Pos := LastPos;
    476 end;
    477 
    478 function TParser.ParseExpressionOperand(Block: TBlock; out
    479   ExpressionOperand: TExpressionOperand): Boolean;
    480 var
    481   Variable: TVariable;
    482   Constant: TConstant;
    483   FunctionCall: TFunctionCall;
    484 begin
    485   Result := False;
    486   if ParseFunctionCall(Block, FunctionCall) then begin
    487     Result := True;
    488     ExpressionOperand := TExpressionOperand.Create;
    489     ExpressionOperand.FunctionCall := FunctionCall;
    490     ExpressionOperand.OperandType := otFunctionCall;
    491   end else
    492   if ParseConstant(Block, Constant) then begin
    493     Result := True;
    494     ExpressionOperand := TExpressionOperand.Create;
    495     ExpressionOperand.ConstantDirect := Constant;
    496     ExpressionOperand.OperandType := otConstantDirect;
    497   end else
    498   if ParseConstantRef(Block, Constant) then begin
    499     Result := True;
    500     ExpressionOperand := TExpressionOperand.Create;
    501     ExpressionOperand.ConstantRef := Constant;
    502     ExpressionOperand.OperandType := otConstantRef;
    503   end else
    504   if ParseVariable(Block, Variable) then begin
    505     Result := True;
    506     ExpressionOperand := TExpressionOperand.Create;
    507     ExpressionOperand.VariableRef := Variable;
    508     ExpressionOperand.OperandType := otVariableRef;
    509   end else Error('Expected expression operand.');
    510 end;
    511 
    512 function TParser.ParseConstantRef(Block: TBlock; out ConstantRef: TConstant
    513   ): Boolean;
    514 var
    515   LastPos: TTokenizerPos;
    516   Token: TToken;
    517 begin
    518   Result := False;
    519   LastPos := Tokenizer.Pos;
    520   Token := Tokenizer.GetNext;
    521   if Token.Kind = tkIdentifier then begin;
    522     ConstantRef := Block.GetConstant(Token.Text);
    523     if Assigned(ConstantRef) then begin
    524       Result := True;
    525     end;
    526   end;
    527   if not Result then Tokenizer.Pos := LastPos;
    528 end;
    529 
    530 function TParser.ParseConstant(Block: TBlock; out ConstantRef: TConstant
    531   ): Boolean;
    532 var
    533   LastPos: TTokenizerPos;
    534   Token: TToken;
    535 begin
    536   Result := False;
    537   LastPos := Tokenizer.Pos;
    538   Token := Tokenizer.GetNext;
    539   if Token.Kind = tkNumber then begin
    540     Result := True;
    541     ConstantRef := TConstant.Create;
    542     ConstantRef.TypeRef := Block.GetType('Integer');
    543     ConstantRef.Value := TValueInteger.Create;
    544     TValueInteger(ConstantRef.Value).Value := StrToInt(Token.Text);
    545   end else
    546   if Token.Kind = tkString then begin
    547     Result := True;
    548     ConstantRef := TConstant.Create;
    549     ConstantRef.TypeRef := Block.GetType('string');
    550     ConstantRef.Value := TValueString.Create;
    551     TValueString(ConstantRef.Value).Value := Token.Text;
    552   end;
    553   if not Result then Tokenizer.Pos := LastPos;
    554 end;
    555 
    556 function TParser.ParseVariable(Block: TBlock; out VariableRef: TVariable
    557   ): Boolean;
    558 var
    559   LastPos: TTokenizerPos;
    560   Token: TToken;
    561 begin
    562   Result := False;
    563   LastPos := Tokenizer.Pos;
    564   Token := Tokenizer.GetNext;
    565   if Token.Kind = tkIdentifier then begin;
    566     VariableRef := Block.GetVariable(Token.Text);
    567     if Assigned(VariableRef) then begin
    568       Result := True;
    569     end;
    570   end;
    571   if not Result then Tokenizer.Pos := LastPos;
    572 end;
    573 
    574 function TParser.ParseIfThenElse(Block: TBlock; out IfThenElse: TIfThenElse
    575   ): Boolean;
    576 var
    577   Expression: TExpression;
    578   Command: TCommand;
    579 begin
    580   Result := False;
    581   if Tokenizer.CheckNext('if', tkKeyword) then begin
    582     Tokenizer.Expect('if', tkKeyword);
    583     Result := True;
    584     IfThenElse := TIfThenElse.Create;
    585     if ParseExpression(Block, Expression) then begin
    586       IfThenElse.Expression.Free;
    587       IfThenElse.Expression := Expression;
    588       Tokenizer.Expect('then', tkKeyword);
    589       if ParseCommand(Block, Command) then begin
    590         IfThenElse.CommandThen.Free;
    591         IfThenElse.CommandThen := Command;
    592         Command.Parent := IfThenElse;
    593         if Tokenizer.CheckNext('else', tkKeyword) then begin
    594           Tokenizer.Expect('else', tkKeyword);
    595           if ParseCommand(Block, Command) then begin
    596             IfThenElse.CommandElse.Free;
    597             IfThenElse.CommandElse := Command;
    598             Command.Parent := IfThenElse;
    599           end else Error('Expected command');
    600         end;
    601       end else Error('Expected command');
    602     end else Error('Expected expression');
    603   end;
    604 end;
    605 
    606 function TParser.ParseWhileDo(Block: TBlock; out WhileDo: TWhileDo): Boolean;
    607 var
    608   Expression: TExpression;
    609   Command: TCommand;
    610 begin
    611   Result := False;
    612   if Tokenizer.CheckNext('while', tkKeyword) then begin
    613     Tokenizer.Expect('while', tkKeyword);
    614     Result := True;
    615     WhileDo := TWhileDo.Create;
    616     if ParseExpression(Block, Expression) then begin
    617       WhileDo.Expression.Free;
    618       WhileDo.Expression := Expression;
    619       Tokenizer.Expect('do', tkKeyword);
    620       if ParseCommand(Block, Command) then begin
    621         WhileDo.Command.Free;
    622         WhileDo.Command := Command;
    623         Command.Parent := WhileDo;
    624       end else Error('Expected command');
    625     end else Error('Expected expression');
    626   end;
    627 end;
    628 
    629 function TParser.ParseRepeatUntil(Block: TBlock; out RepeatUntil: TRepeatUntil
    630   ): Boolean;
    631 var
    632   Expression: TExpression;
    633   Command: TCommand;
    634 begin
    635   Result := False;
    636   if Tokenizer.CheckNext('repeat', tkKeyword) then begin
    637     Tokenizer.Expect('repeat', tkKeyword);
    638     RepeatUntil := TRepeatUntil.Create;
    639     Result := True;
    640     while not Tokenizer.CheckNext('until', tkKeyword) do begin
    641       if ParseCommand(Block, Command) then begin
    642         RepeatUntil.Commands.Add(Command);
    643         Command.Parent := RepeatUntil;
    644         Tokenizer.Expect(';', tkSpecialSymbol);
    645       end else begin
    646         Error('Unexpected token ' + Tokenizer.GetNext.Text);
    647         Result := False;
    648         Break;
    649       end;
    650     end;
    651     Tokenizer.Expect('until', tkKeyword);
    652     if ParseExpression(Block, Expression) then begin
    653       RepeatUntil.Expression.Free;
    654       RepeatUntil.Expression := Expression;
    655     end else Error('Expected expression');
    656   end else Result := False;
    657 end;
    658 
    659 function TParser.ParseForToDo(Block: TBlock; out ForToDo: TForToDo): Boolean;
    660 var
    661   Expression: TExpression;
    662   VariableRef: TVariable;
    663   Command: TCommand;
    664 begin
    665   Result := False;
    666   if Tokenizer.CheckNext('for', tkKeyword) then begin
    667     Tokenizer.Expect('for', tkKeyword);
    668     Result := True;
    669     ForToDo := TForToDo.Create;
    670     if ParseVariable(Block, VariableRef) then begin
    671       ForToDo.VariableRef := VariableRef;
    672       Tokenizer.Expect(':=', tkSpecialSymbol);
    673       if ParseExpression(Block, Expression) then begin
    674         ForToDo.ExpressionFrom.Free;
    675         ForToDo.ExpressionFrom := Expression;
    676         Tokenizer.Expect('to', tkKeyword);
    677         if ParseExpression(Block, Expression) then begin
    678           ForToDo.ExpressionTo.Free;
    679           ForToDo.ExpressionTo := Expression;
    680           Tokenizer.Expect('do', tkKeyword);
    681           if ParseCommand(Block, Command) then begin
    682             ForToDo.Command.Free;
    683             ForToDo.Command := Command;
    684             Command.Parent := ForToDo;
    685           end else Error('Expected command.');
    686         end else Error('Expected expression.');
    687       end else Error('Expected expression.');
    688     end else Error('Expected control variable.');
    689   end;
    690 end;
    691 
    692 function TParser.ParseBreak(Block: TBlock; out BreakCmd: TBreak): Boolean;
    693 begin
    694   Result := False;
    695   if Tokenizer.CheckNext('break', tkKeyword) then begin
    696     Tokenizer.Expect('break', tkKeyword);
    697     Result := True;
    698     BreakCmd := TBreak.Create;
    699   end;
    700 end;
    701 
    702 function TParser.ParseContinue(Block: TBlock; out ContinueCmd: TContinue
    703   ): Boolean;
    704 begin
    705   Result := False;
    706   if Tokenizer.CheckNext('continue', tkKeyword) then begin
    707     Tokenizer.Expect('continue', tkKeyword);
    708     Result := True;
    709     ContinueCmd := TContinue.Create;
    710   end;
    711 end;
    71236
    71337procedure TParser.TokenizerError(Pos: TPoint; Text: string);
     
    807131end;
    808132
     133function TParser.ParseProgram(SystemBlock: TBlock; out Prog: TProgram): Boolean;
     134begin
     135end;
     136
    809137procedure TParser.Parse;
    810138var
     
    836164begin
    837165  Tokenizer.Free;
    838   inherited Destroy;
     166  inherited;
    839167end;
    840168
  • branches/interpreter2/USource.pas

    r213 r221  
    154154    function GetField(Index: Integer): TField; override;
    155155    procedure SetValue(Index: Integer; var Value); override;
     156    destructor Destroy; override;
    156157  end;
    157158
     
    484485destructor TReturn.Destroy;
    485486begin
    486   Expression.Free;
    487   inherited Destroy;
     487  FreeAndNil(Expression);
     488  inherited;
    488489end;
    489490
     
    530531destructor TSourceNodes.Destroy;
    531532begin
    532   List.Free;
    533   inherited Destroy;
     533  FreeAndNil(List);
     534  inherited;
    534535end;
    535536
     
    588589  else if Index = 1 then TypeRef := TType(Value)
    589590  else inherited;
     591end;
     592
     593destructor TConstant.Destroy;
     594begin
     595  FreeAndNil(Value);
     596  inherited;
    590597end;
    591598
     
    722729destructor TRepeatUntil.Destroy;
    723730begin
    724   Expression.Free;
    725   Commands.Free;
    726   inherited Destroy;
     731  FreeAndNil(Expression);
     732  FreeAndNil(Commands);
     733  inherited;
    727734end;
    728735
     
    801808destructor TForToDo.Destroy;
    802809begin
    803   Command.Free;
    804   ExpressionTo.Free;
    805   ExpressionFrom.Free;
    806   inherited Destroy;
     810  FreeAndNil(Command);
     811  FreeAndNil(ExpressionTo);
     812  FreeAndNil(ExpressionFrom);
     813  inherited;
    807814end;
    808815
     
    868875destructor TExpressionOperand.Destroy;
    869876begin
    870   if Assigned(ConstantDirect) then ConstantDirect.Free;
     877  if Assigned(ConstantDirect) then FreeAndNil(ConstantDirect);
     878  if Assigned(FunctionCall) then FreeAndNil(FunctionCall);
    871879end;
    872880
     
    933941destructor TFunction.Destroy;
    934942begin
    935   Block.Free;
    936   Params.Free;
    937   inherited Destroy;
     943  FreeAndNil(Block);
     944  FreeAndNil(Params);
     945  inherited;
    938946end;
    939947
     
    971979destructor TType.Destroy;
    972980begin
    973   Functions.Free;
    974   inherited Destroy;
     981  FreeAndNil(Functions);
     982  inherited;
    975983end;
    976984
     
    10331041destructor TExpressionOperation.Destroy;
    10341042begin
    1035   Items.Free;
    1036   inherited Destroy;
     1043  FreeAndNil(Items);
     1044  inherited;
    10371045end;
    10381046
     
    10791087begin
    10801088  Variable := nil;
    1081   Expression.Free;
    1082   inherited Destroy;
     1089  FreeAndNil(Expression);
     1090  inherited;
    10831091end;
    10841092
     
    11231131destructor TIfThenElse.Destroy;
    11241132begin
    1125   Expression.Free;
    1126   CommandThen.Free;
    1127   CommandElse.Free;
    1128   inherited Destroy;
     1133  FreeAndNil(Expression);
     1134  FreeAndNil(CommandThen);
     1135  FreeAndNil(CommandElse);
     1136  inherited;
    11291137end;
    11301138
     
    11651173destructor TWhileDo.Destroy;
    11661174begin
    1167   Expression.Free;
    1168   Command.Free;
    1169   inherited Destroy;
     1175  FreeAndNil(Expression);
     1176  FreeAndNil(Command);
     1177  inherited;
    11701178end;
    11711179
     
    12051213destructor TFunctionCall.Destroy;
    12061214begin
    1207   Params.Free;
    1208   inherited Destroy;
     1215  FreeAndNil(Params);
     1216  inherited;
    12091217end;
    12101218
     
    13491357destructor TBlock.Destroy;
    13501358begin
    1351   BeginEnd.Free;
    1352   Types.Free;
    1353   Variables.Free;
    1354   Constants.Free;
    1355   Functions.Free;
    1356   inherited Destroy;
     1359  FreeAndNil(BeginEnd);
     1360  FreeAndNil(Types);
     1361  FreeAndNil(Variables);
     1362  FreeAndNil(Constants);
     1363  FreeAndNil(Functions);
     1364  inherited;
    13571365end;
    13581366
     
    13941402destructor TBeginEnd.Destroy;
    13951403begin
    1396   Commands.Free;
    1397   inherited Destroy;
     1404  FreeAndNil(Commands);
     1405  inherited;
    13981406end;
    13991407
     
    14391447destructor TProgram.Destroy;
    14401448begin
    1441   Block.Free;
    1442   SystemBlock.Free;
    1443   inherited Destroy;
     1449  FreeAndNil(Block);
     1450  FreeAndNil(SystemBlock);
     1451  inherited;
    14441452end;
    14451453
  • branches/interpreter2/interpreter.lpi

    r211 r221  
    2525          <SearchPaths>
    2626            <IncludeFiles Value="$(ProjOutDir)"/>
    27             <OtherUnitFiles Value="Forms"/>
     27            <OtherUnitFiles Value="Forms;Generators;Parsers"/>
    2828            <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)-$(BuildMode)"/>
    2929          </SearchPaths>
     
    7272      </Item2>
    7373    </RequiredPackages>
    74     <Units Count="16">
     74    <Units Count="17">
    7575      <Unit0>
    7676        <Filename Value="interpreter.lpr"/>
     
    9898      </Unit5>
    9999      <Unit6>
    100         <Filename Value="UGeneratorPascal.pas"/>
     100        <Filename Value="UGenerator.pas"/>
    101101        <IsPartOfProject Value="True"/>
    102102      </Unit6>
    103103      <Unit7>
    104         <Filename Value="UGeneratorPhp.pas"/>
    105         <IsPartOfProject Value="True"/>
     104        <Filename Value="Forms/UFormMessages.pas"/>
     105        <IsPartOfProject Value="True"/>
     106        <ComponentName Value="FormMessages"/>
     107        <HasResources Value="True"/>
     108        <ResourceBaseClass Value="Form"/>
    106109      </Unit7>
    107110      <Unit8>
    108         <Filename Value="UGenerator.pas"/>
    109         <IsPartOfProject Value="True"/>
     111        <Filename Value="Forms/UFormSource.pas"/>
     112        <IsPartOfProject Value="True"/>
     113        <ComponentName Value="FormSource"/>
     114        <HasResources Value="True"/>
     115        <ResourceBaseClass Value="Form"/>
    110116      </Unit8>
    111117      <Unit9>
    112         <Filename Value="UGeneratorCSharp.pas"/>
     118        <Filename Value="UOptimizer.pas"/>
    113119        <IsPartOfProject Value="True"/>
    114120      </Unit9>
    115121      <Unit10>
    116         <Filename Value="Forms/UFormMessages.pas"/>
    117         <IsPartOfProject Value="True"/>
    118         <ComponentName Value="FormMessages"/>
     122        <Filename Value="Forms/UFormOutput.pas"/>
     123        <IsPartOfProject Value="True"/>
     124        <ComponentName Value="FormOutput"/>
    119125        <HasResources Value="True"/>
    120126        <ResourceBaseClass Value="Form"/>
    121127      </Unit10>
    122128      <Unit11>
    123         <Filename Value="Forms/UFormSource.pas"/>
    124         <IsPartOfProject Value="True"/>
    125         <ComponentName Value="FormSource"/>
     129        <Filename Value="Forms/UFormMain.pas"/>
     130        <IsPartOfProject Value="True"/>
     131        <ComponentName Value="FormMain"/>
    126132        <HasResources Value="True"/>
    127133        <ResourceBaseClass Value="Form"/>
    128134      </Unit11>
    129135      <Unit12>
    130         <Filename Value="UOptimizer.pas"/>
     136        <Filename Value="Generators/UGeneratorCSharp.pas"/>
    131137        <IsPartOfProject Value="True"/>
    132138      </Unit12>
    133139      <Unit13>
    134         <Filename Value="UGeneratorXml.pas"/>
     140        <Filename Value="Generators/UGeneratorPascal.pas"/>
    135141        <IsPartOfProject Value="True"/>
    136142      </Unit13>
    137143      <Unit14>
    138         <Filename Value="Forms/UFormOutput.pas"/>
    139         <IsPartOfProject Value="True"/>
    140         <ComponentName Value="FormOutput"/>
    141         <HasResources Value="True"/>
    142         <ResourceBaseClass Value="Form"/>
     144        <Filename Value="Generators/UGeneratorPhp.pas"/>
     145        <IsPartOfProject Value="True"/>
    143146      </Unit14>
    144147      <Unit15>
    145         <Filename Value="Forms/UFormMain.pas"/>
    146         <IsPartOfProject Value="True"/>
    147         <ComponentName Value="FormMain"/>
    148         <HasResources Value="True"/>
    149         <ResourceBaseClass Value="Form"/>
     148        <Filename Value="Generators/UGeneratorXml.pas"/>
     149        <IsPartOfProject Value="True"/>
    150150      </Unit15>
     151      <Unit16>
     152        <Filename Value="Parsers/UParserPascal.pas"/>
     153        <IsPartOfProject Value="True"/>
     154      </Unit16>
    151155    </Units>
    152156  </ProjectOptions>
     
    158162    <SearchPaths>
    159163      <IncludeFiles Value="$(ProjOutDir)"/>
    160       <OtherUnitFiles Value="Forms"/>
     164      <OtherUnitFiles Value="Forms;Generators;Parsers"/>
    161165      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)-$(BuildMode)"/>
    162166    </SearchPaths>
  • branches/interpreter2/interpreter.lpr

    r209 r221  
    99  Interfaces, SysUtils, // this includes the LCL widgetset
    1010  Forms, UParser, UTokenizer, USource, UExecutor, UInterpreter,
    11   UGeneratorPascal, UGeneratorPhp, UGenerator, UGeneratorCSharp, UFormMessages,
    12   UFormSource, UOptimizer, UGeneratorXml, UFormOutput, UFormMain
     11  UGenerator, UFormMessages,
     12  UFormSource, UOptimizer, UFormOutput, UFormMain, UParserPascal
    1313  { you can add units after this };
    1414
Note: See TracChangeset for help on using the changeset viewer.