Changeset 26 for branches/AS8051toC/UCompiler.pas
- Timestamp:
- Oct 15, 2012, 2:10:48 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/AS8051toC/UCompiler.pas
r25 r26 6 6 7 7 uses 8 Classes, SysUtils ;8 Classes, SysUtils, UParser, SpecializedList; 9 9 10 10 type 11 12 { TCompilerMacro } 13 14 TCompilerMacro = class 15 private 16 Output: string; 17 function ParseString: string; 18 public 19 Macros: TStringList; 20 Parser: TParserASM51; 21 procedure ParseLine; 22 function ParseMacro: Boolean; 23 function ParseMacroUsage: Boolean; 24 procedure ParseExpression; 25 procedure ParseIfExpression; 26 procedure Emit(Text: string); 27 function ParseComment: Boolean; 28 constructor Create; 29 destructor Destroy; override; 30 function Compile(Source: string): string; 31 end; 32 33 { TCompiler } 34 11 35 TCompiler = class 12 36 private 37 Output: string; 38 public 39 Parser: TParserASM51; 40 Symbols: TListObject; 41 procedure Emit(Text: string); 42 function IsHexNumber(Text: string): Boolean; 43 function CheckIdentificator: Boolean; 44 function CheckInstructionParameter: Boolean; 45 function ParseComment: Boolean; 46 procedure ParseDbExpression; 47 function ParseInstruction: Boolean; 48 function ParseKeywords: Boolean; 49 procedure ParseLine; 50 function ParseString: string; 51 function Compile(Source: string): string; 52 constructor Create; 53 destructor Destroy; override; 13 54 end; 14 55 15 56 implementation 16 57 58 { TCompilerMacro } 59 60 procedure TCompilerMacro.ParseLine; 61 begin 62 with Parser do begin 63 if GetNext = '%' then begin 64 if ParseComment then 65 if ParseMacroUsage then Emit(ReadNext) 66 else if ParseMacro then Emit(ReadNext) 67 else ; 68 end else begin 69 Output := Output + ReadNext; 70 end; 71 end; 72 end; 73 74 procedure TCompilerMacro.ParseExpression; 75 begin 76 with Parser do begin 77 78 if ParseMacroUsage then 79 else if GetNext = '$' then begin 80 Expect('$'); 81 Emit('$'); 82 end 83 else if GetNext = '(' then begin 84 Expect('('); 85 Emit('('); 86 ParseExpression; 87 Expect(')'); 88 Emit(')'); 89 end 90 else if GetNext = '''' then Emit('"' + ParseString + '"') 91 else Error('Unknown IF parameter "' + GetNext + '"'); 92 93 if GetNext = '+' then begin 94 Expect('+'); 95 Emit('+'); 96 ParseExpression; 97 end else 98 if GetNext = '-' then begin 99 Expect('-'); 100 Emit('-'); 101 ParseExpression; 102 end else 103 if GetNext = '*' then begin 104 Expect('*'); 105 Emit('*'); 106 ParseExpression; 107 end else 108 if GetNext = '/' then begin 109 Expect('/'); 110 Emit('/'); 111 ParseExpression; 112 end else 113 if GetNext = 'shl' then begin 114 Expect('shl'); 115 Emit('<< '); 116 ParseExpression; 117 end else 118 if GetNext = 'shr' then begin 119 Expect('shr'); 120 Emit('>> '); 121 ParseExpression; 122 end else 123 if GetNext = 'or' then begin 124 Expect('or'); 125 Emit('|| '); 126 ParseExpression; 127 end else 128 if GetNext = 'and' then begin 129 Expect('and'); 130 Emit('&& '); 131 ParseExpression; 132 end; 133 end; 134 end; 135 136 procedure TCompilerMacro.Emit(Text: string); 137 begin 138 Output := Output + Text; 139 end; 140 141 function TCompilerMacro.ParseComment: Boolean; 142 begin 143 with Parser do begin 144 if GetNext = ';' then begin 145 Result := True; 146 Expect(';'); 147 Emit('//'); 148 Emit(ReadEol); 149 end else Result := False; 150 end; 151 end; 152 153 constructor TCompilerMacro.Create; 154 begin 155 Macros := TStringList.Create; 156 Parser := TParserASM51.Create; 157 end; 158 159 destructor TCompilerMacro.Destroy; 160 begin 161 FreeAndNil(Parser); 162 FreeAndNil(Macros); 163 inherited Destroy; 164 end; 165 166 function TCompilerMacro.ParseString: string; 167 begin 168 with Parser do begin 169 Result := ''; 170 Expect(''''); 171 while GetNext <> '''' do begin 172 Result := Result + ReadNext; 173 end; 174 Expect(''''); 175 end; 176 end; 177 178 function TCompilerMacro.Compile(Source: string): string; 179 var 180 OldPos: Integer; 181 begin 182 Output := ''; 183 Parser.Position := 1; 184 Parser.Source := Source; 185 while not Parser.Eof do begin 186 OldPos := Parser.Position; 187 ParseLine; 188 if Parser.GetNext = 'end' then Break; 189 if OldPos = Parser.Position then Break; 190 end; 191 Result := Output; 192 end; 193 194 { TCompiler } 195 196 function TCompiler.Compile(Source: string): string; 197 begin 198 Output := ''; 199 Parser.Position := 1; 200 Parser.Source := Source; 201 while not Parser.Eof do begin 202 ParseLine; 203 if Parser.GetNext = 'end' then Break; 204 end; 205 Result := Output; 206 end; 207 208 constructor TCompiler.Create; 209 begin 210 Parser := TParserASM51.Create; 211 Symbols := TListObject.Create; 212 end; 213 214 destructor TCompiler.Destroy; 215 begin 216 FreeAndNil(Symbols); 217 FreeAndNil(Parser); 218 inherited; 219 end; 220 221 procedure TCompiler.ParseLine; 222 var 223 Part: string; 224 OutLine: string; 225 Instruction: string; 226 Macro: string; 227 Variable: string; 228 begin 229 with Parser do begin 230 if GetNext = '$' then begin 231 Expect('$'); 232 if GetNext = 'include' then begin 233 Expect('include'); 234 Expect('('); 235 Emit('#include '''); 236 Emit(ReadNext); 237 Expect('.'); 238 Emit('.'); 239 Emit(ReadNext); 240 Emit(''''); 241 Expect(')'); 242 end else Error('Unknown token "' + GetNext + '"'); 243 end 244 else if GetNext = ')' then begin 245 Expect(')'); 246 if GetNext = 'else' then begin 247 Expect('else'); 248 Emit('#else '); 249 Expect('('); 250 end else 251 if GetNext = 'fi' then begin 252 Expect('fi'); 253 Emit('#endif '); 254 end; // else Error('Unknown token "' + GetNext + '"'); 255 end 256 else if ParseComment then 257 else if ParseKeywords then 258 else if ParseInstruction then 259 else if IsIdentificator(GetNext) then CheckIdentificator 260 else Error('Unexpected token "' + GetNext + '"'); 261 Emit(LineEnding); 262 end; 263 end; 264 265 function TCompilerMacro.ParseMacro: Boolean; 266 var 267 MacroName: string; 268 OldPos: Integer; 269 begin 270 with Parser do begin 271 OldPos := Position; 272 if GetNext = '%' then begin 273 Result := True; 274 Expect('%'); 275 if GetNext = 'define' then begin 276 Expect('define'); 277 Emit('#define '); 278 Expect('('); 279 MacroName := ReadNext; 280 Emit(MacroName); 281 Expect(')'); 282 Emit(' '); 283 Expect('('); 284 while GetNext <> ')' do begin 285 Emit(ReadNext); 286 end; 287 Expect(')'); 288 Emit(';'); 289 end else 290 if GetNext = 'if' then begin 291 Expect('if'); 292 Emit('#if '); 293 Expect('('); 294 ParseIfExpression; 295 Expect(')'); 296 Expect('then'); 297 Expect('('); 298 end else 299 if GetNext = 'set' then begin 300 Expect('set'); 301 Emit('#define '); 302 Expect('('); 303 Emit(ReadNext + ' '); 304 Expect(','); 305 ParseExpression; 306 Expect(')'); 307 Emit(';'); 308 end else 309 if GetNext = '*' then begin 310 Expect('*'); 311 if GetNext = 'define' then begin 312 Expect('define'); 313 Emit('#define '); 314 Expect('('); 315 Emit(ReadNext); 316 Expect('('); 317 Emit('(' + ReadNext); 318 while GetNext = ',' do begin 319 Expect(','); 320 Emit(', ' + ReadNext); 321 end; 322 Expect(')'); 323 Emit(')'); 324 Expect(')'); 325 if GetNext = 'local' then begin 326 Expect('local'); 327 ReadNext; 328 end; 329 Expect('('); 330 end; 331 end else begin 332 Position := OldPos; 333 Result := False; 334 end; 335 end else Result := False; 336 end; 337 end; 338 339 procedure TCompiler.Emit(Text: string); 340 begin 341 Output := Output + Text; 342 end; 343 344 function TCompiler.ParseComment: Boolean; 345 begin 346 with Parser do begin 347 if GetNext = ';' then begin 348 Result := True; 349 Expect(';'); 350 Emit('//'); 351 Emit(ReadEol); 352 end else Result := False; 353 end; 354 end; 355 356 function TCompilerMacro.ParseMacroUsage: Boolean; 357 var 358 MacroName: string; 359 begin 360 with Parser do begin 361 if GetNext = '%' then begin 362 Result := True; 363 Expect('%'); 364 MacroName := ReadNext; 365 Emit(MacroName); 366 if GetNext = '(' then begin 367 Expect('('); 368 Emit('('); 369 ParseExpression; 370 //else Emit(ReadNext); 371 while GetNext = ',' do begin 372 Expect(','); 373 Emit(','); 374 ParseExpression; 375 //if ParseMacroUsage then 376 //else if GetNext <> ')' then Emit(ReadNext); 377 end; 378 Emit(')'); 379 Expect(')'); 380 end; 381 end else Result := False; 382 end; 383 end; 384 385 function TCompiler.ParseKeywords: Boolean; 386 var 387 Value: string; 388 begin 389 with Parser do begin 390 if GetNext = 'extrn' then begin 391 Expect('extrn'); 392 Result := True; 393 ReadNext; 394 Expect('('); 395 ReadNext; 396 while GetNext = ',' do begin 397 Expect(','); 398 ReadNext; 399 end; 400 Expect(')'); 401 end else 402 if GetNext = 'public' then begin 403 Result := True; 404 Expect('public'); 405 ReadNext; 406 while GetNext = ',' do begin 407 Expect(','); 408 ReadNext; 409 end; 410 end else 411 if GetNext = 'using' then begin 412 Result := True; 413 Expect('using'); 414 Value := ReadNext; 415 Emit('// using reg bank ' + Value); 416 end else 417 if GetNext = 'cseg' then begin 418 Result := True; 419 Expect('cseg'); 420 Expect('at'); 421 Value := ReadNext; 422 if GetNext = 'h' then begin 423 Expect('h'); 424 //Emit('0x' + Value); 425 end; // else Emit(Value); 426 end else 427 if GetNext = 'rseg' then begin 428 Result := True; 429 Expect('rseg'); 430 Value := ReadNext; 431 if GetNext = 'h' then begin 432 Expect('h'); 433 //Emit('0x' + Value); 434 end; // else Emit(Value); 435 end else 436 if GetNext = 'dbit' then begin 437 Result := True; 438 Expect('dbit'); 439 Emit('char '); 440 Emit(ReadNext); 441 end else 442 if GetNext = 'db' then begin 443 Result := True; 444 Expect('db'); 445 Emit('char '); 446 ParseDbExpression; 447 while GetNext = ',' do begin 448 Expect(','); 449 Emit(','); 450 ParseDbExpression; 451 end; 452 end else 453 if GetNext = 'dw' then begin 454 Result := True; 455 Expect('dw'); 456 Emit('char '); 457 ParseDbExpression; 458 while GetNext = ',' do begin 459 Expect(','); 460 Emit(','); 461 ParseDbExpression; 462 end; 463 end else 464 if GetNext = 'ds' then begin 465 Result := True; 466 Expect('ds'); 467 Emit('char* '); 468 ParseDbExpression; 469 while GetNext = ',' do begin 470 Expect(','); 471 Emit(','); 472 ParseDbExpression; 473 end; 474 end else Result := False; 475 end; 476 end; 477 478 function TCompiler.ParseInstruction: Boolean; 479 begin 480 with Parser do begin 481 if GetNext = 'jmp' then begin 482 Expect('jmp'); 483 Result := True; 484 Emit('goto '); 485 Emit(ReadNext); 486 Emit(';'); 487 end else 488 if GetNext = 'mov' then begin 489 Expect('mov'); 490 Result := True; 491 Emit('MOV('); 492 ParseDbExpression; 493 Expect(','); 494 Emit(','); 495 ParseDbExpression; 496 Emit(');'); 497 end else 498 if GetNext = 'reti' then begin 499 Result := True; 500 Expect('reti'); 501 end else Result := False; 502 end; 503 end; 504 505 procedure TCompilerMAcro.ParseIfExpression; 506 begin 507 with Parser do begin 508 if ParseMacroUsage then 509 else if IsNumber(GetNext) then Emit(ReadNext) 510 else Error('Unknown IF parameter "' + GetNext + '"'); 511 if GetNext <> ')' then begin 512 if GetNext = 'eq' then begin 513 Expect('eq'); 514 Emit('= '); 515 end else 516 if GetNext = 'ne' then begin 517 Expect('ne'); 518 Emit('!= '); 519 end else 520 if GetNext = 'gt' then begin 521 Expect('gt'); 522 Emit('> '); 523 end else 524 if GetNext = 'ge' then begin 525 Expect('ge'); 526 Emit('>= '); 527 end else 528 if GetNext = 'lt' then begin 529 Expect('lt'); 530 Emit('< '); 531 end else 532 if GetNext = 'le' then begin 533 Expect('le'); 534 Emit('<= '); 535 end else 536 if GetNext = 'or' then begin 537 Expect('or'); 538 Emit('|| '); 539 end else 540 if GetNext = 'and' then begin 541 Expect('and'); 542 Emit('&& '); 543 end else 544 Error('Unknown operand "' + ReadNext + '"'); 545 if ParseMacroUsage then 546 else if IsNumber(GetNext) then Emit(ReadNext) 547 else Error('Unknown IF parameter "' + GetNext + '"'); 548 end; 549 end; 550 end; 551 552 procedure TCompiler.ParseDbExpression; 553 begin 554 with Parser do begin 555 556 if GetNext = '$' then begin 557 Expect('$'); 558 Emit('$'); 559 end 560 else if GetNext = '(' then begin 561 Expect('('); 562 Emit('('); 563 ParseDbExpression; 564 Expect(')'); 565 Emit(')'); 566 end 567 else if GetNext = '''' then Emit('"' + ParseString + '"') 568 else if CheckInstructionParameter then 569 else if IsIdentificator(GetNext) then begin 570 Emit(ReadNext); 571 end else Error('Unknown IF parameter "' + GetNext + '"'); 572 573 if GetNext = '+' then begin 574 Expect('+'); 575 Emit('+'); 576 ParseDbExpression; 577 end else 578 if GetNext = '-' then begin 579 Expect('-'); 580 Emit('-'); 581 ParseDbExpression; 582 end else 583 if GetNext = '*' then begin 584 Expect('*'); 585 Emit('*'); 586 ParseDbExpression; 587 end else 588 if GetNext = '/' then begin 589 Expect('/'); 590 Emit('/'); 591 ParseDbExpression; 592 end else 593 if GetNext = 'shl' then begin 594 Expect('shl'); 595 Emit('<< '); 596 ParseDbExpression; 597 end else 598 if GetNext = 'shr' then begin 599 Expect('shr'); 600 Emit('>> '); 601 ParseDbExpression; 602 end else 603 if GetNext = 'or' then begin 604 Expect('or'); 605 Emit('|| '); 606 ParseDbExpression; 607 end else 608 if GetNext = 'and' then begin 609 Expect('and'); 610 Emit('&& '); 611 ParseDbExpression; 612 end; 613 end; 614 end; 615 616 function TCompiler.ParseString: string; 617 begin 618 with Parser do begin 619 Result := ''; 620 Expect(''''); 621 while GetNext <> '''' do begin 622 Result := Result + ReadNext; 623 end; 624 Expect(''''); 625 end; 626 end; 627 628 function TCompiler.IsHexNumber(Text: string): Boolean; 629 begin 630 Result := (LowerCase(Copy(Text, Length(Text), 1)) = 'h') and 631 (Parser.IsHexNumber(Copy(Text, 1, Length(Text) - 1))); 632 end; 633 634 function TCompiler.CheckInstructionParameter: Boolean; 635 var 636 Text: string; 637 begin 638 Text := Parser.GetNext; 639 Result := False; 640 if Parser.IsNumber(Text) then Result := True 641 else if Text = '#' then begin 642 Result := True; 643 Parser.Expect('#'); 644 if IsHexNumber(Parser.GetNext) then Emit(Parser.ReadNext) 645 else if Parser.IsNumber(Parser.GetNext) then Emit(Parser.ReadNext) 646 else Parser.Error('Invalid parameter'); 647 end 648 else if Copy(Text, 1, 1) = '@' then begin 649 if IsHexNumber(Copy(Text, 2, Length(Text))) then Result := True; 650 Emit(Parser.ReadNext); 651 end; 652 end; 653 654 function TCompiler.CheckIdentificator: Boolean; 655 var 656 Variable: string; 657 begin 658 with Parser do begin 659 Variable := ReadNext; 660 if GetNext = '%' then begin 661 Expect('%'); 662 Variable := Variable + '##' + ReadNext; 663 end; 664 if GetNext = ':' then begin 665 Expect(':'); 666 Emit(Variable + ':'); 667 end else 668 if GetNext = 'equ' then begin 669 Expect('equ'); 670 Emit('#define ' + Variable + ' '); 671 ParseDbExpression; 672 Emit(';'); 673 end else 674 if GetNext = 'segment' then begin 675 Expect('segment'); 676 ReadNext; 677 end else Error('Unexpected token "' + Variable + '"'); 678 end; 679 end; 680 681 17 682 end. 18 683
Note:
See TracChangeset
for help on using the changeset viewer.