Changeset 146 for branches/easy compiler/UCompiler.pas
- Timestamp:
- Jan 17, 2018, 2:25:45 PM (7 years ago)
- File:
-
- 1 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');
Note:
See TracChangeset
for help on using the changeset viewer.