Changeset 202


Ignore:
Timestamp:
Apr 17, 2020, 12:09:15 AM (5 years ago)
Author:
chronos
Message:
  • Added: Support for String, Integer and Boolean types.
  • Added: Support for more system defined functions..
  • Added: Support for line comments.
  • Added: For-To-Do construction.
  • Added: Defined function parameters and and parsing function calls with parameters.
  • Modified: Improved handling of expressions.
Location:
branches/interpreter2
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • branches/interpreter2/Test.pas

    r200 r202  
     1// Line comment
    12program Test;
    23var
    3   A;
    4   B;
     4  A: string;
     5  B: string;
     6  X: string;
     7  I: Integer;
    58const
    6   C = 1;
     9  C: Integer = 1;
    710begin 
    8   A := 2;
    9   B := C;
     11  X := 'A' + 'B';
     12  WriteLn(X);
     13  A := IntToStr(2);
     14  B := IntToStr(C);
    1015  A := B;
    11   if A then begin
     16 
     17  // If-Then-Else
     18  if A = '2' then begin
    1219    WriteLn('DoThen');
    1320  end else WriteLn('DoElse');
    1421
    15   A := '';
    16   while A do begin
    17     WriteLn(A);
     22  // While-Do
     23  I := 5;
     24  while I <> 0 do begin
     25    WriteLn(IntToStr(I));
     26    I := I - 1;
     27  end;
     28 
     29  // For-To-Do
     30  for I := 0 to 5 do begin
     31    WriteLn(IntToStr(I));   
    1832  end;
    1933   
     34  // Begin-End
    2035  begin
    2136    WriteLn('Hello World!');
  • branches/interpreter2/UExecutor.pas

    r201 r202  
    99
    1010type
     11  TExecutorFunctions = class;
     12
    1113  TExecutorVariable = class
    1214    Variable: TVariable;
    13     Value: string;
     15    Value: TValue;
    1416  end;
    1517
     
    2123  end;
    2224
    23   TExecutorFunctionCallback = function(Params: array of string): string of object;
     25  { TExecutorType }
     26
     27  TExecutorType = class
     28    TypeRef: TType;
     29    Functions: TExecutorFunctions;
     30    constructor Create;
     31    destructor Destroy; override;
     32  end;
     33
     34  { TExecutorTypes }
     35
     36  TExecutorTypes = class(TObjectList)
     37    function SearchByType(TypeRef: TType): TExecutorType;
     38    function AddNew(TypeRef: TType): TExecutorType;
     39  end;
     40
     41  TExecutorFunctionCallback = function(Params: array of TValue): TValue of object;
    2442
    2543  TExecutorFunction = class
     
    3957  TExecutorBlock = class
    4058    Parent: TExecutorBlock;
     59    Types: TExecutorTypes;
    4160    Variables: TExecutorVariables;
    4261    Functions: TExecutorFunctions;
    4362    function GetFunction(FunctionDef: TFunction): TExecutorFunction;
     63    function GetType(TypeDef: TType): TExecutorType;
     64    function GetVariable(Variable: TVariable): TExecutorVariable;
     65    function GetTypeFunction(TypeDef: TType; FunctionDef: TFunction): TExecutorFunction; overload;
     66    function GetTypeFunction(TypeDef: TType; FunctionName: string): TExecutorFunction; overload;
    4467    constructor Create;
    4568    destructor Destroy; override;
     
    5477    FOnOutput: TOutputEvent;
    5578    SystemBlock: TExecutorBlock;
    56     function ExecuteWriteLn(Params: array of string): string;
    57     function ExecuteWrite(Params: array of string): string;
     79    function ExecuteWriteLn(Params: array of TValue): TValue;
     80    function ExecuteWrite(Params: array of TValue): TValue;
     81    function ExecuteIntToStr(Params: array of TValue): TValue;
     82    function ExecuteStrToInt(Params: array of TValue): TValue;
     83    function ExecuteStringAssign(Params: array of TValue): TValue;
     84    function ExecuteStringAdd(Params: array of TValue): TValue;
     85    function ExecuteStringEqual(Params: array of TValue): TValue;
     86    function ExecuteStringNotEqual(Params: array of TValue): TValue;
     87    function ExecuteIntegerAssign(Params: array of TValue): TValue;
     88    function ExecuteIntegerAdd(Params: array of TValue): TValue;
     89    function ExecuteIntegerSub(Params: array of TValue): TValue;
     90    function ExecuteIntegerEqual(Params: array of TValue): TValue;
     91    function ExecuteIntegerNotEqual(Params: array of TValue): TValue;
    5892    procedure InitExecutorBlock(ExecutorBlock: TExecutorBlock; Block: TBlock);
    5993  public
     
    6498    procedure ExecuteIfThenElse(Block: TExecutorBlock; IfThenElse: TIfThenElse);
    6599    procedure ExecuteWhileDo(Block: TExecutorBlock; WhileDo: TWhileDo);
     100    procedure ExecuteForToDo(Block: TExecutorBlock; ForToDo: TForToDo);
    66101    procedure ExecuteBlock(ParentBlock: TExecutorBlock;Block: TBlock);
    67     function ExecuteFunctionCall(Block: TExecutorBlock; FunctionCall: TFunctionCall): string;
     102    function ExecuteFunctionCall(Block: TExecutorBlock; FunctionCall: TFunctionCall): TValue;
    68103    procedure ExecuteAssignment(Block: TExecutorBlock; Assignment: TAssignment);
    69     function ExecuteExpression(Block: TExecutorBlock; Expression: TExpression): string;
     104    function ExecuteExpression(Block: TExecutorBlock; Expression: TExpression): TValue;
     105    function ExecuteExpressionOperation(Block: TExecutorBlock; Expression: TExpressionOperation): TValue;
     106    function ExecuteExpressionOperand(Block: TExecutorBlock; Expression: TExpressionOperand): TValue;
    70107    procedure Run;
    71108    procedure Output(Text: string);
     
    75112
    76113implementation
     114
     115{ TExecutorType }
     116
     117constructor TExecutorType.Create;
     118begin
     119  Functions := TExecutorFunctions.Create;
     120end;
     121
     122destructor TExecutorType.Destroy;
     123begin
     124  Functions.Free;
     125  inherited Destroy;
     126end;
     127
     128{ TExecutorTypes }
     129
     130function TExecutorTypes.SearchByType(TypeRef: TType): TExecutorType;
     131var
     132  I: Integer;
     133begin
     134  I := 0;
     135  while (I < Count) and (TExecutorType(Items[I]).TypeRef <> TypeRef) do Inc(I);
     136  if I < Count then Result := TExecutorType(Items[I])
     137    else Result := nil;
     138end;
     139
     140function TExecutorTypes.AddNew(TypeRef: TType): TExecutorType;
     141begin
     142  Result := TExecutorType.Create;
     143  Result.TypeRef := TypeRef;
     144  Add(Result);
     145end;
    77146
    78147{ TExecutorFunctions }
     
    124193end;
    125194
     195function TExecutorBlock.GetType(TypeDef: TType): TExecutorType;
     196begin
     197  Result := Types.SearchByType(TypeDef);
     198  if not Assigned(Result) and Assigned(Parent) then
     199    Result := Parent.GetType(TypeDef);
     200end;
     201
     202function TExecutorBlock.GetVariable(Variable: TVariable): TExecutorVariable;
     203begin
     204  Result := Variables.SearchByVariable(Variable);
     205  if not Assigned(Result) and Assigned(Parent) then
     206    Result := Parent.GetVariable(Variable);
     207end;
     208
     209function TExecutorBlock.GetTypeFunction(TypeDef: TType; FunctionDef: TFunction
     210  ): TExecutorFunction;
     211var
     212  ExecutorType: TExecutorType;
     213begin
     214  ExecutorType := GetType(TypeDef);
     215  Result := ExecutorType.Functions.SearchByFunction(FunctionDef);
     216end;
     217
     218function TExecutorBlock.GetTypeFunction(TypeDef: TType; FunctionName: string
     219  ): TExecutorFunction;
     220begin
     221  Result := GetTypeFunction(TypeDef, TypeDef.Functions.SearchByName(FunctionName));
     222end;
     223
    126224constructor TExecutorBlock.Create;
    127225begin
     226  Types := TExecutorTypes.Create;
    128227  Variables := TExecutorVariables.Create;
    129228  Functions := TExecutorFunctions.Create;
     
    134233  Variables.Free;
    135234  Functions.Free;
     235  Types.Free;
    136236  inherited Destroy;
    137237end;
     
    139239{ TExecutor }
    140240
    141 function TExecutor.ExecuteWriteLn(Params: array of string): string;
     241function TExecutor.ExecuteWriteLn(Params: array of TValue): TValue;
    142242var
    143243  I: Integer;
    144244  Text: string;
    145245begin
    146   Result := '';
     246  Result := nil;
    147247  Text := '';
    148248  for I := 0 to Length(Params) - 1 do
    149     Text := Text + Params[I];
     249    Text := Text + TValueString(Params[I]).Value;
    150250  Output(Text + LineEnding);
    151251end;
    152252
    153 function TExecutor.ExecuteWrite(Params: array of string): string;
     253function TExecutor.ExecuteWrite(Params: array of TValue): TValue;
    154254var
    155255  I: Integer;
    156256  Text: string;
    157257begin
    158   Result := '';
     258  Result := nil;
    159259  Text := '';
    160260  for I := 0 to Length(Params) - 1 do
    161     Text := Text + Params[I];
     261    Text := Text + TValueString(Params[I]).Value;
    162262  Output(Text);
    163263end;
    164264
     265function TExecutor.ExecuteIntToStr(Params: array of TValue): TValue;
     266begin
     267  Result := TValueString.Create;
     268  TValueString(Result).Value := IntToStr(TValueInteger(Params[0]).Value);
     269end;
     270
     271function TExecutor.ExecuteStrToInt(Params: array of TValue): TValue;
     272begin
     273  Result := TValueInteger.Create;
     274  TValueInteger(Result).Value := StrToInt(TValueString(Params[0]).Value);
     275end;
     276
     277function TExecutor.ExecuteStringAssign(Params: array of TValue): TValue;
     278begin
     279  Result := TValueString.Create;
     280  TValueString(Result).Value := TValueString(Params[0]).Value;
     281end;
     282
     283function TExecutor.ExecuteStringAdd(Params: array of TValue): TValue;
     284begin
     285  Result := TValueString.Create;
     286  TValueString(Result).Value := TValueString(Params[0]).Value + TValueString(Params[1]).Value;
     287end;
     288
     289function TExecutor.ExecuteStringEqual(Params: array of TValue): TValue;
     290begin
     291  Result := TValueBoolean.Create;
     292  TValueBoolean(Result).Value := TValueString(Params[0]).Value = TValueString(Params[1]).Value;
     293end;
     294
     295function TExecutor.ExecuteStringNotEqual(Params: array of TValue): TValue;
     296begin
     297  Result := TValueBoolean.Create;
     298  TValueBoolean(Result).Value := TValueString(Params[0]).Value <> TValueString(Params[1]).Value;
     299end;
     300
     301function TExecutor.ExecuteIntegerAssign(Params: array of TValue): TValue;
     302begin
     303  Result := TValueInteger.Create;
     304  TValueInteger(Result).Value := TValueInteger(Params[0]).Value;
     305end;
     306
     307function TExecutor.ExecuteIntegerAdd(Params: array of TValue): TValue;
     308begin
     309  Result := TValueInteger.Create;
     310  TValueInteger(Result).Value := TValueInteger(Params[0]).Value + TValueInteger(Params[1]).Value;
     311end;
     312
     313function TExecutor.ExecuteIntegerSub(Params: array of TValue): TValue;
     314begin
     315  Result := TValueInteger.Create;
     316  TValueInteger(Result).Value := TValueInteger(Params[0]).Value - TValueInteger(Params[1]).Value;
     317end;
     318
     319function TExecutor.ExecuteIntegerEqual(Params: array of TValue): TValue;
     320begin
     321  Result := TValueBoolean.Create;
     322  TValueBoolean(Result).Value := TValueInteger(Params[0]).Value = TValueInteger(Params[1]).Value;
     323end;
     324
     325function TExecutor.ExecuteIntegerNotEqual(Params: array of TValue): TValue;
     326begin
     327  Result := TValueBoolean.Create;
     328  TValueBoolean(Result).Value := TValueInteger(Params[0]).Value <> TValueInteger(Params[1]).Value;
     329end;
     330
    165331procedure TExecutor.InitExecutorBlock(ExecutorBlock: TExecutorBlock; Block: TBlock);
    166332var
    167333  I: Integer;
     334  J: Integer;
    168335  ExecutorFunction: TExecutorFunction;
    169 begin
     336  ExecutorType: TExecutorType;
     337begin
     338  for I := 0 to Block.Types.Count - 1 do begin
     339    ExecutorType := ExecutorBlock.Types.AddNew(TType(Block.Types[I]));
     340    for J := 0 to ExecutorType.TypeRef.Functions.Count - 1 do begin
     341      ExecutorFunction := ExecutorType.Functions.AddNew(TFunction(ExecutorType.TypeRef.Functions[J]));
     342      if ExecutorType.TypeRef.Name = 'string' then begin
     343        if ExecutorFunction.FunctionDef.Name = '_Assign' then begin
     344          ExecutorFunction.Callback := ExecuteStringAssign;
     345        end else
     346        if ExecutorFunction.FunctionDef.Name = '_Add' then begin
     347          ExecutorFunction.Callback := ExecuteStringAdd;
     348        end else
     349        if ExecutorFunction.FunctionDef.Name = '_Equal' then begin
     350          ExecutorFunction.Callback := ExecuteStringEqual;
     351        end;
     352        if ExecutorFunction.FunctionDef.Name = '_NotEqual' then begin
     353          ExecutorFunction.Callback := ExecuteStringNotEqual;
     354        end;
     355      end;
     356      if ExecutorType.TypeRef.Name = 'Integer' then begin
     357        if ExecutorFunction.FunctionDef.Name = '_Assign' then begin
     358          ExecutorFunction.Callback := ExecuteIntegerAssign;
     359        end else
     360        if ExecutorFunction.FunctionDef.Name = '_Add' then begin
     361          ExecutorFunction.Callback := ExecuteIntegerAdd;
     362        end else
     363        if ExecutorFunction.FunctionDef.Name = '_Sub' then begin
     364          ExecutorFunction.Callback := ExecuteIntegerSub;
     365        end else
     366        if ExecutorFunction.FunctionDef.Name = '_Equal' then begin
     367          ExecutorFunction.Callback := ExecuteIntegerEqual;
     368        end else
     369        if ExecutorFunction.FunctionDef.Name = '_NotEqual' then begin
     370          ExecutorFunction.Callback := ExecuteIntegerNotEqual;
     371        end;
     372      end;
     373    end;
     374  end;
    170375  for I := 0 to Block.Variables.Count - 1 do
    171376    ExecutorBlock.Variables.AddNew(TVariable(Block.Variables[I]));
    172377  for I := 0 to Block.Functions.Count - 1 do begin
    173378    ExecutorFunction := ExecutorBlock.Functions.AddNew(TFunction(Block.Functions[I]));
    174     if ExecutorFunction.FunctionDef.Name = 'Write' then ExecutorFunction.Callback := ExecuteWrite
    175     else if ExecutorFunction.FunctionDef.Name = 'WriteLn' then ExecutorFunction.Callback := ExecuteWriteLn;
     379    if ExecutorFunction.FunctionDef.Name = 'Write' then begin
     380      ExecutorFunction.Callback := ExecuteWrite;
     381    end else
     382    if ExecutorFunction.FunctionDef.Name = 'WriteLn' then begin
     383      ExecutorFunction.Callback := ExecuteWriteLn;
     384    end;
     385    if ExecutorFunction.FunctionDef.Name = 'IntToStr' then begin
     386      ExecutorFunction.Callback := ExecuteIntToStr;
     387    end else
     388    if ExecutorFunction.FunctionDef.Name = 'StrToInt' then begin
     389      ExecutorFunction.Callback := ExecuteStrToInt;
     390    end;
    176391  end;
    177392end;
     
    200415  else if Command is TIfThenElse then ExecuteIfThenElse(Block, TIfThenElse(Command))
    201416  else if Command is TWhileDo then ExecuteWhileDo(Block, TWhileDo(Command))
     417  else if Command is TForToDo then ExecuteForToDo(Block, TForToDo(Command))
    202418  else raise Exception.Create('Unsupported command type');
    203419end;
     
    206422  IfThenElse: TIfThenElse);
    207423var
    208   Value: string;
     424  Value: TValue;
    209425begin
    210426  Value := ExecuteExpression(Block, IfThenElse.Expression);
    211   if Value <> '' then ExecuteCommand(Block, IfThenElse.CommandThen)
    212     else ExecuteCommand(Block, IfThenElse.CommandElse);
     427  if Value is TValueBoolean then begin
     428    if TValueBoolean(Value).Value then ExecuteCommand(Block, IfThenElse.CommandThen)
     429      else ExecuteCommand(Block, IfThenElse.CommandElse);
     430  end else raise Exception.Create('Expected boolean value.');
    213431end;
    214432
    215433procedure TExecutor.ExecuteWhileDo(Block: TExecutorBlock; WhileDo: TWhileDo);
    216434var
    217   Value: string;
     435  Value: TValue;
    218436begin
    219437  while True do begin
    220438    Value := ExecuteExpression(Block, WhileDo.Expression);
    221     if Value <> '' then Continue
    222       else Break;
     439    if Value is TValueBoolean then begin
     440      if not TValueBoolean(Value).Value then Break;
     441      ExecuteCommand(Block, WhileDo.Command);
     442    end else raise Exception.Create('Expected boolean value.');
     443  end;
     444end;
     445
     446procedure TExecutor.ExecuteForToDo(Block: TExecutorBlock; ForToDo: TForToDo);
     447var
     448  Value: TValue;
     449  Variable: TExecutorVariable;
     450  Limit: TValue;
     451begin
     452  Variable := Block.GetVariable(ForToDo.VariableRef);
     453  Variable.Value := ExecuteExpression(Block, ForToDo.ExpressionFrom);
     454  Limit := ExecuteExpression(Block, ForToDo.ExpressionTo);
     455  while True do begin
     456    ExecuteCommand(Block, ForToDo.Command);
     457    TValueInteger(Variable.Value).Value := TValueInteger(Variable.Value).Value + 1;
     458    if TValueInteger(Variable.Value).Value > TValueInteger(Limit).Value then Break;
    223459  end;
    224460end;
     
    236472
    237473function TExecutor.ExecuteFunctionCall(Block: TExecutorBlock;
    238   FunctionCall: TFunctionCall): string;
     474  FunctionCall: TFunctionCall): TValue;
    239475var
    240476  ExecutorFunction: TExecutorFunction;
    241   Params: array of string;
    242   I: Integer;
    243 begin
    244   Result := '';
     477  Params: array of TValue;
     478  I: Integer;
     479begin
     480  Result := nil;
    245481  ExecutorFunction := Block.GetFunction(FunctionCall.FunctionDef);
    246482  if Assigned(ExecutorFunction) then begin
    247483    SetLength(Params, FunctionCall.Params.Count);
    248     for I := 0 to FunctionCall.Params.Count - 1 do
     484    for I := 0 to FunctionCall.Params.Count - 1 do begin
    249485      Params[I] := ExecuteExpression(Block, TExpression(FunctionCall.Params[0]));
     486    end;
    250487    Result := ExecutorFunction.Callback(Params);
    251488  end else raise Exception.Create('No executor for ' + FunctionCall.FunctionDef.Name + ' function.');
     
    255492  Assignment: TAssignment);
    256493var
    257   Value: string;
     494  Value: TValue;
    258495  Variable: TExecutorVariable;
     496  ExecutorFunction: TExecutorFunction;
     497  Params: array of TValue;
    259498begin
    260499  Value := ExecuteExpression(Block, Assignment.Expression);
    261   Variable := Block.Variables.SearchByVariable(Assignment.Variable);
    262   Variable.Value := Value;
     500  Variable := Block.GetVariable(Assignment.Variable);
     501  ExecutorFunction := Block.GetTypeFunction(Assignment.Variable.TypeRef, '_Assign');
     502  if Assignment.Variable.TypeRef = Assignment.Expression.GetType then begin;
     503    SetLength(Params, 1);
     504    Params[0] := Value;
     505    Variable.Value := ExecutorFunction.Callback(Params);
     506  end else raise Exception('Assignment result type is ' + Variable.Variable.TypeRef.Name +
     507    ' but value is ' + Assignment.Expression.GetType.Name + '.');
    263508end;
    264509
    265510function TExecutor.ExecuteExpression(Block: TExecutorBlock;
    266   Expression: TExpression): string;
     511  Expression: TExpression): TValue;
     512begin
     513  if Expression is TExpressionOperation then
     514    Result := ExecuteExpressionOperation(Block, TExpressionOperation(Expression))
     515  else
     516  if Expression is TExpressionOperand then
     517    Result := ExecuteExpressionOperand(Block, TExpressionOperand(Expression))
     518  else raise Exception.Create('Unknown expression class.');
     519end;
     520
     521function TExecutor.ExecuteExpressionOperation(Block: TExecutorBlock;
     522  Expression: TExpressionOperation): TValue;
     523var
     524  I: Integer;
     525  Value: TValue;
     526  ExecutorFunction: TExecutorFunction;
     527  Params: array of TValue;
     528  FuncName: string;
     529begin
     530  if Expression.Operation = eoAdd then FuncName := '_Add'
     531  else if Expression.Operation = eoSub then FuncName := '_Sub'
     532  else if Expression.Operation = eoEqual then FuncName := '_Equal'
     533  else if Expression.Operation = eoNotEqual then FuncName := '_NotEqual'
     534  else raise Exception.Create('Unsupported operation type.');
     535
     536  ExecutorFunction := Block.GetTypeFunction(Expression.TypeRef, FuncName);
     537  Result := Expression.TypeRef.ValueClass.Create;
     538
     539  SetLength(Params, Expression.Items.Count);
     540  for I := 0 to Expression.Items.Count - 1 do begin
     541    Value := ExecuteExpression(Block, TExpression(Expression.Items[I]));
     542    Params[I] := Value;
     543  end;
     544  Result := ExecutorFunction.Callback(Params);
     545end;
     546
     547function TExecutor.ExecuteExpressionOperand(Block: TExecutorBlock;
     548  Expression: TExpressionOperand): TValue;
    267549begin
    268550  if Assigned(Expression.VariableRef) then begin
     
    274556  if Assigned(Expression.FunctionCall) then begin
    275557    Result := ExecuteFunctionCall(Block, Expression.FunctionCall);
    276   end;
     558  end else raise Exception.Create('Unsupported exception operand type.');
    277559end;
    278560
  • branches/interpreter2/UFormMain.lfm

    r201 r202  
    1313  OnShow = FormShow
    1414  LCLVersion = '2.0.2.0'
    15   object MemoSource: TMemo
    16     Left = 24
    17     Height = 672
    18     Top = 64
    19     Width = 671
    20     Font.Name = 'Liberation Mono'
    21     ParentFont = False
    22     ScrollBars = ssAutoBoth
    23     TabOrder = 0
    24   end
    2515  object MemoLog: TMemo
    2616    Left = 24
     
    3020    ReadOnly = True
    3121    ScrollBars = ssAutoBoth
    32     TabOrder = 1
     22    TabOrder = 0
    3323  end
    3424  object MemoOutput: TMemo
     
    4030    ParentFont = False
    4131    ScrollBars = ssAutoBoth
    42     TabOrder = 2
     32    TabOrder = 1
    4333  end
    4434  object ButtonCompile: TButton
     
    4939    Caption = 'Compile'
    5040    OnClick = ButtonCompileClick
    51     TabOrder = 3
     41    TabOrder = 2
    5242  end
    5343  object Label1: TLabel
     
    7464    Caption = 'Run'
    7565    OnClick = ButtonRunClick
     66    TabOrder = 3
     67  end
     68  inline SynEditSource: TSynEdit
     69    Left = 24
     70    Height = 673
     71    Top = 64
     72    Width = 672
     73    Font.Height = -20
     74    Font.Name = 'Liberation Mono'
     75    Font.Pitch = fpFixed
     76    Font.Quality = fqNonAntialiased
     77    ParentColor = False
     78    ParentFont = False
    7679    TabOrder = 4
     80    Gutter.Width = 85
     81    Gutter.MouseActions = <>
     82    RightGutter.Width = 0
     83    RightGutter.MouseActions = <>
     84    Highlighter = SynFreePascalSyn1
     85    Keystrokes = <   
     86      item
     87        Command = ecUp
     88        ShortCut = 38
     89      end   
     90      item
     91        Command = ecSelUp
     92        ShortCut = 8230
     93      end   
     94      item
     95        Command = ecScrollUp
     96        ShortCut = 16422
     97      end   
     98      item
     99        Command = ecDown
     100        ShortCut = 40
     101      end   
     102      item
     103        Command = ecSelDown
     104        ShortCut = 8232
     105      end   
     106      item
     107        Command = ecScrollDown
     108        ShortCut = 16424
     109      end   
     110      item
     111        Command = ecLeft
     112        ShortCut = 37
     113      end   
     114      item
     115        Command = ecSelLeft
     116        ShortCut = 8229
     117      end   
     118      item
     119        Command = ecWordLeft
     120        ShortCut = 16421
     121      end   
     122      item
     123        Command = ecSelWordLeft
     124        ShortCut = 24613
     125      end   
     126      item
     127        Command = ecRight
     128        ShortCut = 39
     129      end   
     130      item
     131        Command = ecSelRight
     132        ShortCut = 8231
     133      end   
     134      item
     135        Command = ecWordRight
     136        ShortCut = 16423
     137      end   
     138      item
     139        Command = ecSelWordRight
     140        ShortCut = 24615
     141      end   
     142      item
     143        Command = ecPageDown
     144        ShortCut = 34
     145      end   
     146      item
     147        Command = ecSelPageDown
     148        ShortCut = 8226
     149      end   
     150      item
     151        Command = ecPageBottom
     152        ShortCut = 16418
     153      end   
     154      item
     155        Command = ecSelPageBottom
     156        ShortCut = 24610
     157      end   
     158      item
     159        Command = ecPageUp
     160        ShortCut = 33
     161      end   
     162      item
     163        Command = ecSelPageUp
     164        ShortCut = 8225
     165      end   
     166      item
     167        Command = ecPageTop
     168        ShortCut = 16417
     169      end   
     170      item
     171        Command = ecSelPageTop
     172        ShortCut = 24609
     173      end   
     174      item
     175        Command = ecLineStart
     176        ShortCut = 36
     177      end   
     178      item
     179        Command = ecSelLineStart
     180        ShortCut = 8228
     181      end   
     182      item
     183        Command = ecEditorTop
     184        ShortCut = 16420
     185      end   
     186      item
     187        Command = ecSelEditorTop
     188        ShortCut = 24612
     189      end   
     190      item
     191        Command = ecLineEnd
     192        ShortCut = 35
     193      end   
     194      item
     195        Command = ecSelLineEnd
     196        ShortCut = 8227
     197      end   
     198      item
     199        Command = ecEditorBottom
     200        ShortCut = 16419
     201      end   
     202      item
     203        Command = ecSelEditorBottom
     204        ShortCut = 24611
     205      end   
     206      item
     207        Command = ecToggleMode
     208        ShortCut = 45
     209      end   
     210      item
     211        Command = ecCopy
     212        ShortCut = 16429
     213      end   
     214      item
     215        Command = ecPaste
     216        ShortCut = 8237
     217      end   
     218      item
     219        Command = ecDeleteChar
     220        ShortCut = 46
     221      end   
     222      item
     223        Command = ecCut
     224        ShortCut = 8238
     225      end   
     226      item
     227        Command = ecDeleteLastChar
     228        ShortCut = 8
     229      end   
     230      item
     231        Command = ecDeleteLastChar
     232        ShortCut = 8200
     233      end   
     234      item
     235        Command = ecDeleteLastWord
     236        ShortCut = 16392
     237      end   
     238      item
     239        Command = ecUndo
     240        ShortCut = 32776
     241      end   
     242      item
     243        Command = ecRedo
     244        ShortCut = 40968
     245      end   
     246      item
     247        Command = ecLineBreak
     248        ShortCut = 13
     249      end   
     250      item
     251        Command = ecSelectAll
     252        ShortCut = 16449
     253      end   
     254      item
     255        Command = ecCopy
     256        ShortCut = 16451
     257      end   
     258      item
     259        Command = ecBlockIndent
     260        ShortCut = 24649
     261      end   
     262      item
     263        Command = ecLineBreak
     264        ShortCut = 16461
     265      end   
     266      item
     267        Command = ecInsertLine
     268        ShortCut = 16462
     269      end   
     270      item
     271        Command = ecDeleteWord
     272        ShortCut = 16468
     273      end   
     274      item
     275        Command = ecBlockUnindent
     276        ShortCut = 24661
     277      end   
     278      item
     279        Command = ecPaste
     280        ShortCut = 16470
     281      end   
     282      item
     283        Command = ecCut
     284        ShortCut = 16472
     285      end   
     286      item
     287        Command = ecDeleteLine
     288        ShortCut = 16473
     289      end   
     290      item
     291        Command = ecDeleteEOL
     292        ShortCut = 24665
     293      end   
     294      item
     295        Command = ecUndo
     296        ShortCut = 16474
     297      end   
     298      item
     299        Command = ecRedo
     300        ShortCut = 24666
     301      end   
     302      item
     303        Command = ecGotoMarker0
     304        ShortCut = 16432
     305      end   
     306      item
     307        Command = ecGotoMarker1
     308        ShortCut = 16433
     309      end   
     310      item
     311        Command = ecGotoMarker2
     312        ShortCut = 16434
     313      end   
     314      item
     315        Command = ecGotoMarker3
     316        ShortCut = 16435
     317      end   
     318      item
     319        Command = ecGotoMarker4
     320        ShortCut = 16436
     321      end   
     322      item
     323        Command = ecGotoMarker5
     324        ShortCut = 16437
     325      end   
     326      item
     327        Command = ecGotoMarker6
     328        ShortCut = 16438
     329      end   
     330      item
     331        Command = ecGotoMarker7
     332        ShortCut = 16439
     333      end   
     334      item
     335        Command = ecGotoMarker8
     336        ShortCut = 16440
     337      end   
     338      item
     339        Command = ecGotoMarker9
     340        ShortCut = 16441
     341      end   
     342      item
     343        Command = ecSetMarker0
     344        ShortCut = 24624
     345      end   
     346      item
     347        Command = ecSetMarker1
     348        ShortCut = 24625
     349      end   
     350      item
     351        Command = ecSetMarker2
     352        ShortCut = 24626
     353      end   
     354      item
     355        Command = ecSetMarker3
     356        ShortCut = 24627
     357      end   
     358      item
     359        Command = ecSetMarker4
     360        ShortCut = 24628
     361      end   
     362      item
     363        Command = ecSetMarker5
     364        ShortCut = 24629
     365      end   
     366      item
     367        Command = ecSetMarker6
     368        ShortCut = 24630
     369      end   
     370      item
     371        Command = ecSetMarker7
     372        ShortCut = 24631
     373      end   
     374      item
     375        Command = ecSetMarker8
     376        ShortCut = 24632
     377      end   
     378      item
     379        Command = ecSetMarker9
     380        ShortCut = 24633
     381      end   
     382      item
     383        Command = EcFoldLevel1
     384        ShortCut = 41009
     385      end   
     386      item
     387        Command = EcFoldLevel2
     388        ShortCut = 41010
     389      end   
     390      item
     391        Command = EcFoldLevel3
     392        ShortCut = 41011
     393      end   
     394      item
     395        Command = EcFoldLevel4
     396        ShortCut = 41012
     397      end   
     398      item
     399        Command = EcFoldLevel5
     400        ShortCut = 41013
     401      end   
     402      item
     403        Command = EcFoldLevel6
     404        ShortCut = 41014
     405      end   
     406      item
     407        Command = EcFoldLevel7
     408        ShortCut = 41015
     409      end   
     410      item
     411        Command = EcFoldLevel8
     412        ShortCut = 41016
     413      end   
     414      item
     415        Command = EcFoldLevel9
     416        ShortCut = 41017
     417      end   
     418      item
     419        Command = EcFoldLevel0
     420        ShortCut = 41008
     421      end   
     422      item
     423        Command = EcFoldCurrent
     424        ShortCut = 41005
     425      end   
     426      item
     427        Command = EcUnFoldCurrent
     428        ShortCut = 41003
     429      end   
     430      item
     431        Command = EcToggleMarkupWord
     432        ShortCut = 32845
     433      end   
     434      item
     435        Command = ecNormalSelect
     436        ShortCut = 24654
     437      end   
     438      item
     439        Command = ecColumnSelect
     440        ShortCut = 24643
     441      end   
     442      item
     443        Command = ecLineSelect
     444        ShortCut = 24652
     445      end   
     446      item
     447        Command = ecTab
     448        ShortCut = 9
     449      end   
     450      item
     451        Command = ecShiftTab
     452        ShortCut = 8201
     453      end   
     454      item
     455        Command = ecMatchBracket
     456        ShortCut = 24642
     457      end   
     458      item
     459        Command = ecColSelUp
     460        ShortCut = 40998
     461      end   
     462      item
     463        Command = ecColSelDown
     464        ShortCut = 41000
     465      end   
     466      item
     467        Command = ecColSelLeft
     468        ShortCut = 40997
     469      end   
     470      item
     471        Command = ecColSelRight
     472        ShortCut = 40999
     473      end   
     474      item
     475        Command = ecColSelPageDown
     476        ShortCut = 40994
     477      end   
     478      item
     479        Command = ecColSelPageBottom
     480        ShortCut = 57378
     481      end   
     482      item
     483        Command = ecColSelPageUp
     484        ShortCut = 40993
     485      end   
     486      item
     487        Command = ecColSelPageTop
     488        ShortCut = 57377
     489      end   
     490      item
     491        Command = ecColSelLineStart
     492        ShortCut = 40996
     493      end   
     494      item
     495        Command = ecColSelLineEnd
     496        ShortCut = 40995
     497      end   
     498      item
     499        Command = ecColSelEditorTop
     500        ShortCut = 57380
     501      end   
     502      item
     503        Command = ecColSelEditorBottom
     504        ShortCut = 57379
     505      end>
     506    MouseActions = <>
     507    MouseTextActions = <>
     508    MouseSelActions = <>
     509    VisibleSpecialChars = [vscSpace, vscTabAtLast]
     510    SelectedColor.BackPriority = 50
     511    SelectedColor.ForePriority = 50
     512    SelectedColor.FramePriority = 50
     513    SelectedColor.BoldPriority = 50
     514    SelectedColor.ItalicPriority = 50
     515    SelectedColor.UnderlinePriority = 50
     516    SelectedColor.StrikeOutPriority = 50
     517    BracketHighlightStyle = sbhsBoth
     518    BracketMatchColor.Background = clNone
     519    BracketMatchColor.Foreground = clNone
     520    BracketMatchColor.Style = [fsBold]
     521    FoldedCodeColor.Background = clNone
     522    FoldedCodeColor.Foreground = clGray
     523    FoldedCodeColor.FrameColor = clGray
     524    MouseLinkColor.Background = clNone
     525    MouseLinkColor.Foreground = clBlue
     526    LineHighlightColor.Background = clNone
     527    LineHighlightColor.Foreground = clNone
     528    inline SynLeftGutterPartList1: TSynGutterPartList
     529      object SynGutterMarks1: TSynGutterMarks
     530        Width = 36
     531        MouseActions = <>
     532      end
     533      object SynGutterLineNumber1: TSynGutterLineNumber
     534        Width = 25
     535        MouseActions = <>
     536        MarkupInfo.Background = clBtnFace
     537        MarkupInfo.Foreground = clNone
     538        DigitCount = 2
     539        ShowOnlyLineNumbersMultiplesOf = 1
     540        ZeroStart = False
     541        LeadingZeros = False
     542      end
     543      object SynGutterChanges1: TSynGutterChanges
     544        Width = 6
     545        MouseActions = <>
     546        ModifiedColor = 59900
     547        SavedColor = clGreen
     548      end
     549      object SynGutterSeparator1: TSynGutterSeparator
     550        Width = 3
     551        MouseActions = <>
     552        MarkupInfo.Background = clWhite
     553        MarkupInfo.Foreground = clGray
     554      end
     555      object SynGutterCodeFolding1: TSynGutterCodeFolding
     556        Width = 15
     557        MouseActions = <>
     558        MarkupInfo.Background = clNone
     559        MarkupInfo.Foreground = clGray
     560        MouseActionsExpanded = <>
     561        MouseActionsCollapsed = <>
     562      end
     563    end
     564  end
     565  object SynFreePascalSyn1: TSynFreePascalSyn
     566    Enabled = False
     567    CompilerMode = pcmObjFPC
     568    NestedComments = True
     569    left = 608
     570    top = 128
    77571  end
    78572end
  • branches/interpreter2/UFormMain.pas

    r201 r202  
    66
    77uses
    8   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, USource;
     8  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
     9  SynHighlighterPas, SynEdit, USource;
    910
    1011type
     
    1718    Label1: TLabel;
    1819    Label2: TLabel;
    19     MemoSource: TMemo;
    2020    MemoLog: TMemo;
    2121    MemoOutput: TMemo;
     22    SynEditSource: TSynEdit;
     23    SynFreePascalSyn1: TSynFreePascalSyn;
    2224    procedure ButtonCompileClick(Sender: TObject);
    2325    procedure ButtonRunClick(Sender: TObject);
     
    5355  if not Initialized then begin
    5456    Initialized := True;
    55     MemoSource.Lines.LoadFromFile('Test.pas');
     57    SynEditSource.Lines.LoadFromFile('Test.pas');
    5658    ButtonRun.Click;
    5759  end;
     
    9597  Parser := TParser.Create;
    9698  Parser.OnError := InterpreterError;
    97   Parser.Source := MemoSource.Lines.Text;
     99  Parser.Source := SynEditSource.Lines.Text;
    98100  Parser.Parse;
    99101  if Assigned(Prog) then Prog.Free;
  • branches/interpreter2/UParser.pas

    r201 r202  
    2121    function ParseProgram(SystemBlock: TBlock; out Prog: TProgram): Boolean;
    2222    function ParseBlock(ParentBlock: TBlock; out Block: TBlock): Boolean;
    23     function ParseVarBlock(Block: TBlock): Boolean;
    24     function ParseConstBlock(Block: TBlock): Boolean;
     23    function ParseBlockVar(Block: TBlock): Boolean;
     24    function ParseBlockConst(Block: TBlock): Boolean;
    2525    function ParseAssignment(Block: TBlock; out Assignment: TAssignment): Boolean;
    2626    function ParseExpression(Block: TBlock; out Expression: TExpression): Boolean;
     27    function ParseExpressionOperation(Block: TBlock; out ExpressionOperation: TExpressionOperation): Boolean;
     28    function ParseExpressionOperand(Block: TBlock; out ExpressionOperand: TExpressionOperand): Boolean;
     29    function ParseConstant(Block: TBlock; out ConstantRef: TConstant): Boolean;
     30    function ParseVariable(Block: TBlock; out VariableRef: TVariable): Boolean;
    2731    function ParseIfThenElse(Block: TBlock; out IfThenElse: TIfThenElse): Boolean;
    2832    function ParseWhileDo(Block: TBlock; out WhileDo: TWhileDo): Boolean;
     33    function ParseForToDo(Block: TBlock; out ForToDo: TForToDo): Boolean;
    2934    procedure TokenizerError(Pos: TPoint; Text: string);
    3035    procedure InitSystemBlock(Block: TBlock);
     
    7378  FunctionDef: TFunction;
    7479  Expression: TExpression;
     80  I: Integer;
    7581begin
    7682  LastPos := Tokenizer.Pos;
     
    8086    if Assigned(FunctionDef) then begin
    8187      FunctionCall := TFunctionCall.Create;
    82       FunctionCall.FunctionDef := functionDef;
     88      FunctionCall.FunctionDef := FunctionDef;
    8389      if Tokenizer.CheckNext('(', tkSpecialSymbol) then begin
    8490        Tokenizer.Expect('(', tkSpecialSymbol);
    85         if ParseExpression(Block, Expression) then begin
    86           FunctionCall.Params.Add(Expression);
    87         end else Error('Exprected function parameter.');
     91        for I := 0 to FunctionDef.Params.Count - 1 do begin
     92          if I > 0 then Tokenizer.Expect(',', tkSpecialSymbol);
     93          if ParseExpression(Block, Expression) then begin
     94            if Expression.GetType = TFunctionParameter(FunctionDef.Params[I]).TypeRef then
     95              FunctionCall.Params.Add(Expression)
     96              else Error('Function parameter mismatch.');
     97          end else Error('Expected function parameter.');
     98        end;
    8899        Tokenizer.Expect(')', tkSpecialSymbol);
    89100      end;
     
    106117  IfThenElse: TIfThenElse;
    107118  WhileDo: TWhileDo;
     119  ForToDo: TForToDo;
    108120begin
    109121  if ParseIfThenElse(Block, IfThenElse) then begin
     
    114126    Result := True;
    115127    Command := WhileDo;
     128  end else
     129  if ParseForToDo(Block, ForToDo) then begin
     130    Result := True;
     131    Command := ForToDo;
    116132  end else
    117133  if ParseBeginEnd(Block, BeginEnd) then begin
     
    163179  Block := TBlock.Create;
    164180  Block.Parent := ParentBlock;
    165   ParseVarBlock(Block);
    166   ParseConstBlock(Block);
     181  ParseBlockVar(Block);
     182  ParseBlockConst(Block);
    167183  if ParseBeginEnd(Block, BeginEnd) then begin
    168184    Result := True;
     
    172188end;
    173189
    174 function TParser.ParseVarBlock(Block: TBlock): Boolean;
     190function TParser.ParseBlockVar(Block: TBlock): Boolean;
    175191var
    176192  Token: TToken;
    177193  Variable: TVariable;
     194  TypeRef: TType;
    178195begin
    179196  if Tokenizer.CheckNext('var', tkKeyword) then begin
     
    188205          Variable.Name := Token.Text;
    189206          Block.Variables.Add(Variable);
     207          Tokenizer.Expect(':', tkSpecialSymbol);
     208          Token := Tokenizer.GetNext;
     209          if Token.Kind = tkIdentifier then begin
     210            TypeRef := Block.GetType(Token.Text);
     211            if Assigned(TypeRef) then begin
     212              Variable.TypeRef := TypeRef;
     213            end else Error('Type ' + Token.Text + ' not found.');
     214          end;
    190215        end else Error('Variable ' + Token.Text + ' redefined.');
    191216        Tokenizer.Expect(';', tkSpecialSymbol);
     
    198223end;
    199224
    200 function TParser.ParseConstBlock(Block: TBlock): Boolean;
     225function TParser.ParseBlockConst(Block: TBlock): Boolean;
    201226var
    202227  Token: TToken;
    203228  Constant: TConstant;
     229  TypeRef: TType;
    204230begin
    205231  if Tokenizer.CheckNext('const', tkKeyword) then begin
     
    214240          Constant.Name := Token.Text;
    215241          Block.Constants.Add(Constant);
     242          Tokenizer.Expect(':', tkSpecialSymbol);
     243          Token := Tokenizer.GetNext;
     244          if Token.Kind = tkIdentifier then begin
     245            TypeRef := Block.GetType(Token.Text);
     246            if Assigned(TypeRef) then begin
     247              Constant.TypeRef := TypeRef;
     248            end else Error('Type ' + Token.Text + ' not found.');
     249          end;
    216250          Tokenizer.Expect('=', tkSpecialSymbol);
    217251          Token := Tokenizer.GetNext;
    218           if (Token.Kind = tkNumber) or (Token.Kind = tkString) then
    219             Constant.Value := Token.Text
    220             else Error('Expected string or number.');
     252          if Token.Kind = tkNumber then begin
     253            Constant.Value := TValueInteger.Create;
     254            TValueInteger(Constant.Value).Value := StrToInt(Token.Text);
     255          end else
     256          if Token.Kind = tkString then begin
     257            Constant.Value := TValueString.Create;
     258            TValueString(Constant.Value).Value := Token.Text;
     259          end else Error('Expected string or number.');
    221260        end else Error('Constant ' + Token.Text + ' redefined.');
    222261        Tokenizer.Expect(';', tkSpecialSymbol);
     
    239278  if Token.Kind = tkIdentifier then begin
    240279    Result := True;
    241     Variable := Block.Variables.SearchByName(Token.Text);
     280    Variable := Block.GetVariable(Token.Text);
    242281    if Assigned(Variable) then begin
    243282      Result := True;
     
    246285      Tokenizer.Expect(':=', tkSpecialSymbol);
    247286      if ParseExpression(Block, Expression) then begin
    248         Assignment.Expression.Free;
    249         Assignment.Expression := Expression;
     287        if Expression.GetType = Variable.TypeRef then begin
     288          Assignment.Expression.Free;
     289          Assignment.Expression := Expression;
     290        end else begin
     291          Result := False;
     292          Error('Assignment type mismatch.');
     293        end;
    250294      end;
     295      if not Result then Assignment.Free;
    251296    end else Error('Variable ' + Token.Text + ' not defined.');
    252297  end;
     
    256301  ): Boolean;
    257302var
     303  ExpressionOperation: TExpressionOperation;
     304  ExpressionOperand: TExpressionOperand;
     305begin
     306  Result := False;
     307  if ParseExpressionOperation(Block, ExpressionOperation) then begin
     308    Result := True;
     309    Expression := ExpressionOperation;
     310  end else
     311  if ParseExpressionOperand(Block, ExpressionOperand) then begin
     312    Result := True;
     313    Expression := ExpressionOperand;
     314  end;
     315end;
     316
     317function TParser.ParseExpressionOperation(Block: TBlock; out
     318  ExpressionOperation: TExpressionOperation): Boolean;
     319var
     320  Operand: TExpressionOperand;
     321  Token: TToken;
     322  Expression: TExpression;
     323  LastPos: TTokenizerPos;
     324begin
     325  Result := False;
     326  LastPos := Tokenizer.Pos;
     327  if ParseExpressionOperand(Block, Operand) then begin
     328    Token := Tokenizer.GetNext;
     329    if (Token.Kind = tkSpecialSymbol) and Tokenizer.IsOperator(Token.Text) then begin
     330      Result := True;
     331      ExpressionOperation := TExpressionOperation.Create;
     332      ExpressionOperation.TypeRef := Operand.GetType;
     333      if Token.Text = '+' then ExpressionOperation.Operation := eoAdd
     334      else if Token.Text = '-' then ExpressionOperation.Operation := eoSub
     335      else if Token.Text = '=' then ExpressionOperation.Operation := eoEqual
     336      else if Token.Text = '<>' then ExpressionOperation.Operation := eoNotEqual
     337      else Error('Unsupported operator ' + Token.Text);
     338      ExpressionOperation.Items.Add(Operand);
     339      if ParseExpression(Block, Expression) then begin
     340        if Expression.GetType = Operand.GetType then
     341          ExpressionOperation.Items.Add(Expression)
     342          else Error('Expression operands needs to be same type.');
     343      end else Error('Missing operand.');
     344    end;
     345  end;
     346  if not Result then Tokenizer.Pos := LastPos;
     347end;
     348
     349function TParser.ParseExpressionOperand(Block: TBlock; out
     350  ExpressionOperand: TExpressionOperand): Boolean;
     351var
    258352  Variable: TVariable;
    259353  Constant: TConstant;
    260   Token: TToken;
    261 begin
    262   Result := False;
     354  FunctionCall: TFunctionCall;
     355begin
     356  Result := False;
     357  if ParseFunctionCall(Block, FunctionCall) then begin
     358    Result := True;
     359    ExpressionOperand := TExpressionOperand.Create;
     360    ExpressionOperand.FunctionCall := FunctionCall;
     361    ExpressionOperand.OperandType := otFunctionCall;
     362  end else
     363  if ParseConstant(Block, Constant) then begin
     364    Result := True;
     365    ExpressionOperand := TExpressionOperand.Create;
     366    ExpressionOperand.ConstantRef := Constant;
     367    ExpressionOperand.OperandType := otConstant;
     368  end else
     369  if ParseVariable(Block, Variable) then begin
     370    Result := True;
     371    ExpressionOperand := TExpressionOperand.Create;
     372    ExpressionOperand.VariableRef := Variable;
     373    ExpressionOperand.OperandType := otVariable;
     374  end else Error('Expected expression operand.');
     375end;
     376
     377function TParser.ParseConstant(Block: TBlock; out ConstantRef: TConstant
     378  ): Boolean;
     379var
     380  LastPos: TTokenizerPos;
     381  Token: TToken;
     382begin
     383  Result := False;
     384  LastPos := Tokenizer.Pos;
    263385  Token := Tokenizer.GetNext;
    264   if Token.Kind = tkIdentifier then begin
    265     Variable := Block.Variables.SearchByName(Token.Text);
    266     if Assigned(Variable) then begin
     386  if Token.Kind = tkIdentifier then begin;
     387    ConstantRef := Block.GetConstant(Token.Text);
     388    if Assigned(ConstantRef) then begin
    267389      Result := True;
    268       Expression := TExpression.Create;
    269       Expression.VariableRef := Variable;
    270     end else begin
    271       Constant := Block.Constants.SearchByName(Token.Text);
    272       if Assigned(Constant) then begin
    273         Result := True;
    274         Expression := TExpression.Create;
    275         Expression.ConstantRef := Constant;
    276       end;
    277390    end;
    278391  end else
    279392  if Token.Kind = tkNumber then begin
    280393    Result := True;
    281     Constant := Block.Constants.AddNew('_C' + IntToStr(Block.Constants.Count));
    282     Constant.Value := Token.Text;
    283     Expression := TExpression.Create;
    284     Expression.ConstantRef := Constant;
     394    ConstantRef := Block.Constants.AddNew('_C' + IntToStr(Block.Constants.Count));
     395    ConstantRef.TypeRef := Block.GetType('Integer');
     396    ConstantRef.Value := TValueInteger.Create;
     397    TValueInteger(ConstantRef.Value).Value := StrToInt(Token.Text);
    285398  end else
    286399  if Token.Kind = tkString then begin
    287400    Result := True;
    288     Constant := Block.Constants.AddNew('_C' + IntToStr(Block.Constants.Count));
    289     Constant.Value := Token.Text;
    290     Expression := TExpression.Create;
    291     Expression.ConstantRef := Constant;
    292   end;
     401    ConstantRef := Block.Constants.AddNew('_C' + IntToStr(Block.Constants.Count));
     402    ConstantRef.TypeRef := Block.GetType('string');
     403    ConstantRef.Value := TValueString.Create;
     404    TValueString(ConstantRef.Value).Value := Token.Text;
     405  end;
     406  if not Result then Tokenizer.Pos := LastPos;
     407end;
     408
     409function TParser.ParseVariable(Block: TBlock; out VariableRef: TVariable
     410  ): Boolean;
     411var
     412  LastPos: TTokenizerPos;
     413  Token: TToken;
     414begin
     415  Result := False;
     416  LastPos := Tokenizer.Pos;
     417  Token := Tokenizer.GetNext;
     418  if Token.Kind = tkIdentifier then begin;
     419    VariableRef := Block.GetVariable(Token.Text);
     420    if Assigned(VariableRef) then begin
     421      Result := True;
     422    end;
     423  end;
     424  if not Result then Tokenizer.Pos := LastPos;
    293425end;
    294426
     
    345477end;
    346478
     479function TParser.ParseForToDo(Block: TBlock; out ForToDo: TForToDo): Boolean;
     480var
     481  Expression: TExpression;
     482  VariableRef: TVariable;
     483  Command: TCommand;
     484begin
     485  Result := False;
     486  if Tokenizer.CheckNext('for', tkKeyword) then begin
     487    Tokenizer.Expect('for', tkKeyword);
     488    Result := True;
     489    ForToDo := TForToDo.Create;
     490    if ParseVariable(Block, VariableRef) then begin
     491      ForToDo.VariableRef := VariableRef;
     492      Tokenizer.Expect(':=', tkSpecialSymbol);
     493      if ParseExpression(Block, Expression) then begin
     494        ForToDo.ExpressionFrom.Free;
     495        ForToDo.ExpressionFrom := Expression;
     496        Tokenizer.Expect('to', tkKeyword);
     497        if ParseExpression(Block, Expression) then begin
     498          ForToDo.ExpressionTo.Free;
     499          ForToDo.ExpressionTo := Expression;
     500          Tokenizer.Expect('do', tkKeyword);
     501          if ParseCommand(Block, Command) then begin
     502            ForToDo.Command.Free;
     503            ForToDo.Command := Command;
     504          end else Error('Expected command.');
     505        end else Error('Expected expression.');
     506      end else Error('Expected expression.');
     507    end else Error('Expected control variable.');
     508  end;
     509end;
     510
    347511procedure TParser.TokenizerError(Pos: TPoint; Text: string);
    348512begin
     
    352516
    353517procedure TParser.InitSystemBlock(Block: TBlock);
    354 begin
    355   Block.Functions.AddNew('WriteLn');
    356   Block.Functions.AddNew('Write');
     518var
     519  TypeBoolean: TType;
     520  TypeString: TType;
     521  TypeInteger: TType;
     522begin
     523  TypeBoolean := Block.Types.AddNew('Boolean');
     524  with TypeBoolean do begin
     525    ValueClass := TValueBoolean;
     526    with Functions.AddNew('_Assign') do begin
     527      Params.AddNew('Source', TypeBoolean);
     528      ResultType := TypeBoolean;
     529    end;
     530    with Functions.AddNew('_Equal') do begin
     531      Params.AddNew('A', TypeBoolean);
     532      Params.AddNew('B', TypeBoolean);
     533      ResultType := TypeBoolean;
     534    end;
     535  end;
     536  TypeString := Block.Types.AddNew('string');
     537  with TypeString do begin
     538    ValueClass := TValueString;
     539    with Functions.AddNew('_Assign') do begin
     540      Params.AddNew('Source', TypeString);
     541      ResultType := TypeString;
     542    end;
     543    with Functions.AddNew('_Add') do begin
     544      Params.AddNew('A', TypeString);
     545      Params.AddNew('B', TypeString);
     546      ResultType := TypeString;
     547    end;
     548    with Functions.AddNew('_Equal') do begin
     549      Params.AddNew('A', TypeString);
     550      Params.AddNew('B', TypeString);
     551      ResultType := TypeBoolean;
     552    end;
     553    with Functions.AddNew('_NotEqual') do begin
     554      Params.AddNew('A', TypeString);
     555      Params.AddNew('B', TypeString);
     556      ResultType := TypeBoolean;
     557    end;
     558  end;
     559  TypeInteger := Block.Types.AddNew('Integer');
     560  with TypeInteger do begin
     561    ValueClass := TValueInteger;
     562    with Functions.AddNew('_Assign') do begin
     563      Params.AddNew('Source', TypeInteger);
     564      ResultType := TypeInteger;
     565    end;
     566    with Functions.AddNew('_Add') do begin
     567      Params.AddNew('A', TypeInteger);
     568      Params.AddNew('B', TypeInteger);
     569      ResultType := TypeInteger;
     570    end;
     571    with Functions.AddNew('_Sub') do begin
     572      Params.AddNew('A', TypeInteger);
     573      Params.AddNew('B', TypeInteger);
     574      ResultType := TypeInteger;
     575    end;
     576    with Functions.AddNew('_Equal') do begin
     577      Params.AddNew('A', TypeInteger);
     578      Params.AddNew('B', TypeInteger);
     579      ResultType := TypeBoolean;
     580    end;
     581    with Functions.AddNew('_NotEqual') do begin
     582      Params.AddNew('A', TypeInteger);
     583      Params.AddNew('B', TypeInteger);
     584      ResultType := TypeBoolean;
     585    end;
     586  end;
     587  with Block.Functions.AddNew('IntToStr') do begin
     588    Params.AddNew('Value', TypeInteger);
     589    ResultType := TypeString;
     590  end;
     591  with Block.Functions.AddNew('StrToInt') do begin
     592    Params.AddNew('Value', TypeString);
     593    ResultType := TypeInteger;
     594  end;
     595  with Block.Functions.AddNew('WriteLn') do begin
     596    Params.AddNew('Text', TypeString);
     597  end;
     598  with Block.Functions.AddNew('Write') do begin
     599    Params.AddNew('Text', TypeString);
     600  end;
    357601end;
    358602
  • branches/interpreter2/USource.pas

    r201 r202  
    1010type
    1111  TExpressions = class;
     12  TFunctions = class;
     13
     14  TValue = class
     15  end;
     16
     17  TValueString = class(TValue)
     18    Value: string;
     19  end;
     20
     21  TValueInteger = class(TValue)
     22    Value: Integer;
     23  end;
     24
     25  TValueBoolean = class(TValue)
     26    Value: Boolean;
     27  end;
     28
     29  TValueClass = class of TValue;
     30
     31  { TType }
     32
     33  TType = class
     34    Name: string;
     35    Functions: TFunctions;
     36    ValueClass: TValueClass;
     37    constructor Create;
     38    destructor Destroy; override;
     39  end;
     40
     41  { TTypes }
     42
     43  TTypes = class(TObjectList)
     44    function SearchByName(Name: string): TType;
     45    function AddNew(Name: string): TType;
     46  end;
    1247
    1348  TVariable = class
    1449    Name: string;
     50    TypeRef: TType;
    1551  end;
    1652
     
    2359  TConstant = class
    2460    Name: string;
    25     Value: string;
     61    TypeRef: TType;
     62    Value: TValue;
    2663  end;
    2764
     
    3370  end;
    3471
     72  TFunctionParameter = class
     73    Name: string;
     74    TypeRef: TType;
     75  end;
     76
     77  { TFunctionParameters }
     78
     79  TFunctionParameters = class(TObjectList)
     80    function SearchByName(Name: string): TFunctionParameter;
     81    function AddNew(Name: string; TypeRef: TType): TFunctionParameter;
     82  end;
     83
     84  { TFunction }
     85
    3586  TFunction = class
    3687    Name: string;
     88    Params: TFunctionParameters;
     89    ResultType: TType;
     90    constructor Create;
     91    destructor Destroy; override;
    3792  end;
    3893
     
    52107    FunctionDef: TFunction;
    53108    Params: TExpressions;
    54     ReturnValue: Boolean;
    55109    constructor Create;
    56110    destructor Destroy; override;
     
    66120  end;
    67121
     122  TExpressionOperator = (eoAdd, eoSub, eoMultiply, eoDivide, eoModulo, eoAnd, eoXor,
     123    eoOr, eoShl, eoShr, eoEqual, eoNotEqual);
     124
     125  { TExpression }
     126
    68127  TExpression = class
     128    function GetType: TType; virtual;
     129  end;
     130
     131  { TExpressionOperation }
     132
     133  TExpressionOperation = class(TExpression)
     134    TypeRef: TType;
     135    Operation: TExpressionOperator;
     136    Items: TExpressions;
     137    constructor Create;
     138    destructor Destroy; override;
     139    function GetType: TType; override;
     140  end;
     141
     142  TExpressionOperandType = (otVariable, otConstant, otFunctionCall);
     143
     144  { TExpressionOperand }
     145
     146  TExpressionOperand = class(TExpression)
     147    OperandType: TExpressionOperandType;
    69148    VariableRef: TVariable;
    70149    ConstantRef: TConstant;
    71150    FunctionCall: TFunctionCall;
     151    function GetType: TType; override;
    72152  end;
    73153
     
    98178  TWhileDo = class(TCommand)
    99179    Expression: TExpression;
     180    Command: TCommand;
     181    constructor Create;
     182    destructor Destroy; override;
     183  end;
     184
     185  { TForToDo }
     186
     187  TForToDo = class(TCommand)
     188    VariableRef: TVariable;
     189    ExpressionFrom: TExpression;
     190    ExpressionTo: TExpression;
    100191    Command: TCommand;
    101192    constructor Create;
     
    110201    Constants: TConstants;
    111202    Functions: TFunctions;
     203    Types: TTypes;
    112204    BeginEnd: TBeginEnd;
    113205    procedure Clear;
     206    function GetType(Name: string): TType;
     207    function GetConstant(Name: string): TConstant;
     208    function GetVariable(Name: string): TVariable;
    114209    function GetFunction(Name: string): TFunction;
    115210    constructor Create;
     
    130225implementation
    131226
     227{ TForToDo }
     228
     229constructor TForToDo.Create;
     230begin
     231  ExpressionFrom := TExpression.Create;
     232  ExpressionTo := TExpression.Create;
     233  Command := TCommand.Create;
     234end;
     235
     236destructor TForToDo.Destroy;
     237begin
     238  Command.Free;
     239  ExpressionTo.Free;
     240  ExpressionFrom.Free;
     241  inherited Destroy;
     242end;
     243
     244{ TExpression }
     245
     246function TExpression.GetType: TType;
     247begin
     248  Result := nil;
     249end;
     250
     251{ TExpressionOperand }
     252
     253function TExpressionOperand.GetType: TType;
     254begin
     255  if OperandType = otFunctionCall then Result := FunctionCall.FunctionDef.ResultType
     256  else if OperandType = otConstant then Result := ConstantRef.TypeRef
     257  else if OperandType = otVariable then Result := VariableRef.TypeRef
     258  else raise Exception.Create('Unsupported operand type');
     259end;
     260
     261{ TFunctionParameters }
     262
     263function TFunctionParameters.SearchByName(Name: string): TFunctionParameter;
     264var
     265  I: Integer;
     266begin
     267  I := 0;
     268  while (I < Count) and (TFunctionParameter(Items[I]).Name <> Name) do Inc(I);
     269  if I < Count then Result := TFunctionParameter(Items[I])
     270    else Result := nil;
     271end;
     272
     273function TFunctionParameters.AddNew(Name: string; TypeRef: TType): TFunctionParameter;
     274begin
     275  Result := TFunctionParameter.Create;
     276  Result.Name := Name;
     277  Result.TypeRef := TypeRef;
     278  Add(Result);
     279end;
     280
     281{ TFunction }
     282
     283constructor TFunction.Create;
     284begin
     285  Params := TFunctionParameters.Create;
     286end;
     287
     288destructor TFunction.Destroy;
     289begin
     290  Params.Free;
     291  inherited Destroy;
     292end;
     293
     294{ TType }
     295
     296constructor TType.Create;
     297begin
     298  Functions := TFunctions.Create;
     299end;
     300
     301destructor TType.Destroy;
     302begin
     303  Functions.Free;
     304  inherited Destroy;
     305end;
     306
     307{ TTypes }
     308
     309function TTypes.SearchByName(Name: string): TType;
     310var
     311  I: Integer;
     312begin
     313  I := 0;
     314  while (I < Count) and (TType(Items[I]).Name <> Name) do Inc(I);
     315  if I < Count then Result := TType(Items[I])
     316    else Result := nil;
     317end;
     318
     319function TTypes.AddNew(Name: string): TType;
     320begin
     321  Result := TType.Create;
     322  Result.Name := Name;
     323  Add(Result);
     324end;
     325
     326{ TExpressionOperation }
     327
     328constructor TExpressionOperation.Create;
     329begin
     330  Items := TExpressions.Create;
     331end;
     332
     333destructor TExpressionOperation.Destroy;
     334begin
     335  Items.Free;
     336  inherited Destroy;
     337end;
     338
     339function TExpressionOperation.GetType: TType;
     340begin
     341  Result := TypeRef;
     342end;
     343
    132344{ TAssignment }
    133345
     
    247459  Constants.Clear;
    248460  Variables.Clear;
     461  Types.Clear;
     462end;
     463
     464function TBlock.GetType(Name: string): TType;
     465begin
     466  Result := Types.SearchByName(Name);
     467  if not Assigned(Result) and Assigned(Parent) then
     468    Result := Parent.Types.SearchByName(Name);
     469end;
     470
     471function TBlock.GetConstant(Name: string): TConstant;
     472begin
     473  Result := Constants.SearchByName(Name);
     474  if not Assigned(Result) and Assigned(Parent) then
     475    Result := Parent.Constants.SearchByName(Name);
     476end;
     477
     478function TBlock.GetVariable(Name: string): TVariable;
     479begin
     480  Result := Variables.SearchByName(Name);
     481  if not Assigned(Result) and Assigned(Parent) then
     482    Result := Parent.Variables.SearchByName(Name);
    249483end;
    250484
     
    261495  Variables := TVariables.Create;
    262496  Functions := TFunctions.Create;
     497  Types := TTypes.Create;
    263498  BeginEnd := TBeginEnd.Create;
    264499end;
     
    267502begin
    268503  BeginEnd.Free;
     504  Types.Free;
    269505  Variables.Free;
    270506  Constants.Free;
  • branches/interpreter2/UTokenizer.pas

    r200 r202  
    3030
    3131  TTokenizerState = (tsNone, tsIdentifier, tsString, tsStringEnd, tsNumber,
    32     tsSpecialSymbol);
     32    tsSpecialSymbol, tsLineComment);
    3333
    3434  { TTokenizer }
     
    4848    function IsSpecialSymbol2(Text: string): Boolean;
    4949    function IsIdentifier(Text: string): Boolean;
     50    function IsOperator(Text: string): Boolean;
    5051    function IsKeyword(Text: string): Boolean;
    5152    procedure Init;
    5253    function GetNext: TToken;
    53     function CheckNext(Text: string; Kind: TTokenKind = tkUnknown): Boolean;
     54    function CheckNext(Text: string; Kind: TTokenKind): Boolean;
    5455    function CheckNextKind(Kind: TTokenKind): Boolean;
    55     procedure Expect(Text: string; Kind: TTokenKind = tkUnknown);
     56    procedure Expect(Text: string; Kind: TTokenKind);
    5657    procedure Error(Text: string);
    5758    property OnError: TErrorEvent read FOnError write FOnError;
     
    109110begin
    110111  Result := (C = ';') or (C = '.') or (C = '(') or (C = ')') or (C = '=') or
    111     (C = ':');
     112    (C = ':') or (C = '+') or (C = '-') or (C = ',') or (C = '/') or
     113    (C = '<') or (C = '>');
    112114end;
    113115
    114116function TTokenizer.IsSpecialSymbol2(Text: string): Boolean;
    115117begin
    116   Result := (Text = ':=');
     118  Result := (Text = ':=') or (Text = '//') or (Text = '<>');
    117119end;
    118120
     
    137139end;
    138140
     141function TTokenizer.IsOperator(Text: string): Boolean;
     142begin
     143  Result := (Text = '+') or (Text = '-') or (Text = '=') or (Text = '<>');
     144end;
     145
    139146function TTokenizer.IsKeyword(Text: string): Boolean;
    140147begin
    141148  Result := (Text = 'begin') or (Text = 'end') or (Text = 'program') or
    142149  (Text = 'var') or (Text = 'const') or (Text = 'if') or (Text = 'then') or
    143   (Text = 'else') or (Text = 'while') or (Text = 'do');
     150  (Text = 'else') or (Text = 'while') or (Text = 'do') or (Text = 'for') or
     151  (Text = 'to');
    144152end;
    145153
     
    229237      end;
    230238    end else
     239    if State = tsLineComment then begin
     240      if C = #10 then begin
     241        State := tsNone;
     242      end else Pos.Increment;
     243    end else
    231244    if State = tsSpecialSymbol then begin
    232245      if IsSpecialSymbol2(Result.Text + C) then begin
    233246        Result.Text := Result.Text + C;
    234247        Pos.Increment;
    235         Break;
     248        if Result.Text = '//' then begin
     249          Result.Text := '';
     250          State := tsLineComment;
     251        end else Break;
    236252      end else begin
    237253        Break;
     
    242258end;
    243259
    244 function TTokenizer.CheckNext(Text: string; Kind: TTokenKind = tkUnknown): Boolean;
     260function TTokenizer.CheckNext(Text: string; Kind: TTokenKind): Boolean;
    245261var
    246262  LastPos: TTokenizerPos;
     
    264280end;
    265281
    266 procedure TTokenizer.Expect(Text: string; Kind: TTokenKind = tkUnknown);
     282procedure TTokenizer.Expect(Text: string; Kind: TTokenKind);
    267283var
    268284  Token: TToken;
  • branches/interpreter2/interpreter.lpi

    r201 r202  
    6363      <Modes Count="0"/>
    6464    </RunParams>
    65     <RequiredPackages Count="1">
     65    <RequiredPackages Count="2">
    6666      <Item1>
     67        <PackageName Value="SynEdit"/>
     68      </Item1>
     69      <Item2>
    6770        <PackageName Value="LCL"/>
    68       </Item1>
     71      </Item2>
    6972    </RequiredPackages>
    7073    <Units Count="7">
Note: See TracChangeset for help on using the changeset viewer.