Changeset 148
- Timestamp:
- Jan 17, 2018, 5:27:23 PM (7 years ago)
- Location:
- branches/easy compiler
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/easy compiler/UCompiler.pas
r147 r148 9 9 10 10 type 11 TSourceTokenKind = (stNone, stString, stIdentifier, stEof, stInteger); 11 TSourceTokenKind = (stNone, stString, stIdentifier, stEof, stInteger, 12 stSpecialSymbol); 12 13 TSourceToken = record 13 14 Text: string; … … 49 50 ): Boolean; 50 51 function ParseFunctionCall(SourceCode: TSourceCode; out FunctionCall: TCommandFunctionCall): Boolean; 51 function ParseIf Zero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean;52 function ParseIfEqual(SourceCode: TSourceCode; out IfZero: TCommandIfEqual): Boolean; 52 53 function ParseReference(SourceCode: TSourceCode): TSourceReference; 53 54 function ParseReferenceVariable(SourceCode: TSourceCode): TSourceReference; … … 126 127 procedure TTokenizer.Tokenize(Text: string; Tokens: TSourceTokens); 127 128 type 128 TTokenizerState = (tsNone, tsIdentifier, tsString, tsInteger );129 TTokenizerState = (tsNone, tsIdentifier, tsString, tsInteger, tsSpecialSymbol); 129 130 var 130 131 State: TTokenizerState; … … 153 154 Token := ''; 154 155 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]); 156 160 end else 157 161 if State = tsIdentifier then begin 158 162 if IsAlphaNumeric(Text[I]) then begin 159 163 Token := Token + Text[I]; 160 end else 161 if IsWhiteSpace(Text[I]) then begin 164 end else begin 162 165 Tokens.AddToken(stIdentifier, Token); 163 166 State := tsNone; 164 167 Dec(I); 165 end else 166 raise Exception.Create('Unexpected character'); 168 end; 167 169 end else 168 170 if State = tsInteger then begin 169 171 if IsDigit(Text[I]) then begin 170 172 Token := Token + Text[I]; 171 end else 172 if IsWhiteSpace(Text[I]) then begin 173 end else begin 173 174 Tokens.AddToken(stInteger, Token); 174 175 State := tsNone; 175 176 Dec(I); 176 end else 177 raise Exception.Create('Unexpected character'); 177 end; 178 178 end else 179 179 if State = tsString then begin … … 230 230 var 231 231 Token: TSourceToken; 232 Token2: TSourceToken; 232 233 NewReference: TSourceReference; 233 234 begin … … 239 240 end else 240 241 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; 246 260 end else 247 261 if Token.Kind = stInteger then begin … … 257 271 var 258 272 Token: TSourceToken; 273 Token2: TSourceToken; 259 274 NewReference: TSourceReference; 260 275 begin 261 276 Token := Tokenizer.GetNext; 262 277 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; 269 296 end else raise Exception.Create('Unexpected parameter'); 270 297 Result := NewReference; … … 300 327 end; 301 328 302 function TCompiler.ParseIf Zero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean;329 function TCompiler.ParseIfEqual(SourceCode: TSourceCode; out IfZero: TCommandIfEqual): Boolean; 303 330 var 304 331 Token: TSourceToken; … … 310 337 Token := Tokenizer.GetNext; 311 338 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); 315 343 Result := True; 316 344 end; … … 362 390 var 363 391 CommandBeginEnd: TCommandBeginEnd; 364 CommandIfZero: TCommandIf Zero;392 CommandIfZero: TCommandIfEqual; 365 393 CommandFunctionCall: TCommandFunctionCall; 366 394 CommandBreak: TCommandBreak; … … 373 401 Command := CommandBeginEnd; 374 402 end else 375 if ParseIf Zero(SourceCode, CommandIfZero) then begin403 if ParseIfEqual(SourceCode, CommandIfZero) then begin 376 404 Command := CommandIfZero; 377 405 end else -
branches/easy compiler/UFormMain.pas
r147 r148 51 51 procedure TForm1.FormShow(Sender: TObject); 52 52 begin 53 with MemoSource.Lines do begin53 { with MemoSource.Lines do begin 54 54 Add('Begin'); 55 55 Add('var I Integer'); … … 59 59 Add('PrintLn I'); 60 60 Add('Decrement I 1'); 61 Add('If Zero I');61 Add('IfEqual I 0'); 62 62 Add('Break'); 63 63 Add('End'); 64 64 Add('End'); 65 65 end; 66 {with MemoSource.Lines do begin66 with MemoSource.Lines do begin 67 67 Add('PrintLn ''Super Calculator'''); 68 68 Add('var Value1 Integer'); … … 103 103 Add('PrintLn Text3'); 104 104 end; 105 105 } 106 106 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'); 107 113 Add('Assign AnimalName[0] ''an elephant'''); 108 114 Add('Assign AnimalProperty[0] ''It is big and slow'''); … … 122 128 Add('IfEqual Answer ''y'''); 123 129 Add('Begin'); 124 Add('PrintLn ''That ''s clear. It is ''');130 Add('PrintLn ''Thats clear. It is '''); 125 131 Add('PrintLn AnimalName[I]'); 126 132 Add('Break'); 127 133 Add('End'); 128 Add('Increment I ');129 Add('If HigherOrEqual I AnimalCount');134 Add('Increment I 1'); 135 Add('IfEqual I AnimalCount'); 130 136 Add('Break'); 131 137 Add('End'); … … 138 144 Add('PrintLn '''''); 139 145 Add('End'); 140 end; 141 } 146 Add('End'); 147 end; 148 142 149 end; 143 150 -
branches/easy compiler/USourceCode.pas
r147 r148 28 28 end; 29 29 30 TSourceValues = class(TObjectList) 31 end; 32 30 33 TSourceValueClass = class of TSourceValue; 31 34 … … 34 37 TSourceType = class 35 38 Name: string; 36 ValueClass: TSourceValueClass; 37 end; 39 function GetValueType: TSourceValueClass; virtual; 40 end; 41 42 TSourceTypeClass = class of TSourceType; 38 43 39 44 { TSourceTypes } … … 41 46 TSourceTypes = class(TObjectList) 42 47 Parent: TSourceTypes; 43 function AddNew(Name: string; ClassType: TSource ValueClass): TSourceType;48 function AddNew(Name: string; ClassType: TSourceTypeClass): TSourceType; 44 49 function Search(Name: string): TSourceType; 45 50 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 46 71 47 72 { TSourceVariable } … … 64 89 end; 65 90 91 TSourceReferenceArray = class(TSourceReference) 92 ArrayRef: TSourceVariable; 93 Index: TSourceReference; 94 end; 95 66 96 { TSourceValueString } 67 97 … … 76 106 Value: Integer; 77 107 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; 78 117 end; 79 118 … … 146 185 end; 147 186 148 { TCommandIfZero } 149 150 TCommandIfZero = class(TSourceCommand) 151 Variable: TSourceReferenceVariable; 187 { TCommandIfEqual } 188 189 TCommandIfEqual = class(TSourceCommand) 190 Reference1: TSourceReference; 191 Reference2: TSourceReference; 152 192 destructor Destroy; override; 153 193 end; … … 184 224 implementation 185 225 186 { TCommandIfZero } 187 188 destructor TCommandIfZero.Destroy; 189 begin 190 Variable.Free; 226 { TSourceType } 227 228 function TSourceType.GetValueType: TSourceValueClass; 229 begin 230 Result := nil; 231 end; 232 233 { TSourceTypeInteger } 234 235 function TSourceTypeInteger.GetValueType: TSourceValueClass; 236 begin 237 Result := TSourceValueInteger; 238 end; 239 240 { TSourceTypeString } 241 242 function TSourceTypeString.GetValueType: TSourceValueClass; 243 begin 244 Result := TSourceValueString; 245 end; 246 247 { TSourceTypeArray } 248 249 function TSourceTypeArray.GetValueType: TSourceValueClass; 250 begin 251 Result := TSourceValueArray; 252 end; 253 254 { TSourceValueArray } 255 256 procedure TSourceValueArray.Assign(Source: TSourceValue); 257 var 258 I: Integer; 259 Value: TSourceValue; 260 begin 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'); 272 end; 273 274 constructor TSourceValueArray.Create; 275 begin 276 Items := TSourceValues.Create; 277 end; 278 279 destructor TSourceValueArray.Destroy; 280 begin 281 Items.Free; 282 inherited Destroy; 283 end; 284 285 { TCommandIfEqual } 286 287 destructor TCommandIfEqual.Destroy; 288 begin 289 Reference1.Free; 290 Reference2.Free; 191 291 inherited Destroy; 192 292 end; … … 236 336 { TSourceTypes } 237 337 238 function TSourceTypes.AddNew(Name: string; ClassType: TSource ValueClass): TSourceType;239 begin 240 Result := TSourceType.Create;338 function TSourceTypes.AddNew(Name: string; ClassType: TSourceTypeClass): TSourceType; 339 begin 340 Result := ClassType.Create; 241 341 Result.Name := Name; 242 Result.ValueClass := ClassType;243 342 Add(Result); 244 343 end; … … 395 494 var 396 495 Funct: TSourceFunction; 496 Typ: TSourceType; 397 497 begin 398 498 Functions.Clear; 399 499 400 500 // 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; 403 507 404 508 // Init functions -
branches/easy compiler/USourceExecutor.pas
r147 r148 44 44 RepeatBlocks: TExecutorRepeats; 45 45 SkipNext: Boolean; 46 procedure ExecuteAssign(CommandAssign: TCommandFunctionCall); 46 47 procedure ExecuteBeginEnd(BeginEnd: TCommandBeginEnd); 47 48 procedure ExecuteCommand(Command: TSourceCommand); 48 49 procedure ExecuteBreak(CommandBreak: TCommandBreak); 50 procedure ExecuteIfEqual(IfEqual: TCommandIfEqual); 49 51 procedure ExecuteRepeat(CommandRepeat: TCommandRepeat); 50 52 function ReadValueReference(Reference: TSourceReference): TSourceValue; … … 120 122 121 123 function TSourceExecutor.ReadValueReference(Reference: TSourceReference): TSourceValue; 124 var 125 ArrayIndex: TSourceValue; 122 126 begin 123 127 Result := nil; … … 127 131 if Reference is TSourceReferenceVariable then begin 128 132 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'); 130 141 end; 131 142 132 143 function TSourceExecutor.ReadVarReference(Reference: TSourceReference): TSourceVariable; 144 var 145 ArrayIndex: TSourceValue; 133 146 begin 134 147 Result := nil; 135 148 if Reference is TSourceReferenceVariable then begin 136 149 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); 137 157 end else raise Exception.Create('Unsupported reference'); 158 end; 159 160 procedure TSourceExecutor.ExecuteAssign(CommandAssign: TCommandFunctionCall); 161 var 162 Variable: TSourceVariable; 163 Value: TSourceValue; 164 ExecutorVar: TExecutorVariable; 165 begin 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; 138 178 end; 139 179 … … 170 210 end else 171 211 raise Exception.Create('Used break outside repeat loop'); 212 end; 213 214 procedure TSourceExecutor.ExecuteIfEqual(IfEqual: TCommandIfEqual); 215 var 216 Value1: TSourceValue; 217 Value2: TSourceValue; 218 begin 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.'); 172 230 end; 173 231 … … 235 293 end else 236 294 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)); 247 296 end else 248 297 if Name = 'increment' then begin … … 272 321 ExecuteBreak(TCommandBreak(Command)); 273 322 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)); 283 325 end else 284 326 if Command is TCommandRepeat then begin -
branches/easy compiler/USourceGenerator.pas
r147 r148 44 44 else if ValueType.Name = 'Integer' then 45 45 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' 46 50 else raise Exception.Create('Unsupported type'); 47 51 Result := Result + ';' + LineEnding; … … 66 70 if Reference is TSourceReferenceVariable then begin 67 71 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) + ']'; 68 76 end else raise Exception.Create('Unsupported parameter type'); 69 77 end; … … 116 124 Result := Result + IndentStr + 'until False;' + LineEnding; 117 125 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 '; 120 129 end else 121 130 raise Exception.Create('Unsupported instruction');
Note:
See TracChangeset
for help on using the changeset viewer.