Changeset 59 for branches/ByteArray/Assembler.pas
- Timestamp:
- Nov 25, 2023, 11:47:52 PM (12 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/ByteArray/Assembler.pas
r56 r59 14 14 RefPos: Integer; 15 15 TextPos: TPoint; 16 class function Create(LabelName: string; RefPos: Integer ): TLabelRef; static;16 class function Create(LabelName: string; RefPos: Integer; TextPos: TPoint): TLabelRef; static; 17 17 end; 18 18 … … 23 23 FOnError: TErrorEvent; 24 24 Parser: TParser; 25 InstDataWidth: TBigIntSize; 26 InstAddressWidth: TBigIntSize; 25 27 function ParseVar: Boolean; 26 28 function ParseDb: Boolean; 27 29 function ParseOrg: Boolean; 28 30 function ParseInstruction: Boolean; 31 function ParseInstructionParameter(ParamType: TParamType; Memory: TMemory): Boolean; 29 32 function ParseLabel: Boolean; 30 33 procedure UpdateLabelRefs; 31 34 function ParseNumParam(out Number: TBigInt): Boolean; 32 35 function ParseReg(out RegIndex: TRegIndex): Boolean; 36 function ParseDataWidth(out Size: TBigIntSize): Boolean; 37 function ParseAddressWidth(out Size: TBigIntSize): Boolean; 33 38 public 34 InstructionSet: TInstruction Set;39 InstructionSet: TInstructionInfos; 35 40 Memory: TMemory; 36 41 Labels: TDictionary<string, TBigInt>; … … 38 43 Variables: TDictionary<string, TBigInt>; 39 44 Messages: TMessages; 45 DataWidth: TBigIntSize; 46 AddressWidth: TBigIntSize; 40 47 procedure Error(Text: string; Pos: TPoint); 41 48 procedure Compile(Source: string); … … 58 65 SExpectedVariableValue = 'Expected variable value.'; 59 66 SUnsupportedParameterType = 'Unsupported parameter type'; 67 SDuplicateLabel = 'Duplicate label %s.'; 68 SLabelReferencedButNotDefined = 'Label %s referenced but not defined.'; 69 SDuplicateVariableName = 'Duplicate variable name %s'; 70 SExpectedParameter = 'Expected parameter'; 71 SExpectedParameterType = 'Expected parameter type [%s]'; 72 SExpectedNumberButFound = 'Expected number but %s found.'; 60 73 61 74 { TLabelRef } 62 75 63 class function TLabelRef.Create(LabelName: string; RefPos: Integer ): TLabelRef;76 class function TLabelRef.Create(LabelName: string; RefPos: Integer; TextPos: TPoint): TLabelRef; 64 77 begin 65 78 Result.LabelName := LabelName; 66 79 Result.RefPos := RefPos; 80 Result.TextPos := TextPos; 67 81 end; 68 82 … … 77 91 if Labels.TryGetValue(LabelRefs[I].LabelName, Addr) then 78 92 Memory.Write(LabelRefs[I].RefPos, 1, Addr) 79 else Error('Label ' + LabelRefs[I].LabelName + ' referenced but not defined.', LabelRefs[I].TextPos); 93 else Error(Format(SLabelReferencedButNotDefined, [LabelRefs[I].LabelName]), 94 LabelRefs[I].TextPos); 80 95 end; 81 96 end; … … 84 99 var 85 100 Token: TToken; 86 begin 101 LastPos: TParserPos; 102 begin 103 LastPos := Parser.Pos; 87 104 Result := False; 88 105 Token := Parser.ReadNext; … … 99 116 Result := True; 100 117 end else begin 101 LabelRefs.Add(TLabelRef.Create(Token.Value, Memory.Position ));118 LabelRefs.Add(TLabelRef.Create(Token.Value, Memory.Position + 1, Parser.Pos.Pos)); 102 119 Number := 0; 103 120 Result := True; 104 121 end; 105 end else Error('Unexpected token ' + Token.Value + '.', Token.Pos); 122 end; 123 if not Result then Parser.Pos := LastPos; 106 124 end; 107 125 … … 110 128 LastPos: TParserPos; 111 129 Token: TToken; 130 Index: Integer; 112 131 begin 113 132 Result := False; 114 133 LastPos := Parser.Pos; 115 134 Token := Parser.ReadNext; 116 if (Length(Token.Value) = 1) and (Token.Value[1] in ['A'..'H']) then begin 117 RegIndex := TRegIndex(Ord(Token.Value[1]) - Ord('A')); 118 Result := True; 119 end else Parser.Pos := LastPos; 135 if (Length(Token.Value) >= 2) and (Token.Value[1] = 'R') then begin 136 if TryStrToInt(Copy(Token.Value, 2, MaxInt), Index) then begin 137 RegIndex := Index; 138 Result := True; 139 end; 140 end; 141 if not Result then Parser.Pos := LastPos; 142 end; 143 144 function TAssembler.ParseDataWidth(out Size: TBigIntSize): Boolean; 145 var 146 LastPos: TParserPos; 147 Token: TToken; 148 Index: Integer; 149 begin 150 Result := False; 151 LastPos := Parser.Pos; 152 Token := Parser.ReadNext; 153 if (Length(Token.Value) >= 2) and (Token.Value[1] = 'D') then begin 154 if TryStrToInt(Copy(Token.Value, 2, MaxInt), Index) then begin 155 Size := Index; 156 Result := True; 157 end; 158 end; 159 if not Result then Parser.Pos := LastPos; 160 end; 161 162 function TAssembler.ParseAddressWidth(out Size: TBigIntSize): Boolean; 163 var 164 LastPos: TParserPos; 165 Token: TToken; 166 Index: Integer; 167 begin 168 Result := False; 169 LastPos := Parser.Pos; 170 Token := Parser.ReadNext; 171 if (Length(Token.Value) >= 2) and (Token.Value[1] = 'A') then begin 172 if TryStrToInt(Copy(Token.Value, 2, MaxInt), Index) then begin 173 Size := Index; 174 Result := True; 175 end; 176 end; 177 if not Result then Parser.Pos := LastPos; 120 178 end; 121 179 … … 134 192 Labels.Clear; 135 193 LabelRefs.Clear; 194 Variables.Clear; 136 195 Parser.Reset; 137 196 Parser.Source := Source; … … 172 231 if TryStrToBigInt(TokenValue.Value, Number) then 173 232 Variables.Add(TokenName.Value, Number) 174 else Error( 'Expected number', TokenValue.Pos);175 end else Error( 'Duplicate variable name ' + TokenName.Value, TokenName.Pos);233 else Error(SExpectedNumber, TokenValue.Pos); 234 end else Error(Format(SDuplicateVariableName, [TokenName.Value]), TokenName.Pos); 176 235 end else Error(SExpectedVariableValue, TokenValue.Pos); 177 236 end else Error(SExpectedVariableName, TokenName.Pos); … … 199 258 if Token.Kind = tkString then begin 200 259 Memory.WriteStringPos(Token.Value); 201 end else raise Exception.Create('Expected parameter'); 260 end else 261 if Token.Kind = tkEof then 262 else if Token.Kind = tkEol then 263 else raise Exception.Create(SExpectedParameter); 202 264 end; 203 265 if Parser.CheckNextAndRead(tkSpecialSymbol, ',') then begin … … 219 281 if Token.Kind = tkNumber then begin 220 282 Memory.Position := StrToInt(Token.Value); 221 end else Error( 'Expected number but ' + Token.Value + ' found.', Token.Pos);283 end else Error(Format(SExpectedNumberButFound, [Token.Value]), Token.Pos); 222 284 end; 223 285 end; … … 225 287 function TAssembler.ParseInstruction: Boolean; 226 288 var 227 InstructionInfo : TInstructionInfo;289 InstructionInfos: TInstructionInfos; 228 290 I: Integer; 229 291 Token: TToken; 230 292 LastPos: TParserPos; 293 J: Integer; 294 AllowedParams: set of TParamType; 295 ParamType: TParamType; 296 ParamOk: Boolean; 297 LastMessagesCount: Integer; 298 Text: string; 299 EmptyParam: Boolean; 300 InstructionMemory: TMemory; 301 ParamMemory: TMemory; 302 begin 303 Result := False; 304 LastPos := Parser.Pos; 305 Token := Parser.ReadNext; 306 InstructionInfos := InstructionSet.SearchByNameMultiple(Token.Value); 307 InstDataWidth := DataWidth; 308 InstAddressWidth := AddressWidth; 309 InstructionMemory := TMemory.Create; 310 InstructionMemory.Grow := True; 311 ParamMemory := TMemory.Create; 312 ParamMemory.Grow := True; 313 J := 0; 314 if InstructionInfos.Count > 0 then 315 repeat 316 EmptyParam := False; 317 318 if J > 0 then 319 Parser.Expect(tkSpecialSymbol, ','); 320 321 // Get allowed parameters 322 AllowedParams := []; 323 for I := 0 to InstructionInfos.Count - 1 do begin 324 if Length(InstructionInfos[I].Params) > J then 325 AllowedParams := AllowedParams + [InstructionInfos[I].Params[J]] 326 else EmptyParam := True; 327 end; 328 329 if AllowedParams <> [] then begin 330 ParamOk := False; 331 for ParamType := Low(TParamType) to High(TParamType) do begin 332 if ParamType in AllowedParams then begin 333 LastMessagesCount := Messages.Count; 334 ParamMemory.Clear; 335 if ParseInstructionParameter(ParamType, ParamMemory) and 336 (LastMessagesCount = Messages.Count) then begin 337 ParamOk := True; 338 InstructionMemory.WriteMemoryPos(ParamMemory); 339 Break; 340 end else Messages.Count := LastMessagesCount; 341 end; 342 end; 343 if not ParamOk then begin 344 if EmptyParam then begin 345 ParamType := ptNone; 346 end else begin 347 Text := ''; 348 for ParamType := Low(TParamType) to High(TParamType) do begin 349 if ParamType in AllowedParams then begin 350 if Text <> '' then Text := Text + ' or '; 351 Text := Text + ParamTypeString[ParamType] 352 end; 353 end; 354 355 Error(Format(SExpectedParameterType, [Text]), Parser.Pos.Pos); 356 Break; 357 end; 358 end; 359 end; 360 361 // Remove not matching instruction infos 362 for I := InstructionInfos.Count - 1 downto 0 do 363 if (Length(InstructionInfos[I].Params) > J) and 364 (InstructionInfos[I].Params[J] <> ParamType) then InstructionInfos.Delete(I); 365 366 if (InstructionInfos.Count = 1) and (J >= (Length(InstructionInfos[0].Params) - 1)) then begin 367 Memory.WritePos(1, Byte(InstructionInfos[0].Instruction)); 368 Memory.WriteMemoryPos(InstructionMemory); 369 Result := True; 370 Break; 371 end; 372 373 Inc(J); 374 until False; 375 376 if not Result then Parser.Pos := LastPos; 377 FreeAndNil(ParamMemory); 378 FreeAndNil(InstructionMemory); 379 end; 380 381 function TAssembler.ParseInstructionParameter(ParamType: TParamType; Memory: TMemory): Boolean; 382 var 383 LastPos: TParserPos; 384 I: Integer; 231 385 RegIndex: TRegIndex; 232 386 Number: TBigInt; 233 begin 234 Result := False; 235 LastPos := Parser.Pos; 236 Token := Parser.ReadNext; 237 InstructionInfo := InstructionSet.SearchName(Token.Value); 238 if Assigned(InstructionInfo) then begin 239 Result := True; 240 Memory.WritePos(1, Integer(InstructionInfo.Instruction)); 241 for I := 0 to Length(InstructionInfo.Params) - 1 do begin 242 if I > 0 then 243 Parser.Expect(tkSpecialSymbol, ','); 244 if InstructionInfo.Params[I] = ptNumber then begin 245 if ParseNumParam(Number) then Memory.WritePos(1, Number) 246 else Error(SExpectedNumber, Token.Pos); 247 end else 248 if InstructionInfo.Params[I] = ptReg then begin 249 if ParseReg(RegIndex) then Memory.WritePos(1, Byte(RegIndex)) 250 else Error(SExpectedRegisterName, Token.Pos); 251 end else 252 if InstructionInfo.Params[I] = ptRegIndirect then begin 253 Parser.Expect(tkSpecialSymbol, '('); 254 if ParseReg(RegIndex) then Memory.WritePos(1, Byte(RegIndex)) 255 else Error(SExpectedRegisterName, Token.Pos); 256 Parser.Expect(tkSpecialSymbol, ')'); 257 end else 258 if InstructionInfo.Params[I] = ptRegIndirectIndex then begin 259 Parser.Expect(tkSpecialSymbol, '('); 260 if ParseReg(RegIndex) then begin 261 Memory.WritePos(1, Byte(RegIndex)); 262 Parser.Expect(tkSpecialSymbol, '+'); 263 Token := Parser.ReadNext; 264 if ParseNumParam(Number) then Memory.WritePos(1, Number) 265 else Error(SExpectedNumericIndex, Token.Pos); 266 end else Error(SExpectedRegisterName, Token.Pos); 267 Parser.Expect(tkSpecialSymbol, ')'); 268 end else Error(SUnsupportedParameterType, Token.Pos); 387 Token: TToken; 388 begin 389 LastPos := Parser.Pos; 390 Result := True; 391 case ParamType of 392 ptData: begin 393 if ParseNumParam(Number) then Memory.WritePos(InstDataWidth, Number) 394 else begin 395 Error(SExpectedNumber, Parser.Pos.Pos); 396 Result := False; 397 end; 398 end; 399 ptAddress: begin 400 if ParseNumParam(Number) then Memory.WritePos(InstAddressWidth, Number) 401 else begin 402 Error(SExpectedNumber, Parser.Pos.Pos); 403 Result := False; 404 end; 405 end; 406 ptReg: begin 407 if ParseReg(RegIndex) then Memory.WritePos(1, Byte(RegIndex)) 408 else begin 409 Error(SExpectedRegisterName, Parser.Pos.Pos); 410 Result := False; 411 end; 412 end; 413 ptRegIndirect: begin 414 if not Parser.Expect(tkSpecialSymbol, '(') then Result := False; 415 if ParseReg(RegIndex) then Memory.WritePos(1, Byte(RegIndex)) 416 else begin 417 Error(SExpectedRegisterName, Parser.Pos.Pos); 418 Result := False; 419 end; 420 if not Parser.Expect(tkSpecialSymbol, ')') then Result := False;; 421 end; 422 ptRegIndirectIndex: begin 423 if not Parser.Expect(tkSpecialSymbol, '(') then Result := False; 424 if ParseReg(RegIndex) then begin 425 Memory.WritePos(1, Byte(RegIndex)); 426 if not Parser.Expect(tkSpecialSymbol, '+') then Result := False; 427 if ParseNumParam(Number) then Memory.WritePos(InstAddressWidth, Number) 428 else begin 429 Error(SExpectedNumericIndex, Parser.Pos.Pos); 430 Result := False; 431 end; 432 end else begin 433 Error(SExpectedRegisterName, Parser.Pos.Pos); 434 Result := False; 435 end; 436 if not Parser.Expect(tkSpecialSymbol, ')') then Result := False; 437 end; 438 ptDataWidth: begin 439 if ParseDataWidth(InstDataWidth) then begin 440 Memory.WritePos(1, InstDataWidth) 441 end else begin 442 Error(SExpectedRegisterName, Parser.Pos.Pos); 443 Result := False; 444 end; 445 end; 446 ptAddressWidth: begin 447 if ParseAddressWidth(InstAddressWidth) then begin 448 Memory.WritePos(1, InstAddressWidth) 449 end else begin 450 Error(SExpectedRegisterName, Parser.Pos.Pos); 451 Result := False; 452 end; 453 end; 454 else begin 455 Result := False; 456 Error(SUnsupportedParameterType, Parser.Pos.Pos); 269 457 end; 270 458 end; … … 285 473 if not Labels.TryGetValue(Token.Value, Addr) then begin 286 474 Labels.Add(Token.Value, Memory.Position); 287 end else Error( 'Duplicate label ' + Token.Value + '.', Token.Pos);475 end else Error(Format(SDuplicateLabel, [Token.Value]), Token.Pos); 288 476 end; 289 477 if not Result then Parser.Pos := LastPos; … … 323 511 Messages := TMessages.Create; 324 512 Memory := TMemory.Create; 325 InstructionSet := TInstructionSet.Create; 513 InstructionSet := TInstructionInfos.Create; 514 InstructionSet.Init; 326 515 Labels := TDictionary<string, TBigInt>.Create; 327 516 LabelRefs := TList<TLabelRef>.Create;
Note:
See TracChangeset
for help on using the changeset viewer.