- Timestamp:
- Jan 17, 2018, 2:25:45 PM (7 years ago)
- Location:
- branches/easy compiler
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/easy compiler/UCompiler.pas
r145 r146 33 33 function IsKeyword(Text: string): Boolean; 34 34 function GetNext(Kind: TSourceTokenKind = stNone): TSourceToken; 35 function CheckNext(Text: string; Kind: TSourceTokenKind): Boolean; 35 36 procedure Tokenize(Text: string; Tokens: TSourceTokens); 36 37 end; … … 42 43 Tokenizer: TTokenizer; 43 44 procedure Parse(Code: TSourceCode); 44 procedure ParseBeginEnd(BeginEnd: TSourceBeginEnd); 45 function ParseBeginEnd(SourceCode: TSourceCode; out BeginEnd: TCommandBeginEnd): Boolean; 46 function ParseFunctionCall(SourceCode: TSourceCode; out FunctionCall: TCommandFunctionCall): Boolean; 47 function ParseIfZero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean; 48 function ParseReference(SourceCode: TSourceCode): TSourceReference; 49 function ParseReferenceVariable(SourceCode: TSourceCode): TSourceReference; 50 function ParseVar(SourceCode: TSourceCode): Boolean; 45 51 public 46 52 procedure Compile(Source: string; SourceCode: TSourceCode); … … 99 105 if (Kind <> stNone) and (Result.Kind <> Kind) then 100 106 raise Exception.Create('Unexpected token type'); 107 end; 108 109 function TTokenizer.CheckNext(Text: string; Kind: TSourceTokenKind): Boolean; 110 var 111 Index: Integer; 112 Token: TSourceToken; 113 begin 114 Index := TokenIndex; 115 Token := GetNext; 116 Result := (LowerCase(Token.Text) = Text) and (Token.Kind = Kind); 117 TokenIndex := Index; 101 118 end; 102 119 … … 172 189 begin 173 190 Tokenizer.TokenIndex := 0; 174 ParseBeginEnd(Code .Main);175 end; 176 177 procedure TCompiler.ParseBeginEnd(BeginEnd: TSourceBeginEnd);191 ParseBeginEnd(Code, Code.Main); 192 end; 193 194 function TCompiler.ParseVar(SourceCode: TSourceCode): Boolean; 178 195 var 179 196 Token: TSourceToken; 180 197 Token2: TSourceToken; 181 Keyword: string;182 Instruction: TSourceInstruction;183 NewReference: TSourceReference;184 Funct: TSourceFunction;185 Param: TSourceFunctionParameter;186 198 Variable: TSourceVariable; 187 199 ValueType: TSourceType; 188 189 function ParseReference: TSourceReference; 200 TokenIndex: Integer; 201 begin 202 Result := False; 203 TokenIndex := Tokenizer.TokenIndex; 204 Token := Tokenizer.GetNext; 205 if LowerCase(Token.Text) = 'var' then begin 206 Token := Tokenizer.GetNext; 207 Token2 := Tokenizer.GetNext; 208 if Token2.Kind <> stIdentifier then 209 raise Exception.Create('Expected type parameter'); 210 Variable := SourceCode.Variables.Search(Token.Text); 211 if not Assigned(Variable) then begin 212 ValueType := SourceCode.Types.Search(Token2.Text); 213 if not Assigned(ValueType) then 214 raise Exception.Create('Unsupported type: ' + Token2.Text); 215 Variable := SourceCode.Variables.AddNew(Token.Text, 216 ValueType); 217 end else raise Exception.Create('Variable redefined: ' + Token.Text); 218 Result := True; 219 end; 220 if not Result then Tokenizer.TokenIndex := TokenIndex; 221 end; 222 223 function TCompiler.ParseReference(SourceCode: TSourceCode): TSourceReference; 224 var 225 Token: TSourceToken; 226 NewReference: TSourceReference; 190 227 begin 191 228 Token := Tokenizer.GetNext; … … 193 230 NewReference := TSourceReferenceConstant.Create; 194 231 TSourceReferenceConstant(NewReference).Constant := 195 BeginEnd.SourceCode.Constants.AddNewString(Token.Text);232 SourceCode.Constants.AddNewString(Token.Text); 196 233 end else 197 234 if Token.Kind = stIdentifier then begin 198 235 NewReference := TSourceReferenceVariable.Create; 199 236 TSourceReferenceVariable(NewReference).Variable := 200 BeginEnd.SourceCode.Variables.Search(Token.Text);237 SourceCode.Variables.Search(Token.Text); 201 238 if TSourceReferenceVariable(NewReference).Variable = nil then 202 239 raise Exception.Create('Variable not found: ' + Token.Text); … … 205 242 NewReference := TSourceReferenceConstant.Create; 206 243 TSourceReferenceConstant(NewReference).Constant := 207 BeginEnd.SourceCode.Constants.AddNewInteger(StrToInt(Token.Text));244 SourceCode.Constants.AddNewInteger(StrToInt(Token.Text)); 208 245 end else 209 246 raise Exception.Create('Unexpected parameter'); … … 211 248 end; 212 249 213 function ParseReferenceVariable(Initialize: Boolean = False): TSourceReference; 250 function TCompiler.ParseReferenceVariable(SourceCode: TSourceCode): TSourceReference; 251 var 252 Token: TSourceToken; 253 NewReference: TSourceReference; 214 254 begin 215 255 Token := Tokenizer.GetNext; … … 217 257 NewReference := TSourceReferenceVariable.Create; 218 258 TSourceReferenceVariable(NewReference).Variable := 219 BeginEnd.SourceCode.Variables.Search(Token.Text);259 SourceCode.Variables.Search(Token.Text); 220 260 if TSourceReferenceVariable(NewReference).Variable = nil then 221 261 raise Exception.Create('Variable not found: ' + Token.Text); … … 225 265 end; 226 266 227 begin 228 while True do begin 267 function TCompiler.ParseFunctionCall(SourceCode: TSourceCode; out FunctionCall: TCommandFunctionCall): Boolean; 268 var 269 Funct: TSourceFunction; 270 Param: TSourceFunctionParameter; 271 Token: TSourceToken; 272 TokenIndex: Integer; 273 Keyword: string; 274 begin 275 Result := False; 276 TokenIndex := Tokenizer.TokenIndex; 277 Token := Tokenizer.GetNext; 278 Keyword := LowerCase(Token.Text); 279 Funct := SourceCode.Functions.Search(Keyword); 280 if Assigned(Funct) then begin 281 FunctionCall := TCommandFunctionCall.Create; 282 FunctionCall.Name := Keyword; 283 for Param in Funct.Parameters do 284 if Param.Kind = pkString then begin 285 FunctionCall.Parameters.Add(ParseReference(SourceCode)) 286 end else 287 if Param.Kind = pkVariable then begin 288 FunctionCall.Parameters.Add(ParseReferenceVariable(SourceCode)); 289 end else 290 raise Exception.Create('Unsupported parameter type.'); 291 Result := True; 292 end; 293 if not Result then Tokenizer.TokenIndex := TokenIndex; 294 end; 295 296 function TCompiler.ParseIfZero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean; 297 var 298 Token: TSourceToken; 299 TokenIndex: Integer; 300 Keyword: string; 301 begin 302 Result := False; 303 TokenIndex := Tokenizer.TokenIndex; 304 Token := Tokenizer.GetNext; 305 Keyword := LowerCase(Token.Text); 306 if Keyword = 'ifzero' then begin 307 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; 317 Keyword: string; 318 TokenIndex: Integer; 319 CommandBeginEnd: TCommandBeginEnd; 320 CommandIfZero: TCommandIfZero; 321 CommandFunctionCall: TCommandFunctionCall; 322 begin 323 Result := False; 324 TokenIndex := Tokenizer.TokenIndex; 325 Token := Tokenizer.GetNext; 326 Keyword := LowerCase(Token.Text); 327 if Keyword = 'begin' then begin 328 BeginEnd := TCommandBeginEnd.Create; 329 BeginEnd.SourceCode := SourceCode; 330 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 339 Break; 340 end 341 else raise Exception.Create('Unknown token: ' + Keyword); 342 end; 229 343 Token := Tokenizer.GetNext; 230 if Token.Kind = stEof then Break 231 else 232 if Token.Kind = stIdentifier then begin 233 Keyword := LowerCase(Token.Text); 234 if Keyword = 'var' then begin 235 Token := Tokenizer.GetNext; 236 Token2 := Tokenizer.GetNext; 237 if Token2.Kind <> stIdentifier then 238 raise Exception.Create('Expected type parameter'); 239 Variable := BeginEnd.SourceCode.Variables.Search(Token.Text); 240 if not Assigned(Variable) then begin 241 ValueType := BeginEnd.SourceCode.Types.Search(Token2.Text); 242 if not Assigned(ValueType) then 243 raise Exception.Create('Unsupported type: ' + Token2.Text); 244 Variable := BeginEnd.SourceCode.Variables.AddNew(Token.Text, 245 ValueType); 246 end else raise Exception.Create('Variable redefined: ' + Token.Text); 247 end else 248 if Keyword = 'begin' then begin 249 Instruction := TSourceBeginEnd.Create; 250 BeginEnd.Instructions.Add(Instruction); 251 TSourceBeginEnd(Instruction).SourceCode := BeginEnd.SourceCode; 252 ParseBeginEnd(TSourceBeginEnd(Instruction)); 253 end else 254 if Keyword = 'end' then begin 255 Break; 256 end else 257 begin 258 Funct := BeginEnd.SourceCode.Functions.Search(Keyword); 259 if Assigned(Funct) then begin 260 Instruction := TSourceFunctionCall.Create; 261 TSourceFunctionCall(Instruction).Name := Keyword; 262 for Param in Funct.Parameters do 263 if Param.Kind = pkString then begin 264 TSourceFunctionCall(Instruction).Parameters.Add(ParseReference) 265 end else 266 if Param.Kind = pkVariable then begin 267 TSourceFunctionCall(Instruction).Parameters.Add(ParseReferenceVariable(True)); 268 end else 269 raise Exception.Create('Unsupported parameter type.'); 270 BeginEnd.Instructions.Add(Instruction); 271 end else raise Exception.Create('Unsupported keyword: ' + Token.Text); 272 end; 273 end else raise Exception.Create('Unsupported token kind.'); 274 end; 344 if LowerCase(Token.Text) <> 'end' then 345 raise Exception.Create('Expected end keyword'); 346 Result := True; 347 end; 348 if not Result then Tokenizer.TokenIndex := TokenIndex; 275 349 end; 276 350 … … 292 366 var 293 367 I: Integer; 294 Instruction: TSource Instruction;368 Instruction: TSourceCommand; 295 369 TargetInstruction: TTargetInstruction; 296 370 begin 297 371 { Target.Instructions.Count := 0; 298 372 for I := 0 to SourceCode.Instructions.Count - 1 do begin 299 Instruction := TSource Instruction(SourceCode.Instructions[I]);300 if Instruction is T SourceFunctionCall then begin373 Instruction := TSourceCommand(SourceCode.Instructions[I]); 374 if Instruction is TCommandFunctionCall then begin 301 375 TargetInstruction := TTargetInstruction.Create; 302 376 TargetInstruction.Kind := tiFunction; 303 TargetInstruction.Name := T SourceFunctionCall(Instruction).Name;377 TargetInstruction.Name := TCommandFunctionCall(Instruction).Name; 304 378 Target.Instructions.Add(TargetInstruction) 305 379 end else raise Exception.Create('Unsupported source instruction'); -
branches/easy compiler/UFormMain.pas
r145 r146 51 51 procedure TForm1.FormShow(Sender: TObject); 52 52 begin 53 { with MemoSource.Lines do begin 53 with MemoSource.Lines do begin 54 Add('Begin'); 54 55 Add('var I Integer'); 55 56 Add('Assign I 10'); 56 Add('Repeat');57 //Add('Repeat'); 57 58 Add('Begin'); 58 Add('Decrement I 1');59 //Add('Decrement I 1'); 59 60 Add('IfZero I'); 60 Add('Break'); 61 Add('Print ''condition'''); 62 //Add('Break'); 61 63 Add('End'); 62 end; 63 } with MemoSource.Lines do begin 64 Add('End'); 65 end; 66 { with MemoSource.Lines do begin 64 67 Add('PrintLn ''Super Calculator'''); 65 68 Add('var Value1 Integer'); … … 78 81 Add('PrintLn Result'); 79 82 end; 80 {with MemoSource.Lines do begin83 with MemoSource.Lines do begin 81 84 Add('PrintLn ''Hello World!'''); 82 85 Add('print ''Hello'' PRINT '' World!'''); -
branches/easy compiler/USourceCode.pas
r145 r146 9 9 10 10 type 11 TSource Instruction= class11 TSourceCommand = class 12 12 end; 13 13 … … 125 125 end; 126 126 127 { T SourceFunctionCall }128 129 T SourceFunctionCall = class(TSourceInstruction)127 { TCommandFunctionCall } 128 129 TCommandFunctionCall = class(TSourceCommand) 130 130 Name: string; 131 131 Parameters: TSourceReferences; … … 136 136 TSourceCode = class; 137 137 138 { T SourceBeginEnd }139 140 T SourceBeginEnd = class(TSourceInstruction)138 { TCommandBeginEnd } 139 140 TCommandBeginEnd = class(TSourceCommand) 141 141 SourceCode: TSourceCode; 142 142 Instructions: TSourceInstructions; 143 143 constructor Create; 144 144 destructor Destroy; override; 145 end; 146 147 TCommandIfZero = class(TSourceCommand) 148 Variable: TSourceVariable; 145 149 end; 146 150 … … 155 159 Variables: TSourceVariables; 156 160 Constants: TSourceConstants; 157 Main: T SourceBeginEnd;161 Main: TCommandBeginEnd; 158 162 constructor Create; 159 163 destructor Destroy; override; … … 171 175 end; 172 176 173 { T SourceFunctionCall }174 175 constructor T SourceFunctionCall.Create;177 { TCommandFunctionCall } 178 179 constructor TCommandFunctionCall.Create; 176 180 begin 177 181 Parameters := TSourceReferences.Create; 178 182 end; 179 183 180 destructor T SourceFunctionCall.Destroy;184 destructor TCommandFunctionCall.Destroy; 181 185 begin 182 186 Parameters.Free; … … 184 188 end; 185 189 186 { T SourceBeginEnd }187 188 constructor T SourceBeginEnd.Create;190 { TCommandBeginEnd } 191 192 constructor TCommandBeginEnd.Create; 189 193 begin 190 194 Instructions := TSourceInstructions.Create; 191 195 end; 192 196 193 destructor T SourceBeginEnd.Destroy;197 destructor TCommandBeginEnd.Destroy; 194 198 begin 195 199 Instructions.Free; … … 351 355 end; 352 356 353 { T SourceFunctionCall }357 { TCommandFunctionCall } 354 358 355 359 { TSourceCode } … … 394 398 Constants := TSourceConstants.Create; 395 399 Functions := TSourceFunctions.Create; 396 Main := T SourceBeginEnd.Create;400 Main := TCommandBeginEnd.Create; 397 401 Main.SourceCode := Self; 398 402 InitFunctions; -
branches/easy compiler/USourceExecutor.pas
r145 r146 31 31 FOnOutput: TOutputEvent; 32 32 Variables: TExecutorVariables; 33 procedure ExecuteBeginEnd(BeginEnd: T SourceBeginEnd);33 procedure ExecuteBeginEnd(BeginEnd: TCommandBeginEnd); 34 34 public 35 35 constructor Create; … … 84 84 end; 85 85 86 procedure TSourceExecutor.ExecuteBeginEnd(BeginEnd: T SourceBeginEnd);86 procedure TSourceExecutor.ExecuteBeginEnd(BeginEnd: TCommandBeginEnd); 87 87 var 88 88 IP: Integer; 89 Instruction: TSource Instruction;89 Instruction: TSourceCommand; 90 90 Variable: TSourceVariable; 91 91 Value: TSourceValue; … … 93 93 Text: string; 94 94 IntValue: Integer; 95 SkipNext: Boolean; 95 96 96 97 function ReadValueReference(Reference: TSourceReference): TSourceValue; … … 114 115 115 116 begin 117 SkipNext := False; 116 118 IP := 0; 117 119 while IP < BeginEnd.Instructions.Count do begin 118 Instruction := TSourceInstruction(BeginEnd.Instructions[IP]); 119 if Instruction is TSourceFunctionCall then 120 with TSourceFunctionCall(Instruction) 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 121 128 if Name = 'print' then begin 122 129 if Assigned(FOnOutput) then begin … … 178 185 else raise Exception.Create('Wrong type for increment'); 179 186 end else 180 raise Exception.Create('Unsupported function: ' + T SourceFunctionCall(Instruction).Name);187 raise Exception.Create('Unsupported function: ' + TCommandFunctionCall(Instruction).Name); 181 188 end else 182 if Instruction is TSourceBeginEnd then begin 183 ExecuteBeginEnd(TSourceBeginEnd(Instruction)); 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'); 184 201 end else 185 202 raise Exception.Create('Unsupported instruction'); -
branches/easy compiler/USourceGenerator.pas
r145 r146 14 14 private 15 15 Indent: Integer; 16 function GenerateBeginEnd(BeginEnd: T SourceBeginEnd): string;16 function GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string; 17 17 function IndentStr: string; 18 18 public … … 49 49 end; 50 50 51 function TSourceGenerator.GenerateBeginEnd(BeginEnd: T SourceBeginEnd): string;51 function TSourceGenerator.GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string; 52 52 var 53 Instruction: TSource Instruction;53 Instruction: TSourceCommand; 54 54 I: Integer; 55 55 Value: TSourceValue; … … 77 77 with BeginEnd do 78 78 for I := 0 to Instructions.Count - 1 do begin 79 Instruction := TSource Instruction(Instructions[I]);80 if Instruction is T SourceFunctionCall then81 with T SourceFunctionCall(Instruction) do begin79 Instruction := TSourceCommand(Instructions[I]); 80 if Instruction is TCommandFunctionCall then 81 with TCommandFunctionCall(Instruction) do begin 82 82 if Name = 'print' then begin 83 83 Result := Result + IndentStr + 'Write(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + … … 101 101 raise Exception.Create('Unsupported instruction name.'); 102 102 end else 103 if Instruction is T SourceBeginEnd then begin104 Result := Result + GenerateBeginEnd(T SourceBeginEnd(Instruction)) +103 if Instruction is TCommandBeginEnd then begin 104 Result := Result + GenerateBeginEnd(TCommandBeginEnd(Instruction)) + 105 105 ';' + LineEnding; 106 end else 107 if Instruction is TCommandIfZero then begin 108 Result := Result + IndentStr + 'if ' + TCommandIfZero(Instruction).Variable.Name + ' = 0 then '; 106 109 end else 107 110 raise Exception.Create('Unsupported instruction');
Note:
See TracChangeset
for help on using the changeset viewer.