Changeset 148


Ignore:
Timestamp:
Jan 17, 2018, 5:27:23 PM (6 years ago)
Author:
chronos
Message:
  • Added: Unfinished support for variable arrays.
Location:
branches/easy compiler
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/easy compiler/UCompiler.pas

    r147 r148  
    99
    1010type
    11   TSourceTokenKind = (stNone, stString, stIdentifier, stEof, stInteger);
     11  TSourceTokenKind = (stNone, stString, stIdentifier, stEof, stInteger,
     12    stSpecialSymbol);
    1213  TSourceToken = record
    1314    Text: string;
     
    4950      ): Boolean;
    5051    function ParseFunctionCall(SourceCode: TSourceCode; out FunctionCall: TCommandFunctionCall): Boolean;
    51     function ParseIfZero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean;
     52    function ParseIfEqual(SourceCode: TSourceCode; out IfZero: TCommandIfEqual): Boolean;
    5253    function ParseReference(SourceCode: TSourceCode): TSourceReference;
    5354    function ParseReferenceVariable(SourceCode: TSourceCode): TSourceReference;
     
    126127procedure TTokenizer.Tokenize(Text: string; Tokens: TSourceTokens);
    127128type
    128   TTokenizerState = (tsNone, tsIdentifier, tsString, tsInteger);
     129  TTokenizerState = (tsNone, tsIdentifier, tsString, tsInteger, tsSpecialSymbol);
    129130var
    130131  State: TTokenizerState;
     
    153154        Token := '';
    154155      end else
    155       raise Exception.Create('Unexpected character');
     156      if (Text[I] = '[') or (Text[I] = ']') then begin
     157        Tokens.AddToken(stSpecialSymbol, Text[I]);
     158      end else
     159      raise Exception.Create('Unexpected character: ' + Text[I]);
    156160    end else
    157161    if State = tsIdentifier then begin
    158162      if IsAlphaNumeric(Text[I]) then begin
    159163        Token := Token + Text[I];
    160       end else
    161       if IsWhiteSpace(Text[I]) then begin
     164      end else begin
    162165        Tokens.AddToken(stIdentifier, Token);
    163166        State := tsNone;
    164167        Dec(I);
    165       end else
    166       raise Exception.Create('Unexpected character');
     168      end;
    167169    end else
    168170    if State = tsInteger then begin
    169171      if IsDigit(Text[I]) then begin
    170172        Token := Token + Text[I];
    171       end else
    172       if IsWhiteSpace(Text[I]) then begin
     173      end else begin
    173174        Tokens.AddToken(stInteger, Token);
    174175        State := tsNone;
    175176        Dec(I);
    176       end else
    177       raise Exception.Create('Unexpected character');
     177      end;
    178178    end else
    179179    if State = tsString then begin
     
    230230var
    231231  Token: TSourceToken;
     232  Token2: TSourceToken;
    232233  NewReference: TSourceReference;
    233234begin
     
    239240  end else
    240241  if Token.Kind = stIdentifier then begin
    241     NewReference := TSourceReferenceVariable.Create;
    242     TSourceReferenceVariable(NewReference).Variable :=
    243       SourceCode.Variables.Search(Token.Text);
    244     if TSourceReferenceVariable(NewReference).Variable = nil then
    245       raise Exception.Create('Variable not found: ' + Token.Text);
     242    if Tokenizer.CheckNext('[', stSpecialSymbol) then begin
     243      Token2 := Tokenizer.GetNext;
     244      NewReference := TSourceReferenceArray.Create;
     245      TSourceReferenceArray(NewReference).ArrayRef := SourceCode.Variables.Search(Token.Text);
     246      if TSourceReferenceArray(NewReference).ArrayRef = nil then
     247        raise Exception.Create('Variable not found: ' + Token.Text);
     248      TSourceReferenceArray(NewReference).Index := ParseReference(SourceCode);
     249
     250      Token2 := Tokenizer.GetNext;
     251      if (Token2.Text <> ']') or (Token2.Kind <> stSpecialSymbol) then
     252        raise Exception.Create('Expected ]');
     253    end else begin
     254      NewReference := TSourceReferenceVariable.Create;
     255      TSourceReferenceVariable(NewReference).Variable :=
     256        SourceCode.Variables.Search(Token.Text);
     257      if TSourceReferenceVariable(NewReference).Variable = nil then
     258        raise Exception.Create('Variable not found: ' + Token.Text);
     259    end;
    246260  end else
    247261  if Token.Kind = stInteger then begin
     
    257271var
    258272  Token: TSourceToken;
     273  Token2: TSourceToken;
    259274  NewReference: TSourceReference;
    260275begin
    261276  Token := Tokenizer.GetNext;
    262277  if Token.Kind = stIdentifier then begin
    263     NewReference := TSourceReferenceVariable.Create;
    264     TSourceReferenceVariable(NewReference).Variable :=
    265       SourceCode.Variables.Search(Token.Text);
    266     if TSourceReferenceVariable(NewReference).Variable = nil then
    267       raise Exception.Create('Variable not found: ' + Token.Text);
    268 
     278    if Tokenizer.CheckNext('[', stSpecialSymbol) then begin
     279      Token2 := Tokenizer.GetNext;
     280      NewReference := TSourceReferenceArray.Create;
     281      TSourceReferenceArray(NewReference).ArrayRef := SourceCode.Variables.Search(Token.Text);
     282      if TSourceReferenceArray(NewReference).ArrayRef = nil then
     283        raise Exception.Create('Variable not found: ' + Token.Text);
     284      TSourceReferenceArray(NewReference).Index := ParseReference(SourceCode);
     285
     286      Token2 := Tokenizer.GetNext;
     287      if (Token2.Text <> ']') or (Token2.Kind <> stSpecialSymbol) then
     288        raise Exception.Create('Expected ]');
     289    end else begin
     290      NewReference := TSourceReferenceVariable.Create;
     291      TSourceReferenceVariable(NewReference).Variable :=
     292        SourceCode.Variables.Search(Token.Text);
     293      if TSourceReferenceVariable(NewReference).Variable = nil then
     294        raise Exception.Create('Variable not found: ' + Token.Text);
     295    end;
    269296  end else raise Exception.Create('Unexpected parameter');
    270297  Result := NewReference;
     
    300327end;
    301328
    302 function TCompiler.ParseIfZero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean;
     329function TCompiler.ParseIfEqual(SourceCode: TSourceCode; out IfZero: TCommandIfEqual): Boolean;
    303330var
    304331  Token: TSourceToken;
     
    310337  Token := Tokenizer.GetNext;
    311338  Keyword := LowerCase(Token.Text);
    312   if Keyword = 'ifzero' then begin
    313     IfZero := TCommandIfZero.Create;
    314     IfZero.Variable := TSourceReferenceVariable(ParseReferenceVariable(SourceCode));
     339  if Keyword = 'ifequal' then begin
     340    IfZero := TCommandIfEqual.Create;
     341    IfZero.Reference1 := ParseReference(SourceCode);
     342    IfZero.Reference2 := ParseReference(SourceCode);
    315343    Result := True;
    316344  end;
     
    362390var
    363391  CommandBeginEnd: TCommandBeginEnd;
    364   CommandIfZero: TCommandIfZero;
     392  CommandIfZero: TCommandIfEqual;
    365393  CommandFunctionCall: TCommandFunctionCall;
    366394  CommandBreak: TCommandBreak;
     
    373401    Command := CommandBeginEnd;
    374402  end else
    375   if ParseIfZero(SourceCode, CommandIfZero) then begin
     403  if ParseIfEqual(SourceCode, CommandIfZero) then begin
    376404    Command := CommandIfZero;
    377405  end else
  • branches/easy compiler/UFormMain.pas

    r147 r148  
    5151procedure TForm1.FormShow(Sender: TObject);
    5252begin
    53   with MemoSource.Lines do begin
     53{  with MemoSource.Lines do begin
    5454    Add('Begin');
    5555    Add('var I Integer');
     
    5959    Add('PrintLn I');
    6060    Add('Decrement I 1');
    61     Add('IfZero I');
     61    Add('IfEqual I 0');
    6262    Add('Break');
    6363    Add('End');
    6464    Add('End');
    6565  end;
    66 {  with MemoSource.Lines do begin
     66  with MemoSource.Lines do begin
    6767    Add('PrintLn ''Super Calculator''');
    6868    Add('var Value1 Integer');
     
    103103    Add('PrintLn Text3');
    104104  end;
    105 
     105}
    106106  with MemoSource.Lines do begin
     107    Add('Begin');
     108    Add('Var AnimalName StringArray');
     109    Add('Var AnimalProperty StringArray');
     110    Add('Var AnimalCount Integer');
     111    Add('Var Answer String');
     112    Add('Var I Integer');
    107113    Add('Assign AnimalName[0] ''an elephant''');
    108114    Add('Assign AnimalProperty[0] ''It is big and slow''');
     
    122128        Add('IfEqual Answer ''y''');
    123129        Add('Begin');
    124           Add('PrintLn ''That''s clear. It is ''');
     130          Add('PrintLn ''Thats clear. It is ''');
    125131          Add('PrintLn AnimalName[I]');
    126132          Add('Break');
    127133        Add('End');
    128         Add('Increment I');
    129         Add('IfHigherOrEqual I AnimalCount');
     134        Add('Increment I 1');
     135        Add('IfEqual I AnimalCount');
    130136        Add('Break');
    131137      Add('End');
     
    138144      Add('PrintLn ''''');
    139145    Add('End');
    140   end;
    141   }
     146    Add('End');
     147  end;
     148
    142149end;
    143150
  • branches/easy compiler/USourceCode.pas

    r147 r148  
    2828  end;
    2929
     30  TSourceValues = class(TObjectList)
     31  end;
     32
    3033  TSourceValueClass = class of TSourceValue;
    3134
     
    3437  TSourceType = class
    3538    Name: string;
    36     ValueClass: TSourceValueClass;
    37   end;
     39    function GetValueType: TSourceValueClass; virtual;
     40  end;
     41
     42  TSourceTypeClass = class of TSourceType;
    3843
    3944  { TSourceTypes }
     
    4146  TSourceTypes = class(TObjectList)
    4247    Parent: TSourceTypes;
    43     function AddNew(Name: string; ClassType: TSourceValueClass): TSourceType;
     48    function AddNew(Name: string; ClassType: TSourceTypeClass): TSourceType;
    4449    function Search(Name: string): TSourceType;
    4550  end;
     51
     52  { TSourceTypeInteger }
     53
     54  TSourceTypeInteger = class(TSourceType)
     55    function GetValueType: TSourceValueClass; override;
     56  end;
     57
     58  { TSourceTypeString }
     59
     60  TSourceTypeString = class(TSourceType)
     61    function GetValueType: TSourceValueClass; override;
     62  end;
     63
     64  { TSourceTypeArray }
     65
     66  TSourceTypeArray = class(TSourceType)
     67    ItemType: TSourceType;
     68    function GetValueType: TSourceValueClass; override;
     69  end;
     70
    4671
    4772  { TSourceVariable }
     
    6489  end;
    6590
     91  TSourceReferenceArray = class(TSourceReference)
     92    ArrayRef: TSourceVariable;
     93    Index: TSourceReference;
     94  end;
     95
    6696  { TSourceValueString }
    6797
     
    76106    Value: Integer;
    77107    procedure Assign(Source: TSourceValue); override;
     108  end;
     109
     110  { TSourceValueArray }
     111
     112  TSourceValueArray = class(TSourceValue)
     113    Items: TSourceValues;
     114    procedure Assign(Source: TSourceValue); override;
     115    constructor Create;
     116    destructor Destroy; override;
    78117  end;
    79118
     
    146185  end;
    147186
    148   { TCommandIfZero }
    149 
    150   TCommandIfZero = class(TSourceCommand)
    151     Variable: TSourceReferenceVariable;
     187  { TCommandIfEqual }
     188
     189  TCommandIfEqual = class(TSourceCommand)
     190    Reference1: TSourceReference;
     191    Reference2: TSourceReference;
    152192    destructor Destroy; override;
    153193  end;
     
    184224implementation
    185225
    186 { TCommandIfZero }
    187 
    188 destructor TCommandIfZero.Destroy;
    189 begin
    190   Variable.Free;
     226{ TSourceType }
     227
     228function TSourceType.GetValueType: TSourceValueClass;
     229begin
     230  Result := nil;
     231end;
     232
     233{ TSourceTypeInteger }
     234
     235function TSourceTypeInteger.GetValueType: TSourceValueClass;
     236begin
     237  Result := TSourceValueInteger;
     238end;
     239
     240{ TSourceTypeString }
     241
     242function TSourceTypeString.GetValueType: TSourceValueClass;
     243begin
     244  Result := TSourceValueString;
     245end;
     246
     247{ TSourceTypeArray }
     248
     249function TSourceTypeArray.GetValueType: TSourceValueClass;
     250begin
     251  Result := TSourceValueArray;
     252end;
     253
     254{ TSourceValueArray }
     255
     256procedure TSourceValueArray.Assign(Source: TSourceValue);
     257var
     258  I: Integer;
     259  Value: TSourceValue;
     260begin
     261  if Source is TSourceValueInteger then begin
     262    while Items.Count < TSourceValueArray(Source).Items.Count do begin
     263      Value := TSourceValue(TSourceValue(TSourceValueArray(Source).Items[Items.Count]).ClassType.Create);
     264      Items.Add(Value);
     265    end;
     266    while Items.Count > TSourceValueArray(Source).Items.Count do begin
     267      Items.Delete(Items.Count - 1);
     268    end;
     269    for I := 0 to Items.Count - 1 do
     270      TSourceValue(Items[I]).Assign(TSourceValue(TSourceValueArray(Source).Items[I]));
     271  end else raise Exception.Create('Type for assignment not matches');
     272end;
     273
     274constructor TSourceValueArray.Create;
     275begin
     276  Items := TSourceValues.Create;
     277end;
     278
     279destructor TSourceValueArray.Destroy;
     280begin
     281  Items.Free;
     282  inherited Destroy;
     283end;
     284
     285{ TCommandIfEqual }
     286
     287destructor TCommandIfEqual.Destroy;
     288begin
     289  Reference1.Free;
     290  Reference2.Free;
    191291  inherited Destroy;
    192292end;
     
    236336{ TSourceTypes }
    237337
    238 function TSourceTypes.AddNew(Name: string; ClassType: TSourceValueClass): TSourceType;
    239 begin
    240   Result := TSourceType.Create;
     338function TSourceTypes.AddNew(Name: string; ClassType: TSourceTypeClass): TSourceType;
     339begin
     340  Result := ClassType.Create;
    241341  Result.Name := Name;
    242   Result.ValueClass := ClassType;
    243342  Add(Result);
    244343end;
     
    395494var
    396495  Funct: TSourceFunction;
     496  Typ: TSourceType;
    397497begin
    398498  Functions.Clear;
    399499
    400500  // Init types
    401   Types.AddNew('Integer', TSourceValueInteger);
    402   Types.AddNew('String', TSourceValueString);
     501  Types.AddNew('Integer', TSourceTypeInteger);
     502  Types.AddNew('String', TSourceTypeString);
     503  Typ := Types.AddNew('StringArray', TSourceTypeArray);
     504  TSourceTypeArray(Typ).ItemType := TSourceTypeString.Create;
     505  Typ := Types.AddNew('IntegerArray', TSourceTypeArray);
     506  TSourceTypeArray(Typ).ItemType := TSourceTypeInteger.Create;
    403507
    404508  // Init functions
  • branches/easy compiler/USourceExecutor.pas

    r147 r148  
    4444    RepeatBlocks: TExecutorRepeats;
    4545    SkipNext: Boolean;
     46    procedure ExecuteAssign(CommandAssign: TCommandFunctionCall);
    4647    procedure ExecuteBeginEnd(BeginEnd: TCommandBeginEnd);
    4748    procedure ExecuteCommand(Command: TSourceCommand);
    4849    procedure ExecuteBreak(CommandBreak: TCommandBreak);
     50    procedure ExecuteIfEqual(IfEqual: TCommandIfEqual);
    4951    procedure ExecuteRepeat(CommandRepeat: TCommandRepeat);
    5052    function ReadValueReference(Reference: TSourceReference): TSourceValue;
     
    120122
    121123function TSourceExecutor.ReadValueReference(Reference: TSourceReference): TSourceValue;
     124var
     125  ArrayIndex: TSourceValue;
    122126begin
    123127  Result := nil;
     
    127131  if Reference is TSourceReferenceVariable then begin
    128132    Result := Variables.Search(TSourceReferenceVariable(Reference).Variable).Value;
    129   end else raise Exception.Create('Unsupported reference');
     133  end else
     134  if Reference is TSourceReferenceArray then begin
     135    ArrayIndex := ReadValueReference(TSourceReferenceArray(Reference).Index);
     136    if not (ArrayIndex is TSourceValueInteger) then
     137      raise Exception.Create('Only integer array index supported');
     138    Result := TSourceValue(TSourceValueArray(Variables.Search(TSourceReferenceArray(Reference).ArrayRef).Value).Items[TSourceValueInteger(ArrayIndex).Value]);
     139  end else
     140  raise Exception.Create('Unsupported reference');
    130141end;
    131142
    132143function TSourceExecutor.ReadVarReference(Reference: TSourceReference): TSourceVariable;
     144var
     145  ArrayIndex: TSourceValue;
    133146begin
    134147  Result := nil;
    135148  if Reference is TSourceReferenceVariable then begin
    136149    Result := TSourceReferenceVariable(Reference).Variable;
     150  end else
     151  if Reference is TSourceReferenceArray then begin
     152    ArrayIndex := ReadValueReference(TSourceReferenceArray(Reference).Index);
     153    if not (ArrayIndex is TSourceValueInteger) then
     154      raise Exception.Create('Only integer array index supported');
     155//    Result := TSourceValue(TSourceValueArray(Variables.Search(TSourceReferenceArray(Reference).ArrayRef).Value).Items[TSourceValueInteger(ArrayIndex)]);
     156//TODO:    Result := Variables.Search(TSourceReferenceArray(Reference).ArrayRef);
    137157  end else raise Exception.Create('Unsupported reference');
     158end;
     159
     160procedure TSourceExecutor.ExecuteAssign(CommandAssign: TCommandFunctionCall);
     161var
     162  Variable: TSourceVariable;
     163  Value: TSourceValue;
     164  ExecutorVar: TExecutorVariable;
     165begin
     166  with TCommandFunctionCall(CommandAssign) do begin
     167    Variable := ReadVarReference(TSourceReference(Parameters[0]));
     168    Value := ReadValueReference(TSourceReference(Parameters[1]));
     169    ExecutorVar := Variables.Search(Variable);
     170    if not Assigned(ExecutorVar) then begin
     171      ExecutorVar := TExecutorVariable.Create;
     172      ExecutorVar.Variable := Variable;
     173      Variables.Add(ExecutorVar);
     174      ExecutorVar.Value := Variable.ValueType.GetValueType.Create;
     175    end;
     176    ExecutorVar.Value.Assign(Value);
     177  end;
    138178end;
    139179
     
    170210  end else
    171211  raise Exception.Create('Used break outside repeat loop');
     212end;
     213
     214procedure TSourceExecutor.ExecuteIfEqual(IfEqual: TCommandIfEqual);
     215var
     216  Value1: TSourceValue;
     217  Value2: TSourceValue;
     218begin
     219  Value1 := ReadValueReference(IfEqual.Reference1);
     220  Value2 := ReadValueReference(IfEqual.Reference2);
     221  if (Value1 is TSourceValueInteger) and (Value2 is TSourceValueInteger) then begin
     222    if TSourceValueInteger(Value1).Value <> TSourceValueInteger(Value2).Value then
     223      SkipNext := True;
     224  end else
     225  if (Value1 is TSourceValueString) and (Value2 is TSourceValueString) then begin
     226    if TSourceValueString(Value1).Value <> TSourceValueString(Value2).Value then
     227      SkipNext := True;
     228  end else
     229  raise Exception.Create('Unsupported types for comparison.');
    172230end;
    173231
     
    235293    end else
    236294    if Name = 'assign' then begin
    237       Variable := ReadVarReference(TSourceReference(Parameters[0]));
    238       Value := ReadValueReference(TSourceReference(Parameters[1]));
    239       ExecutorVar := Variables.Search(Variable);
    240       if not Assigned(ExecutorVar) then begin
    241         ExecutorVar := TExecutorVariable.Create;
    242         ExecutorVar.Variable := Variable;
    243         Variables.Add(ExecutorVar);
    244         ExecutorVar.Value := Variable.ValueType.ValueClass.Create;
    245       end;
    246       ExecutorVar.Value.Assign(Value);
     295      ExecuteAssign(TCommandFunctionCall(Command));
    247296    end else
    248297    if Name = 'increment' then begin
     
    272321    ExecuteBreak(TCommandBreak(Command));
    273322  end else
    274   if Command is TCommandIfZero then begin
    275     ExecutorVar := Variables.Search(TCommandIfZero(Command).Variable.Variable);
    276     if Assigned(ExecutorVar) then begin
    277       if ExecutorVar.Variable.ValueType.Name = 'Integer' then begin
    278         if TSourceValueInteger(ExecutorVar.Value).Value <> 0 then SkipNext := True;
    279       end else
    280       raise Exception.Create('Can compare only integers');
    281     end else
    282     raise Exception.Create('Variable not found');
     323  if Command is TCommandIfEqual then begin
     324    ExecuteIfEqual(TCommandIfEqual(Command));
    283325  end else
    284326  if Command is TCommandRepeat then begin
  • branches/easy compiler/USourceGenerator.pas

    r147 r148  
    4444    else if ValueType.Name = 'Integer' then
    4545      Result := Result + 'Integer'
     46    else if ValueType.Name = 'StringArray' then
     47      Result := Result + 'array of string'
     48    else if ValueType.Name = 'IntegerArray' then
     49      Result := Result + 'array of Integer'
    4650    else raise Exception.Create('Unsupported type');
    4751    Result := Result + ';' + LineEnding;
     
    6670  if Reference is TSourceReferenceVariable then begin
    6771    Result := Result + TSourceReferenceVariable(Reference).Variable.Name;
     72  end else
     73  if Reference is TSourceReferenceArray then begin
     74    Result := Result + TSourceReferenceArray(Reference).ArrayRef.Name +
     75      '[' + GenerateRef(TSourceReferenceArray(Reference).Index) + ']';
    6876  end else raise Exception.Create('Unsupported parameter type');
    6977end;
     
    116124    Result := Result + IndentStr + 'until False;' + LineEnding;
    117125  end else
    118   if Command is TCommandIfZero then begin
    119     Result := Result + IndentStr + 'if ' + TCommandIfZero(Command).Variable.Variable.Name + ' = 0 then ';
     126  if Command is TCommandIfEqual then begin
     127    Result := Result + IndentStr + 'if ' + GenerateRef(TCommandIfEqual(Command).Reference1) +
     128      ' = ' + GenerateRef(TCommandIfEqual(Command).Reference2) + ' then ';
    120129  end else
    121130  raise Exception.Create('Unsupported instruction');
Note: See TracChangeset for help on using the changeset viewer.