Changeset 147 for branches/easy compiler
- Timestamp:
- Jan 17, 2018, 3:34:13 PM (7 years ago)
- Location:
- branches/easy compiler
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/easy compiler/Steps.txt
r144 r147 20 20 Add begin-end block support 21 21 - local variables, constants, types 22 22 Add ifzero support 23 - if condition is valid then skip next command 24 Add Repeat keyword 25 - can be exited by Break command and reiterated by Continue 23 26 24 27 TODO: -
branches/easy compiler/UCompiler.pas
r146 r147 44 44 procedure Parse(Code: TSourceCode); 45 45 function ParseBeginEnd(SourceCode: TSourceCode; out BeginEnd: TCommandBeginEnd): Boolean; 46 function ParseBreak(SourceCode: TSourceCode; out CommandBreak: TCommandBreak 47 ): Boolean; 48 function ParseCommand(SourceCode: TSourceCode; out Command: TSourceCommand 49 ): Boolean; 46 50 function ParseFunctionCall(SourceCode: TSourceCode; out FunctionCall: TCommandFunctionCall): Boolean; 47 51 function ParseIfZero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean; 48 52 function ParseReference(SourceCode: TSourceCode): TSourceReference; 49 53 function ParseReferenceVariable(SourceCode: TSourceCode): TSourceReference; 54 function ParseRepeat(SourceCode: TSourceCode; out 55 CommandRepeat: TCommandRepeat): Boolean; 50 56 function ParseVar(SourceCode: TSourceCode): Boolean; 51 57 public … … 306 312 if Keyword = 'ifzero' then begin 307 313 IfZero := TCommandIfZero.Create; 308 IfZero.Variable := TSourceReferenceVariable(ParseReferenceVariable(SourceCode)).Variable; 309 Result := True; 310 end; 311 if not Result then Tokenizer.TokenIndex := TokenIndex; 312 end; 313 314 function TCompiler.ParseBeginEnd(SourceCode: TSourceCode; out BeginEnd: TCommandBeginEnd): Boolean; 315 var 316 Token: TSourceToken; 314 IfZero.Variable := TSourceReferenceVariable(ParseReferenceVariable(SourceCode)); 315 Result := True; 316 end; 317 if not Result then Tokenizer.TokenIndex := TokenIndex; 318 end; 319 320 function TCompiler.ParseBreak(SourceCode: TSourceCode; out CommandBreak: TCommandBreak): Boolean; 321 var 322 Token: TSourceToken; 323 TokenIndex: Integer; 317 324 Keyword: string; 318 TokenIndex: Integer; 325 begin 326 Result := False; 327 TokenIndex := Tokenizer.TokenIndex; 328 Token := Tokenizer.GetNext; 329 Keyword := LowerCase(Token.Text); 330 if Keyword = 'break' then begin 331 CommandBreak := TCommandBreak.Create; 332 Result := True; 333 end; 334 if not Result then Tokenizer.TokenIndex := TokenIndex; 335 end; 336 337 function TCompiler.ParseRepeat(SourceCode: TSourceCode; out CommandRepeat: TCommandRepeat): Boolean; 338 var 339 Token: TSourceToken; 340 TokenIndex: Integer; 341 Keyword: string; 342 Command: TSourceCommand; 343 begin 344 Result := False; 345 TokenIndex := Tokenizer.TokenIndex; 346 Token := Tokenizer.GetNext; 347 Keyword := LowerCase(Token.Text); 348 if Keyword = 'repeat' then begin 349 CommandRepeat := TCommandRepeat.Create; 350 if ParseCommand(SourceCode, Command) then begin 351 CommandRepeat := TCommandRepeat.Create; 352 CommandRepeat.Command := Command; 353 Command.Parent := CommandRepeat; 354 end else 355 raise Exception.Create('Unexpected token'); 356 Result := True; 357 end; 358 if not Result then Tokenizer.TokenIndex := TokenIndex; 359 end; 360 361 function TCompiler.ParseCommand(SourceCode: TSourceCode; out Command: TSourceCommand): Boolean; 362 var 319 363 CommandBeginEnd: TCommandBeginEnd; 320 364 CommandIfZero: TCommandIfZero; 321 365 CommandFunctionCall: TCommandFunctionCall; 366 CommandBreak: TCommandBreak; 367 CommandRepeat: TCommandRepeat; 368 begin 369 Command := nil; 370 Result := True; 371 if ParseVar(SourceCode) then else 372 if ParseBeginEnd(SourceCode, CommandBeginEnd) then begin 373 Command := CommandBeginEnd; 374 end else 375 if ParseIfZero(SourceCode, CommandIfZero) then begin 376 Command := CommandIfZero; 377 end else 378 if ParseBreak(SourceCode, CommandBreak) then begin 379 Command := CommandBreak; 380 end else 381 if ParseRepeat(SourceCode, CommandRepeat) then begin 382 Command := CommandRepeat; 383 end else 384 if ParseFunctionCall(SourceCode, CommandFunctionCall) then begin 385 Command := CommandFunctionCall; 386 end else Result := False; 387 end; 388 389 function TCompiler.ParseBeginEnd(SourceCode: TSourceCode; out BeginEnd: TCommandBeginEnd): Boolean; 390 var 391 Token: TSourceToken; 392 Keyword: string; 393 TokenIndex: Integer; 394 Command: TSourceCommand; 322 395 begin 323 396 Result := False; … … 329 402 BeginEnd.SourceCode := SourceCode; 330 403 while True do begin 331 if ParseVar(SourceCode) then 332 else if ParseBeginEnd(SourceCode, CommandBeginEnd) then 333 BeginEnd.Instructions.Add(CommandBeginEnd) 334 else if ParseIfZero(SourceCode, CommandIfZero) then 335 BeginEnd.Instructions.Add(CommandIfZero) 336 else if ParseFunctionCall(SourceCode, CommandFunctionCall) then 337 BeginEnd.Instructions.Add(CommandFunctionCall) 338 else if Tokenizer.CheckNext('end', stIdentifier) then begin 404 if ParseCommand(SourceCode, Command) then begin 405 if Assigned(Command) then begin 406 BeginEnd.Commands.Add(Command); 407 Command.Parent := BeginEnd; 408 end; 409 end else 410 if Tokenizer.CheckNext('end', stIdentifier) then begin 339 411 Break; 340 end 341 else raise Exception.Create('Unknown token: ' + Keyword); 412 end else begin 413 Token := Tokenizer.GetNext; 414 Keyword := LowerCase(Token.Text); 415 raise Exception.Create('Unknown token: ' + Keyword); 416 end; 342 417 end; 343 418 Token := Tokenizer.GetNext; -
branches/easy compiler/UFormMain.pas
r146 r147 55 55 Add('var I Integer'); 56 56 Add('Assign I 10'); 57 //Add('Repeat');57 Add('Repeat'); 58 58 Add('Begin'); 59 //Add('Decrement I 1'); 59 Add('PrintLn I'); 60 Add('Decrement I 1'); 60 61 Add('IfZero I'); 61 Add('Print ''condition'''); 62 //Add('Break'); 62 Add('Break'); 63 63 Add('End'); 64 64 Add('End'); -
branches/easy compiler/USourceCode.pas
r146 r147 10 10 type 11 11 TSourceCommand = class 12 end; 13 14 TSourceInstructions = class(TObjectList) 12 Parent: TSourceCommand; 13 end; 14 15 TSourceCommands = class(TObjectList) 15 16 end; 16 17 … … 140 141 TCommandBeginEnd = class(TSourceCommand) 141 142 SourceCode: TSourceCode; 142 Instructions: TSourceInstructions;143 Commands: TSourceCommands; 143 144 constructor Create; 144 145 destructor Destroy; override; 145 146 end; 146 147 148 { TCommandIfZero } 149 147 150 TCommandIfZero = class(TSourceCommand) 148 Variable: TSourceVariable; 151 Variable: TSourceReferenceVariable; 152 destructor Destroy; override; 153 end; 154 155 { TCommandRepeat } 156 157 TCommandRepeat = class(TSourceCommand) 158 Command: TSourceCommand; 159 destructor Destroy; override; 160 end; 161 162 TCommandBreak = class(TSourceCommand) 163 end; 164 165 TCommandContinue = class(TSourceCommand) 149 166 end; 150 167 … … 167 184 implementation 168 185 186 { TCommandIfZero } 187 188 destructor TCommandIfZero.Destroy; 189 begin 190 Variable.Free; 191 inherited Destroy; 192 end; 193 194 { TCommandRepeat } 195 196 destructor TCommandRepeat.Destroy; 197 begin 198 Command.Free; 199 inherited Destroy; 200 end; 201 169 202 { TSourceConstant } 170 203 … … 192 225 constructor TCommandBeginEnd.Create; 193 226 begin 194 Instructions := TSourceInstructions.Create;227 Commands := TSourceCommands.Create; 195 228 end; 196 229 197 230 destructor TCommandBeginEnd.Destroy; 198 231 begin 199 Instructions.Free;232 Commands.Free; 200 233 inherited Destroy; 201 234 end; … … 388 421 389 422 Funct := Functions.AddNew('increment'); 423 Funct.AddParameter('Variable', pkVariable); 424 Funct.AddParameter('Addition', pkString); 425 426 Funct := Functions.AddNew('decrement'); 390 427 Funct.AddParameter('Variable', pkVariable); 391 428 Funct.AddParameter('Addition', pkString); -
branches/easy compiler/USourceExecutor.pas
r146 r147 22 22 TExecutorVariables = class(TObjectList) 23 23 function Search(Variable: TSourceVariable): TExecutorVariable; 24 end; 25 26 TExecutorRepeat = class 27 RepeatCommand: TCommandRepeat; 28 Terminated: Boolean; 29 end; 30 31 { TExecutorRepeats } 32 33 TExecutorRepeats = class(TObjectList) 34 function Search(RepeatCommand: TCommandRepeat): TExecutorRepeat; 24 35 end; 25 36 … … 31 42 FOnOutput: TOutputEvent; 32 43 Variables: TExecutorVariables; 44 RepeatBlocks: TExecutorRepeats; 45 SkipNext: Boolean; 33 46 procedure ExecuteBeginEnd(BeginEnd: TCommandBeginEnd); 47 procedure ExecuteCommand(Command: TSourceCommand); 48 procedure ExecuteBreak(CommandBreak: TCommandBreak); 49 procedure ExecuteRepeat(CommandRepeat: TCommandRepeat); 50 function ReadValueReference(Reference: TSourceReference): TSourceValue; 51 function ReadVarReference(Reference: TSourceReference): TSourceVariable; 34 52 public 35 53 constructor Create; … … 43 61 implementation 44 62 63 { TExecutorRepeat } 64 65 function TExecutorRepeats.Search(RepeatCommand: TCommandRepeat): TExecutorRepeat; 66 var 67 Item: TExecutorRepeat; 68 begin 69 Result := nil; 70 for Item in Self do 71 if Item.RepeatCommand = RepeatCommand then begin 72 Result := Item; 73 Break; 74 end; 75 end; 76 45 77 { TExecutorVariable } 46 78 … … 71 103 begin 72 104 Variables := TExecutorVariables.Create; 105 RepeatBlocks := TExecutorRepeats.Create; 73 106 end; 74 107 75 108 destructor TSourceExecutor.Destroy; 76 109 begin 110 RepeatBlocks.Free; 77 111 Variables.Free; 78 112 inherited Destroy; … … 81 115 procedure TSourceExecutor.Execute(SourceCode: TSourceCode); 82 116 begin 117 SkipNext := False; 83 118 ExecuteBeginEnd(SourceCode.Main); 84 119 end; 85 120 121 function TSourceExecutor.ReadValueReference(Reference: TSourceReference): TSourceValue; 122 begin 123 Result := nil; 124 if Reference is TSourceReferenceConstant then begin 125 Result := TSourceReferenceConstant(Reference).Constant.Value; 126 end else 127 if Reference is TSourceReferenceVariable then begin 128 Result := Variables.Search(TSourceReferenceVariable(Reference).Variable).Value; 129 end else raise Exception.Create('Unsupported reference'); 130 end; 131 132 function TSourceExecutor.ReadVarReference(Reference: TSourceReference): TSourceVariable; 133 begin 134 Result := nil; 135 if Reference is TSourceReferenceVariable then begin 136 Result := TSourceReferenceVariable(Reference).Variable; 137 end else raise Exception.Create('Unsupported reference'); 138 end; 139 86 140 procedure TSourceExecutor.ExecuteBeginEnd(BeginEnd: TCommandBeginEnd); 87 141 var 88 142 IP: Integer; 89 Instruction: TSourceCommand; 143 begin 144 IP := 0; 145 while IP < BeginEnd.Commands.Count do begin 146 if SkipNext then begin 147 SkipNext := False; 148 Inc(IP); 149 Continue; 150 end; 151 ExecuteCommand(TSourceCommand(BeginEnd.Commands[IP])); 152 Inc(IP); 153 end; 154 end; 155 156 procedure TSourceExecutor.ExecuteBreak(CommandBreak: TCommandBreak); 157 var 158 RepeatBlock: TSourceCommand; 159 ExecutorRepeat: TExecutorRepeat; 160 begin 161 RepeatBlock := CommandBreak.Parent; 162 while not (RepeatBlock is TCommandRepeat) and (RepeatBlock <> nil) do 163 RepeatBlock := RepeatBlock.Parent; 164 if Assigned(RepeatBlock) then begin 165 ExecutorRepeat := RepeatBlocks.Search(RepeatBlock as TCommandRepeat); 166 if Assigned(ExecutorRepeat) then begin 167 ExecutorRepeat.Terminated := True; 168 end else 169 raise Exception.Create('Missing executor repeat block'); 170 end else 171 raise Exception.Create('Used break outside repeat loop'); 172 end; 173 174 procedure TSourceExecutor.ExecuteRepeat(CommandRepeat: TCommandRepeat); 175 var 176 RepeatBlock: TExecutorRepeat; 177 begin 178 RepeatBlock := TExecutorRepeat.Create; 179 RepeatBlock.RepeatCommand := CommandRepeat; 180 RepeatBlock.Terminated := False; 181 RepeatBlocks.Add(RepeatBlock); 182 repeat 183 ExecuteCommand(CommandRepeat.Command); 184 until RepeatBlock.Terminated; 185 RepeatBlocks.Remove(RepeatBlock); 186 end; 187 188 procedure TSourceExecutor.ExecuteCommand(Command: TSourceCommand); 189 var 90 190 Variable: TSourceVariable; 91 191 Value: TSourceValue; … … 93 193 Text: string; 94 194 IntValue: Integer; 95 SkipNext: Boolean; 96 97 function ReadValueReference(Reference: TSourceReference): TSourceValue; 98 begin 99 Result := nil; 100 if Reference is TSourceReferenceConstant then begin 101 Result := TSourceReferenceConstant(Reference).Constant.Value; 102 end else 103 if Reference is TSourceReferenceVariable then begin 104 Result := Variables.Search(TSourceReferenceVariable(Reference).Variable).Value; 105 end else raise Exception.Create('Unsupported reference'); 106 end; 107 108 function ReadVarReference(Reference: TSourceReference): TSourceVariable; 109 begin 110 Result := nil; 111 if Reference is TSourceReferenceVariable then begin 112 Result := TSourceReferenceVariable(Reference).Variable; 113 end else raise Exception.Create('Unsupported reference'); 114 end; 115 116 begin 117 SkipNext := False; 118 IP := 0; 119 while IP < BeginEnd.Instructions.Count do begin 120 if SkipNext then begin 121 SkipNext := False; 122 Inc(IP); 123 Continue; 124 end; 125 Instruction := TSourceCommand(BeginEnd.Instructions[IP]); 126 if Instruction is TCommandFunctionCall then 127 with TCommandFunctionCall(Instruction) do begin 128 if Name = 'print' then begin 129 if Assigned(FOnOutput) then begin 130 Value := ReadValueReference(TSourceReference(Parameters[0])); 131 if Value is TSourceValueString then 132 FOnOutput(TSourceValueString(Value).Value) 133 else if Value is TSourceValueInteger then 134 FOnOutput(IntToStr(TSourceValueInteger(Value).Value)) 135 else raise Exception.Create('Unsupported value type'); 136 end; 195 begin 196 if Command is TCommandFunctionCall then 197 with TCommandFunctionCall(Command) do begin 198 if Name = 'print' then begin 199 if Assigned(FOnOutput) then begin 200 Value := ReadValueReference(TSourceReference(Parameters[0])); 201 if Value is TSourceValueString then 202 FOnOutput(TSourceValueString(Value).Value) 203 else if Value is TSourceValueInteger then 204 FOnOutput(IntToStr(TSourceValueInteger(Value).Value)) 205 else raise Exception.Create('Unsupported value type'); 206 end; 207 end else 208 if Name = 'println' then begin 209 if Assigned(FOnOutput) then begin 210 Value := ReadValueReference(TSourceReference(Parameters[0])); 211 if Value is TSourceValueString then 212 FOnOutput(TSourceValueString(Value).Value + LineEnding) 213 else if Value is TSourceValueInteger then 214 FOnOutput(IntToStr(TSourceValueInteger(Value).Value) + LineEnding) 215 else raise Exception.Create('Unsupported value type'); 216 end; 217 end else 218 if Name = 'inputln' then begin 219 if Assigned(FOnInput) then begin 220 Variable := ReadVarReference(TSourceReference(Parameters[0])); 221 ExecutorVar := Variables.Search(Variable); 222 if ExecutorVar.Value is TSourceValueString then begin 223 TSourceValueString(ExecutorVar.Value).Value := FOnInput; 224 FOnOutput(TSourceValueString(ExecutorVar.Value).Value + LineEnding); 225 end else 226 if ExecutorVar.Value is TSourceValueInteger then begin 227 Text := FOnInput; 228 if TryStrToInt(Text, IntValue) then 229 TSourceValueInteger(ExecutorVar.Value).Value := IntValue 230 else TSourceValueInteger(ExecutorVar.Value).Value := 0; 231 FOnOutput(IntToStr(TSourceValueInteger(ExecutorVar.Value).Value) + LineEnding); 232 end else 233 raise Exception.Create('Unsupported value type'); 234 end; 235 end else 236 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); 247 end else 248 if Name = 'increment' then begin 249 Variable := ReadVarReference(TSourceReference(Parameters[0])); 250 Value := ReadValueReference(TSourceReference(Parameters[1])); 251 ExecutorVar := Variables.Search(Variable); 252 if not Assigned(ExecutorVar) then raise Exception.Create('Variable not found'); 253 if (ExecutorVar.Value is TSourceValueInteger) and (Value is TSourceValueInteger) then 254 Inc(TSourceValueInteger(ExecutorVar.Value).Value, TSourceValueInteger(Value).Value) 255 else raise Exception.Create('Wrong type for increment'); 256 end else 257 if Name = 'decrement' then begin 258 Variable := ReadVarReference(TSourceReference(Parameters[0])); 259 Value := ReadValueReference(TSourceReference(Parameters[1])); 260 ExecutorVar := Variables.Search(Variable); 261 if not Assigned(ExecutorVar) then raise Exception.Create('Variable not found'); 262 if (ExecutorVar.Value is TSourceValueInteger) and (Value is TSourceValueInteger) then 263 Dec(TSourceValueInteger(ExecutorVar.Value).Value, TSourceValueInteger(Value).Value) 264 else raise Exception.Create('Wrong type for increment'); 265 end else 266 raise Exception.Create('Unsupported function: ' + TCommandFunctionCall(Command).Name); 267 end else 268 if Command is TCommandBeginEnd then begin 269 ExecuteBeginEnd(TCommandBeginEnd(Command)); 270 end else 271 if Command is TCommandBreak then begin 272 ExecuteBreak(TCommandBreak(Command)); 273 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; 137 279 end else 138 if Name = 'println' then begin 139 if Assigned(FOnOutput) then begin 140 Value := ReadValueReference(TSourceReference(Parameters[0])); 141 if Value is TSourceValueString then 142 FOnOutput(TSourceValueString(Value).Value + LineEnding) 143 else if Value is TSourceValueInteger then 144 FOnOutput(IntToStr(TSourceValueInteger(Value).Value) + LineEnding) 145 else raise Exception.Create('Unsupported value type'); 146 end; 147 end else 148 if Name = 'inputln' then begin 149 if Assigned(FOnInput) then begin 150 Variable := ReadVarReference(TSourceReference(Parameters[0])); 151 ExecutorVar := Variables.Search(Variable); 152 if ExecutorVar.Value is TSourceValueString then begin 153 TSourceValueString(ExecutorVar.Value).Value := FOnInput; 154 FOnOutput(TSourceValueString(ExecutorVar.Value).Value + LineEnding); 155 end else 156 if ExecutorVar.Value is TSourceValueInteger then begin 157 Text := FOnInput; 158 if TryStrToInt(Text, IntValue) then 159 TSourceValueInteger(ExecutorVar.Value).Value := IntValue 160 else TSourceValueInteger(ExecutorVar.Value).Value := 0; 161 FOnOutput(IntToStr(TSourceValueInteger(ExecutorVar.Value).Value) + LineEnding); 162 end else 163 raise Exception.Create('Unsupported value type'); 164 end; 165 end else 166 if Name = 'assign' then 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.ValueClass.Create; 175 end; 176 ExecutorVar.Value.Assign(Value); 177 end else 178 if Name = 'increment' then begin 179 Variable := ReadVarReference(TSourceReference(Parameters[0])); 180 Value := ReadValueReference(TSourceReference(Parameters[1])); 181 ExecutorVar := Variables.Search(Variable); 182 if not Assigned(ExecutorVar) then raise Exception.Create('Variable not found'); 183 if (ExecutorVar.Value is TSourceValueInteger) and (Value is TSourceValueInteger) then 184 Inc(TSourceValueInteger(ExecutorVar.Value).Value, TSourceValueInteger(Value).Value) 185 else raise Exception.Create('Wrong type for increment'); 186 end else 187 raise Exception.Create('Unsupported function: ' + TCommandFunctionCall(Instruction).Name); 188 end else 189 if Instruction is TCommandBeginEnd then begin 190 ExecuteBeginEnd(TCommandBeginEnd(Instruction)); 191 end else 192 if Instruction is TCommandIfZero then begin 193 ExecutorVar := Variables.Search(TCommandIfZero(Instruction).Variable); 194 if Assigned(ExecutorVar) then begin 195 if ExecutorVar.Variable.ValueType.Name = 'Integer' then begin 196 if TSourceValueInteger(ExecutorVar.Value).Value = 0 then SkipNext := True; 197 end else 198 raise Exception.Create('Can compare only integers'); 199 end else 200 raise Exception.Create('Variable not found'); 201 end else 202 raise Exception.Create('Unsupported instruction'); 203 Inc(IP); 204 end; 280 raise Exception.Create('Can compare only integers'); 281 end else 282 raise Exception.Create('Variable not found'); 283 end else 284 if Command is TCommandRepeat then begin 285 ExecuteRepeat(Command as TCommandRepeat); 286 end else 287 raise Exception.Create('Unsupported instruction'); 205 288 end; 206 289 -
branches/easy compiler/USourceGenerator.pas
r146 r147 15 15 Indent: Integer; 16 16 function GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string; 17 function GenerateCommand(Command: TSourceCommand): string; 18 function GenerateRef(Reference: TSourceReference): string; 17 19 function IndentStr: string; 18 20 public … … 49 51 end; 50 52 51 function TSourceGenerator.Generate BeginEnd(BeginEnd: TCommandBeginEnd): string;53 function TSourceGenerator.GenerateRef(Reference: TSourceReference): string; 52 54 var 53 Instruction: TSourceCommand;54 I: Integer;55 55 Value: TSourceValue; 56 57 function GenerateRef(Reference: TSourceReference): string;58 56 begin 59 57 Result := ''; … … 71 69 end; 72 70 71 function TSourceGenerator.GenerateCommand(Command: TSourceCommand): string; 72 begin 73 Result := ''; 74 if Command is TCommandFunctionCall then 75 with TCommandFunctionCall(Command) do begin 76 if Name = 'print' then begin 77 Result := Result + IndentStr + 'Write(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + 78 LineEnding; 79 end else 80 if Name = 'println' then begin 81 Result := Result + IndentStr + 'WriteLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + 82 LineEnding; 83 end else 84 if Name = 'assign' then begin 85 Result := Result + IndentStr + GenerateRef(TSourceReference(Parameters[0])) + ' := ' + 86 GenerateRef(TSourceReference(Parameters[1])) + ';' + LineEnding; 87 end else 88 if Name = 'inputln' then begin 89 Result := Result + IndentStr + 'ReadLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + LineEnding; 90 end else 91 if Name = 'increment' then begin 92 Result := Result + IndentStr + 'Inc(' + GenerateRef(TSourceReference(Parameters[0])) + ', ' + 93 GenerateRef(TSourceReference(Parameters[1])) + ');' + LineEnding; 94 end else 95 if Name = 'decrement' then begin 96 Result := Result + IndentStr + 'Dec(' + GenerateRef(TSourceReference(Parameters[0])) + ', ' + 97 GenerateRef(TSourceReference(Parameters[1])) + ');' + LineEnding; 98 end else 99 raise Exception.Create('Unsupported instruction name.'); 100 end else 101 if Command is TCommandBeginEnd then begin 102 Result := Result + GenerateBeginEnd(TCommandBeginEnd(Command)) + 103 ';' + LineEnding; 104 end else 105 if Command is TCommandBreak then begin 106 Result := Result + IndentStr + 'Break;' + LineEnding; 107 end else 108 if Command is TCommandContinue then begin 109 Result := Result + IndentStr + 'Continue;' + LineEnding; 110 end else 111 if Command is TCommandRepeat then begin 112 Result := Result + IndentStr + 'repeat' + LineEnding; 113 Inc(Indent); 114 Result := Result + IndentStr + GenerateCommand(TCommandRepeat(Command).Command) + LineEnding; 115 Dec(Indent); 116 Result := Result + IndentStr + 'until False;' + LineEnding; 117 end else 118 if Command is TCommandIfZero then begin 119 Result := Result + IndentStr + 'if ' + TCommandIfZero(Command).Variable.Variable.Name + ' = 0 then '; 120 end else 121 raise Exception.Create('Unsupported instruction'); 122 end; 123 124 function TSourceGenerator.GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string; 125 var 126 I: Integer; 73 127 begin 74 128 Result := ''; … … 76 130 Inc(Indent); 77 131 with BeginEnd do 78 for I := 0 to Instructions.Count - 1 do begin 79 Instruction := TSourceCommand(Instructions[I]); 80 if Instruction is TCommandFunctionCall then 81 with TCommandFunctionCall(Instruction) do begin 82 if Name = 'print' then begin 83 Result := Result + IndentStr + 'Write(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + 84 LineEnding; 85 end else 86 if Name = 'println' then begin 87 Result := Result + IndentStr + 'WriteLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + 88 LineEnding; 89 end else 90 if Name = 'assign' then begin 91 Result := Result + IndentStr + GenerateRef(TSourceReference(Parameters[0])) + ' := ' + 92 GenerateRef(TSourceReference(Parameters[1])) + ';' + LineEnding; 93 end else 94 if Name = 'inputln' then begin 95 Result := Result + IndentStr + 'ReadLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + LineEnding; 96 end else 97 if Name = 'increment' then begin 98 Result := Result + IndentStr + 'Inc(' + GenerateRef(TSourceReference(Parameters[0])) + ', ' + 99 GenerateRef(TSourceReference(Parameters[1])) + ');' + LineEnding; 100 end else 101 raise Exception.Create('Unsupported instruction name.'); 102 end else 103 if Instruction is TCommandBeginEnd then begin 104 Result := Result + GenerateBeginEnd(TCommandBeginEnd(Instruction)) + 105 ';' + LineEnding; 106 end else 107 if Instruction is TCommandIfZero then begin 108 Result := Result + IndentStr + 'if ' + TCommandIfZero(Instruction).Variable.Name + ' = 0 then '; 109 end else 110 raise Exception.Create('Unsupported instruction'); 132 for I := 0 to Commands.Count - 1 do begin 133 Result := Result + GenerateCommand(TSourceCommand(Commands[I])); 111 134 end; 112 135 Dec(Indent);
Note:
See TracChangeset
for help on using the changeset viewer.