source: branches/AS8051toC/UCompiler.pas

Last change on this file was 26, checked in by chronos, 12 years ago
  • Upraveno: Překlad rozdělen do fáze zpracování maker a druhé fáze zpracování instrukcí.
File size: 15.5 KB
Line 
1unit UCompiler;
2
3{$mode delphi{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, UParser, SpecializedList;
9
10type
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
35 TCompiler = class
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;
54 end;
55
56implementation
57
58{ TCompilerMacro }
59
60procedure TCompilerMacro.ParseLine;
61begin
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;
72end;
73
74procedure TCompilerMacro.ParseExpression;
75begin
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;
134end;
135
136procedure TCompilerMacro.Emit(Text: string);
137begin
138 Output := Output + Text;
139end;
140
141function TCompilerMacro.ParseComment: Boolean;
142begin
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;
151end;
152
153constructor TCompilerMacro.Create;
154begin
155 Macros := TStringList.Create;
156 Parser := TParserASM51.Create;
157end;
158
159destructor TCompilerMacro.Destroy;
160begin
161 FreeAndNil(Parser);
162 FreeAndNil(Macros);
163 inherited Destroy;
164end;
165
166function TCompilerMacro.ParseString: string;
167begin
168 with Parser do begin
169 Result := '';
170 Expect('''');
171 while GetNext <> '''' do begin
172 Result := Result + ReadNext;
173 end;
174 Expect('''');
175 end;
176end;
177
178function TCompilerMacro.Compile(Source: string): string;
179var
180 OldPos: Integer;
181begin
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;
192end;
193
194{ TCompiler }
195
196function TCompiler.Compile(Source: string): string;
197begin
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;
206end;
207
208constructor TCompiler.Create;
209begin
210 Parser := TParserASM51.Create;
211 Symbols := TListObject.Create;
212end;
213
214destructor TCompiler.Destroy;
215begin
216 FreeAndNil(Symbols);
217 FreeAndNil(Parser);
218 inherited;
219end;
220
221procedure TCompiler.ParseLine;
222var
223 Part: string;
224 OutLine: string;
225 Instruction: string;
226 Macro: string;
227 Variable: string;
228begin
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;
263end;
264
265function TCompilerMacro.ParseMacro: Boolean;
266var
267 MacroName: string;
268 OldPos: Integer;
269begin
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;
337end;
338
339procedure TCompiler.Emit(Text: string);
340begin
341 Output := Output + Text;
342end;
343
344function TCompiler.ParseComment: Boolean;
345begin
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;
354end;
355
356function TCompilerMacro.ParseMacroUsage: Boolean;
357var
358 MacroName: string;
359begin
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;
383end;
384
385function TCompiler.ParseKeywords: Boolean;
386var
387 Value: string;
388begin
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;
476end;
477
478function TCompiler.ParseInstruction: Boolean;
479begin
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;
503end;
504
505procedure TCompilerMAcro.ParseIfExpression;
506begin
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;
550end;
551
552procedure TCompiler.ParseDbExpression;
553begin
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;
614end;
615
616function TCompiler.ParseString: string;
617begin
618 with Parser do begin
619 Result := '';
620 Expect('''');
621 while GetNext <> '''' do begin
622 Result := Result + ReadNext;
623 end;
624 Expect('''');
625 end;
626end;
627
628function TCompiler.IsHexNumber(Text: string): Boolean;
629begin
630 Result := (LowerCase(Copy(Text, Length(Text), 1)) = 'h') and
631 (Parser.IsHexNumber(Copy(Text, 1, Length(Text) - 1)));
632end;
633
634function TCompiler.CheckInstructionParameter: Boolean;
635var
636 Text: string;
637begin
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;
652end;
653
654function TCompiler.CheckIdentificator: Boolean;
655var
656 Variable: string;
657begin
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;
679end;
680
681
682end.
683
Note: See TracBrowser for help on using the repository browser.