source: trunk/UMainForm.pas

Last change on this file was 18, checked in by george, 15 years ago
  • Upraveno: Vylepšené parsování.
File size: 32.7 KB
Line 
1unit UMainForm;
2
3interface
4
5uses
6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7 Dialogs, StdCtrls;
8
9type
10 TMemoryType = (mtProgram, mtData, mtEEPROM);
11
12 TModuleType = (mdProgram, mdUnit, mdLibrary, mdPackage);
13
14 TInstruction = (inNone, inJump, inConditionalJump, inExpressionEvaluation,
15 inReturn);
16
17 TNodeType = (ntNone, ntVariable, nTFunction, ntConstant, ntOperator);
18
19 TValue = array of Byte;
20
21 TCompiler = class;
22 TCommonBlock = class;
23 TTypeList = class;
24 TConstantList = class;
25 TVariableList = class;
26 TFunctionList = class;
27 TExpression = class;
28 TOperationList = class;
29 TFunction = class;
30
31 TDevice = class
32 Family: string;
33 Memory: array[TMemoryType] of Integer;
34 end;
35
36 TCommonBlock = class
37 Name: string;
38 Parent: TCommonBlock;
39 Constants: TConstantList;
40 Types: TTypeList;
41 Variables: TVariableList;
42 Methods: TFunctionList;
43 Operations: TOperationList;
44 procedure AllocateMemory;
45 constructor Create; virtual;
46 destructor Destroy; override;
47 procedure ParseDefinitions(Compiler: TCompiler);
48 function ParseExpression(Compiler: TCompiler): TExpression;
49 procedure ParseProgramCode(Compiler: TCompiler);
50 procedure ParseOperation(Compiler: TCompiler);
51 procedure GenerateAssembler(Compiler: TCompiler; LabelPrefix: string);
52 procedure CheckReferences;
53 end;
54
55 TType = class
56 Parent: TTypeList;
57 Name: string;
58 Size: Integer;
59 UsedType: TType;
60 procedure Parse(Compiler: TCompiler);
61 end;
62
63 TTypeList = class(TList)
64 Parent: TCommonBlock;
65 procedure Parse(Compiler: TCompiler);
66 function Search(Name: string): TType;
67 end;
68
69 TConstant = class
70 Name: string;
71 ValueType: TType;
72 Value: TValue;
73 procedure Parse(Compiler: TCompiler);
74 end;
75
76 TConstantList = class(TList)
77 Parent: TCommonBlock;
78 function Search(Name: string): TConstant;
79 procedure Parse(Compiler: TCompiler);
80 end;
81
82 TVariable = class
83 Name: string;
84 ValueType: TType;
85 Value: TValue;
86 procedure Parse(Compiler: TCompiler);
87 end;
88
89 TVariableList = class(TList)
90 Parent: TCommonBlock;
91 procedure Parse(Compiler: TCompiler);
92 function Search(Name: string): TVariable;
93 end;
94
95 TExpression = class
96 NodeType: TNodeType;
97 Variable: TVariable;
98 Method: TFunction;
99 Value: TValue;
100 OperatorName: string;
101 SubItems: TList; // TList<TExpression>
102 Associated: Boolean;
103 constructor Create;
104 destructor Destroy; override;
105 procedure GenerateAssembler(Compiler: TCompiler; LabelPrefix: string);
106 end;
107
108 TOperation = class
109 Instruction: TInstruction;
110 ExpressionTree: TExpression;
111 GotoAddress: Integer;
112 Negative: Boolean;
113 Referenced: Boolean;
114 end;
115
116 TOperationList = class(TList)
117
118 end;
119
120 TFunction = class(TCommonBlock)
121 Parameters: TList; // TList<TParameter>
122 ResultType: TType;
123 constructor Create; override;
124 destructor Destroy; override;
125 procedure Parse(Compiler: TCompiler);
126 end;
127
128 TFunctionList = class(TList)
129 Parent: TCommonBlock;
130 procedure Parse(Compiler: TCompiler);
131 function Search(Name: string): TFunction;
132 end;
133
134 TModule = class(TCommonBlock)
135 ModuleType: TModuleType;
136 UsedModules: TList; // TList<TModule>
137 constructor Create; override;
138 destructor Destroy; override;
139 procedure Parse(Compiler: TCompiler);
140 private
141 procedure ParseUnit(Compiler: TCompiler);
142 procedure ParseProgram(Compiler: TCompiler);
143 procedure Clear;
144 end;
145
146 TProgram = class
147 Device: TDevice;
148 Modules: TList; // TList<TModule>
149 constructor Create;
150 destructor Destroy; override;
151 procedure Parse(Compiler: TCompiler);
152 procedure AllocateMemory;
153 procedure GenerateAssembler(Compiler: TCompiler);
154 end;
155
156 TAssemblerLine = class
157 LabelName: string;
158 Instruction: string;
159 Operand1: string;
160 Operand2: string;
161 SourceCode: string;
162 function AsString: string;
163 end;
164
165 TCompiler = class
166 private
167 SourceCode: TStringList;
168 CodePosition: Integer;
169 AssemblyCode: TList; // TList<TAssemblerLine>
170 ProgramCode: TProgram;
171 procedure ErrorMessage(Text: string);
172 function IsAlphanumeric(Character: Char): Boolean;
173 function NextCode(Shift: Boolean = False): string;
174 function ReadCode: string;
175 procedure Expect(Code: string);
176 function IsWhiteSpace(Character: Char): Boolean;
177 function IsAlphabetic(Character: Char): Boolean;
178 function IsIdentificator(Text: string): Boolean;
179 function IsKeyword(Text: string): Boolean;
180 function IsOperator(Text: string): Boolean;
181 procedure GenerateAssemblyCode;
182 procedure AddInstruction(LabelName, Instruction, Operand1, Operand2: string);
183 public
184 constructor Create;
185 procedure Compile(SourceCode: TStrings);
186 destructor Destroy; override;
187 end;
188
189 TMainForm = class(TForm)
190 Memo1: TMemo;
191 Button1: TButton;
192 Memo2: TMemo;
193 Memo3: TMemo;
194 procedure FormShow(Sender: TObject);
195 procedure FormClose(Sender: TObject; var Action: TCloseAction);
196 procedure Button1Click(Sender: TObject);
197 procedure FormCreate(Sender: TObject);
198 procedure FormDestroy(Sender: TObject);
199 private
200 { Private declarations }
201 public
202 Compiler: TCompiler;
203 end;
204
205const
206 KeyWords: array[0..37] of string = ('program', 'unit', 'uses', 'begin', 'end',
207 'type', 'const', 'var', 'array', 'record', 'absolute', 'virtual', 'class',
208 'set', 'private', 'public', 'interface', 'implementation', 'finalization',
209 'initialization', 'for', 'while', 'if', 'case', 'of', 'pointer',
210 'object', 'packed', 'procedure', 'function', 'to', 'do', 'downto', 'repeat',
211 'until', 'then', 'asm', 'else');
212 Operators: array[0..22] of string = ('@', 'not', '*', 'and', '/', 'shl',
213 'shr', 'as', 'div', 'mod', 'or', 'xor', '-', '+', '=', '>', '<', '<>', '<=',
214 '>=', 'is', 'in', ':=');
215
216var
217 MainForm: TMainForm;
218
219implementation
220
221{$R *.dfm}
222
223procedure TMainForm.Button1Click(Sender: TObject);
224var
225 I: Integer;
226begin
227 Compiler.Compile(Memo1.Lines);
228 Memo2.Clear;
229 for I := 0 to Compiler.AssemblyCode.Count - 1 do
230 Memo2.Lines.Add(TAssemblerLine(Compiler.AssemblyCode[I]).AsString);
231end;
232
233procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
234begin
235 Memo1.Lines.SaveToFile('Example.pas');
236end;
237
238procedure TMainForm.FormCreate(Sender: TObject);
239begin
240 Compiler := TCompiler.Create;
241end;
242
243procedure TMainForm.FormDestroy(Sender: TObject);
244begin
245 Compiler.Destroy;
246end;
247
248procedure TMainForm.FormShow(Sender: TObject);
249var
250 I: Integer;
251begin
252 Memo1.Lines.LoadFromFile('Example.pas');
253 Compiler.Compile(Memo1.Lines);
254 Memo2.Clear;
255 for I := 0 to Compiler.AssemblyCode.Count - 1 do
256 Memo2.Lines.Add(TAssemblerLine(Compiler.AssemblyCode[I]).AsString);
257
258end;
259
260{ TCompiler }
261
262procedure TCompiler.AddInstruction(LabelName, Instruction, Operand1,
263 Operand2: string);
264var
265 NewLine: TAssemblerLine;
266begin
267 NewLine := TAssemblerLine.Create;
268 AssemblyCode.Add(NewLine);
269 NewLine.LabelName := LabelName;
270 NewLine.Instruction := Instruction;
271 NewLine.Operand1 := Operand1;
272 NewLine.Operand2 := Operand2;
273end;
274
275procedure TCompiler.Compile(SourceCode: TStrings);
276begin
277 MainForm.Memo3.Clear;
278 Self.SourceCode.Assign(SourceCode);
279 CodePosition := 1;
280 ProgramCode.Parse(Self);
281 ProgramCode.AllocateMemory;
282 AssemblyCode.Clear;
283 GenerateAssemblyCode;
284end;
285
286constructor TCompiler.Create;
287begin
288 SourceCode := TStringList.Create;
289 AssemblyCode := TList.Create;
290 ProgramCode := TProgram.Create;
291end;
292
293destructor TCompiler.Destroy;
294begin
295 ProgramCode.Free;
296 AssemblyCode.Free;
297 SourceCode.Free;
298end;
299
300procedure TCompiler.ErrorMessage(Text: string);
301begin
302 //ShowMessage(Text);
303 MainForm.Memo3.Lines.Add(Text);
304end;
305
306procedure TCompiler.Expect(Code: string);
307begin
308 if NextCode <> Code then begin
309 ErrorMessage('Expected ' + Code + ' but ' + NextCode + ' found.');
310 end;
311 ReadCode;
312end;
313
314procedure TCompiler.GenerateAssemblyCode;
315begin
316 ProgramCode.GenerateAssembler(Self);
317end;
318
319function TCompiler.IsAlphabetic(Character: Char): Boolean;
320begin
321 Result := (Character in ['a'..'z']) or (Character in ['A'..'Z']);
322end;
323
324function TCompiler.IsAlphanumeric(Character: Char): Boolean;
325begin
326 Result := IsAlphabetic(Character) or (Character in ['0'..'9']);
327end;
328
329function TCompiler.IsKeyword(Text: string): Boolean;
330var
331 I: Integer;
332begin
333 Result := False;
334 for I := 0 to High(Keywords) do
335 if Keywords[I] = Text then
336 Result := True;
337end;
338
339function TCompiler.IsOperator(Text: string): Boolean;
340var
341 I: Integer;
342begin
343 Result := False;
344 for I := 0 to High(Operators) do
345 if Operators[I] = Text then
346 Result := True;
347end;
348
349function TCompiler.IsIdentificator(Text: string): Boolean;
350var
351 I: Integer;
352begin
353 Result := True;
354 if Length(Text) = 0 then Result := False;
355 if IsKeyWord(Text) then Result := False;
356 if Length(Text) > 0 then
357 if not (Text[1] in ['a'..'z', 'A'..'Z', '%', '_']) then
358 Result := False;
359 for I := 2 to Length(Text) do
360 if not (Text[i] in ['a'..'z', 'A'..'Z', '0'..'9', '_']) then
361 Result := False;
362end;
363
364function TCompiler.IsWhiteSpace(Character: Char): Boolean;
365begin
366 Result := (Character = ' ') or (Character = #13) or (Character = #10);
367end;
368
369function TCompiler.NextCode(Shift: Boolean = False): string;
370var
371 I: Integer;
372// II: Integer;
373 J: Integer;
374const
375 SpecChar: set of char = [';', '.', ',', ':', '(', ')', '[', ']', '+', '-', '/', '*',
376 '^', '=', '<' , '>' , '@'];
377 DoubleSpecChar : array[1..7] of string = (':=', '..', '<=', '>=', '<>', '+=', '-=');
378begin
379 Result := '';
380 J := CodePosition;
381 I := CodePosition;
382 with SourceCode do
383 while Result = '' do begin
384 while IsWhiteSpace(Text[I]) do Inc(I);
385 J := I;
386 if Copy(Text, J, 1) = '//' then begin
387 while (Text[I] <> #13) and (Text[I] <> #10) do Inc(I);
388 Result := '';
389 end else
390 if Copy(Text, J, 1) = '{' then begin
391 while (Text[I] <> '}') do Inc(I);
392 Result := '';
393 end else
394 if Copy(Text, J, 1) = '(*' then begin
395 while not((Text[I] = '*') and (Text[I + 1] = ')')) do Inc(I);
396 Result := '';
397 end else
398 if Text[J] = '''' then begin
399 I := J + 1;
400 while not ((Text[I] = '''') and (Text[I + 1] <> '''')) do Inc(I);
401 Inc(I);
402 Result := Copy(Text, J, I - J );
403 end else
404 if (Text[J] in SpecChar) then begin
405 if (Text[J + 1] in SpecChar) then begin
406 for I := 0 to High(DoubleSpecChar) do
407 if Copy(Text, J, 2) = DoubleSpecChar[I] then begin
408 Result := Copy(Text, J, 2);
409 Inc(J, 2);
410 Break;
411 end;
412 I := J;
413 end;
414 if Result = '' then begin
415 Result := Text[J];
416 Inc(I);
417 end;
418 end else begin
419 while IsAlphanumeric(Text[I]) do Inc(I);
420 Result := LowerCase(Copy(Text, J, I - J));
421 end;
422 J := I;
423 end;
424 if Shift then CodePosition := J;
425end;
426
427procedure TModule.ParseUnit(Compiler: TCompiler);
428begin
429 with Compiler do begin
430 Expect('unit');
431 with TModule(ProgramCode.Modules[0]) do begin
432 Name := ReadCode;
433 ModuleType := mdUnit;
434 end;
435 Expect(';');
436 //ParseInterface;
437 //ParseImplementation;
438 end;
439end;
440
441function TCompiler.ReadCode: string;
442begin
443 Result := NextCode(True);
444end;
445
446{ TFunction }
447
448constructor TFunction.Create;
449begin
450 inherited;
451 Parameters := TList.Create;
452 ResultType := TType.Create;
453end;
454
455destructor TFunction.Destroy;
456begin
457 Parameters.Free;
458 ResultType.Free;
459 inherited;
460end;
461
462procedure TFunction.Parse(Compiler: TCompiler);
463begin
464 with Compiler do begin
465 if NextCode = 'var' then TVariableList(Variables).Parse(Compiler)
466 else if NextCode = 'const' then TConstantList(Constants).Parse(Compiler)
467 else if NextCode = 'type' then TTypeList(Types).Parse(Compiler)
468 else ProgramCode.Parse(Compiler);
469 end;
470end;
471
472{ TProgram }
473
474procedure TProgram.AllocateMemory;
475var
476 I: Integer;
477begin
478 for I := 0 to Modules.Count - 1 do
479 TModule(Modules[I]).AllocateMemory;
480end;
481
482constructor TProgram.Create;
483begin
484 Device := TDevice.Create;
485 Modules := TList.Create;
486end;
487
488destructor TProgram.Destroy;
489begin
490
491end;
492
493procedure TProgram.GenerateAssembler(Compiler: TCompiler);
494var
495 I: Integer;
496begin
497 for I := 0 to Modules.Count - 1 do
498 TModule(Modules[I]).GenerateAssembler(Compiler, '');
499end;
500
501procedure TProgram.Parse(Compiler: TCompiler);
502var
503 I: Integer;
504begin
505 for I := 0 to Modules.Count - 1 do
506 TModule(Modules[I]).Clear;
507 Modules.Clear;
508 with TModule(Modules[Modules.Add(TModule.Create)]) do begin
509 Name := 'main';
510 with TType(Types[Types.Add(TType.Create)]) do begin
511 Name := 'byte';
512 Size := 1;
513 UsedType := nil;
514 end;
515 end;
516 TModule(Modules[0]).Parse(Compiler);
517end;
518
519{ TConstant }
520
521procedure TConstant.Parse(Compiler: TCompiler);
522begin
523
524end;
525
526{ TConstantList }
527
528procedure TConstantList.Parse(Compiler: TCompiler);
529begin
530// Compiler.Expect('const');
531// while Compiler.IsIdentificator(Compiler.NextCode) do
532// TConstant(Items[Add(TConstant.Create)]).Parse(Compiler);
533end;
534
535function TConstantList.Search(Name: string): TConstant;
536var
537 I: Integer;
538begin
539 I := 0;
540 while (I < Count) and (TConstant(Items[I]).Name <> Name) do Inc(I);
541 if I < Count then Result := Items[I] else begin
542 if Assigned(Parent.Parent) then Result := Parent.Parent.Constants.Search(Name)
543 else begin
544 Result := nil;
545 end;
546 end;
547end;
548
549{ TModule }
550
551procedure TModule.Clear;
552begin
553 Variables.Clear;
554 Constants.Clear;
555 Methods.Clear;
556 Operations.Clear;
557end;
558
559constructor TModule.Create;
560begin
561 inherited;
562 UsedModules := TList.Create;
563end;
564
565destructor TModule.Destroy;
566begin
567 UsedModules.Destroy;
568 inherited;
569end;
570
571procedure TModule.ParseProgram(Compiler: TCompiler);
572var
573 Identifier: string;
574begin
575 with Compiler do begin
576 if NextCode = 'program' then begin
577 Expect('program');
578 Name := ReadCode;
579 ModuleType := mdProgram;
580 Expect(';');
581 end else Name := '';
582
583 // Uses section
584 if NextCode = 'uses' then begin
585 Identifier := ReadCode;
586 while NextCode = ',' do begin
587 Identifier := ReadCode;
588
589 end;
590 end;
591 ParseDefinitions(Compiler);
592 end;
593end;
594
595procedure TModule.Parse(Compiler: TCompiler);
596begin
597 with Compiler do begin
598 if NextCode = 'program' then ParseProgram(Compiler)
599 else if NextCode = 'unit' then ParseUnit(Compiler)
600 else ParseProgram(Compiler);
601 end;
602end;
603
604procedure TCommonBlock.AllocateMemory;
605begin
606// for I := 0 to Variables - 1 do
607
608end;
609
610procedure TCommonBlock.CheckReferences;
611var
612 I: Integer;
613begin
614 for I := 0 to Operations.Count - 1 do
615 with TOperation(Operations[I]) do begin
616 if (Instruction = inJump) or (Instruction = inConditionalJump) then
617 TOperation(Operations[GotoAddress]).Referenced := True;
618 end;
619end;
620
621constructor TCommonBlock.Create;
622begin
623 Constants := TConstantList.Create;
624 Constants.Parent := Self;
625 Types := TTypeList.Create;
626 Types.Parent := Self;
627 Variables := TVariableList.Create;
628 Variables.Parent := Self;
629 Methods := TFunctionList.Create;
630 Methods.Parent := Self;
631 Operations := TOperationList.Create;
632end;
633
634destructor TCommonBlock.Destroy;
635begin
636 Constants.Destroy;
637 Types.Destroy;
638 Variables.Destroy;
639 Methods.Destroy;
640 Operations.Destroy;
641 inherited;
642end;
643
644procedure TCommonBlock.GenerateAssembler(Compiler: TCompiler; LabelPrefix: string);
645var
646 I: Integer;
647 LabelName: string;
648begin
649 with Compiler do
650 for I := 0 to Operations.Count - 1 do
651 with TOperation(Operations[I]) do begin
652 if Referenced then LabelName := Name + '_L' + IntToStr(I)
653 else LabelName := '';
654 case Instruction of
655 inJump: begin
656 AddInstruction(LabelName, 'JMP', Name + '_L' + IntToStr(GotoAddress), '');
657 end;
658 inConditionalJump: begin
659 ExpressionTree.GenerateAssembler(Compiler, LabelPrefix + '_L' + IntToStr(GotoAddress));
660 AddInstruction(LabelName, 'BRCS', Name + '_L' + IntToStr(GotoAddress), '');
661 end;
662 inExpressionEvaluation: begin
663 if LabelName <> '' then AddInstruction(LabelName, '', '', '');
664 ExpressionTree.GenerateAssembler(Compiler, Name + '_L' + IntToStr(GotoAddress));
665 end;
666 inReturn:
667 AddInstruction(LabelName, 'RET', '', '');
668 end;
669 end;
670end;
671
672procedure TCommonBlock.ParseDefinitions(Compiler: TCompiler);
673begin
674 with Compiler do begin
675 while NextCode <> '.' do begin
676 if NextCode = 'var' then TVariableList(Variables).Parse(Compiler)
677 else if NextCode = 'const' then TConstantList(Constants).Parse(Compiler)
678 else if NextCode = 'type' then TTypeList(Types).Parse(Compiler)
679 else begin
680 ParseProgramCode(Compiler);
681 Break;
682 end;
683 end;
684 end;
685end;
686
687function TCommonBlock.ParseExpression(Compiler: TCompiler): TExpression;
688var
689 Identifier: string;
690 NewVariable: TVariable;
691 Method: TFunction;
692 Constant: TConstant;
693// Brackets: Integer;
694 Expressions: TList; // TList<TExpression>;
695 I: Integer;
696 II: Integer;
697begin
698 Expressions := TList.Create;
699 Expressions.Add(TExpression.Create);
700 with Compiler do begin
701 while ((NextCode <> ';') and (NextCode <> ',') and (not IsKeyWord(NextCode))) and
702 not (((NextCode = ')') or (NextCode = ']'))) do begin
703 Identifier := ReadCode;
704 if Identifier = '(' then begin
705 with TExpression(Expressions[Expressions.Count - 1]) do begin
706 SubItems[1] := ParseExpression(Compiler);
707 end;
708 with TExpression(Expressions.Items[Expressions.Add(TExpression.Create)]) do begin
709 SubItems[0] := TExpression(Expressions[Expressions.Count - 2]).SubItems[1];
710 end;
711 Expect(')');
712 end else
713 if IsOperator(Identifier) then begin
714 TExpression(Expressions[Expressions.Count - 1]).OperatorName := Identifier;
715 TExpression(Expressions[Expressions.Count - 1]).NodeType := ntOperator;
716 end else
717 if IsIdentificator(Identifier) then begin
718 NewVariable := Variables.Search(Identifier);
719 if Assigned(NewVariable) then begin
720 with TExpression(Expressions[Expressions.Count - 1]) do begin
721 SubItems[1] := TExpression.Create;
722 TExpression(SubItems[1]).NodeType := ntVariable;
723 TExpression(SubItems[1]).Variable := NewVariable;
724 end;
725 with TExpression(Expressions.Items[Expressions.Add(TExpression.Create)]) do begin
726 SubItems[0] := TExpression(Expressions[Expressions.Count - 2]).SubItems[1];
727 end;
728 end else begin
729 Method := Methods.Search(Identifier);
730 if Assigned(Method) then begin
731 with TExpression(Expressions[Expressions.Count - 1]) do begin
732 SubItems[1] := TExpression.Create;
733 if NextCode = '(' then // Method with parameters
734 with TExpression(SubItems[1]) do begin
735 Expect('(');
736 SubItems.Add(ParseExpression(Compiler));
737 while NextCode = ',' do begin
738 Expect(',');
739 SubItems.Add(ParseExpression(Compiler));
740 end;
741 Expect(')');
742 end;
743 TExpression(SubItems[1]).NodeType := nTFunction;
744 TExpression(SubItems[1]).Method := Method;
745 end;
746 with TExpression(Expressions.Items[Expressions.Add(TExpression.Create)]) do begin
747 SubItems[0] := TExpression(Expressions[Expressions.Count - 2]).SubItems[1];
748 end;
749 end else begin
750 Constant := Constants.Search(Identifier);
751 if Assigned(Constant) then begin
752 with TExpression(Expressions[Expressions.Count - 1]) do begin
753 SubItems[1] := TExpression.Create;
754 TExpression(SubItems[1]).NodeType := ntConstant;
755 TExpression(SubItems[1]).Value := Constant.Value;
756 end;
757 with TExpression(Expressions.Items[Expressions.Add(TExpression.Create)]) do begin
758 SubItems[0] := TExpression(Expressions[Expressions.Count - 2]).SubItems[1];
759 end;
760 end else begin
761 ErrorMessage('Neznámý identifikátor: ' + Identifier);
762 end;
763 end;
764 end;
765 end else
766 begin
767 with TExpression(Expressions[Expressions.Count - 1]) do begin
768 SubItems[1] := TExpression.Create;
769 TExpression(SubItems[1]).NodeType := ntConstant;
770
771 if Identifier[1] = '''' then begin
772 SetLength(TExpression(SubItems[1]).Value, Length(Identifier));
773 for I := 1 to Length(Identifier) do TExpression(SubItems[1]).Value[I - 1] := Byte(Identifier[I]);
774 end else begin
775 SetLength(TExpression(SubItems[1]).Value, 1);
776 TExpression(SubItems[1]).Value[0] := StrToInt(Identifier);
777 end;
778 end;
779 with TExpression(Expressions.Items[Expressions.Add(TExpression.Create)]) do begin
780 SubItems[0] := TExpression(Expressions[Expressions.Count - 2]).SubItems[1];
781 end;
782 end;
783 end;
784
785 // Build expression tree
786 for II := 0 to High(Operators) do begin
787 I := 1;
788 while (I < Expressions.Count - 1) do begin
789 if not TExpression(Expressions[I]).Associated and
790 (TExpression(Expressions[I]).OperatorName = Operators[II]) then begin
791 TExpression(Expressions[I]).Associated := True;
792 TExpression(Expressions[I - 1]).SubItems[1] := Expressions[I];
793 TExpression(Expressions[I + 1]).SubItems[0] := Expressions[I];
794 Expressions.Delete(I);
795 end else Inc(I);
796 end;
797 end;
798 end;
799 Result := TExpression(Expressions[0]).SubItems[1];
800 TExpression(Expressions[0]).Destroy;
801 TExpression(Expressions[1]).Destroy;
802 Expressions.Destroy;
803end;
804
805procedure TCommonBlock.ParseOperation(Compiler: TCompiler);
806var
807 Identifier: string;
808 Variable: TVariable;
809 Method: TFunction;
810 First: TOperation;
811 Second: TOperation;
812 StartIndex: Integer;
813 LoopVaraible: TVariable;
814begin
815 with Compiler do begin
816 if NextCode = 'begin' then ParseProgramCode(Compiler)
817 else if NextCode = 'if' then begin
818 Expect('if');
819 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
820 Instruction := inConditionalJump;
821 ExpressionTree := ParseExpression(Compiler);
822 Negative := True;
823 end;
824 First := Operations[Operations.Count - 1];
825 Expect('then');
826 ParseOperation(Compiler);
827 if NextCode = 'else' then begin
828 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
829 Instruction := inJump;
830 end;
831 Second := Operations[Operations.Count - 1];
832 First.GotoAddress := Operations.Count;
833 Expect('else');
834 ParseOperation(Compiler);
835 Second.GotoAddress := Operations.Count;
836 end else First.GotoAddress := Operations.Count;
837 end
838 else if NextCode = 'repeat' then begin
839 Expect('repeat');
840 StartIndex := Operations.Count;
841 ParseOperation(Compiler);
842 Expect('until');
843 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
844 Instruction := inConditionalJump;
845 ExpressionTree := ParseExpression(Compiler);
846 GotoAddress := StartIndex;
847 end;
848 end
849 else if NextCode = 'while' then begin
850 Expect('while');
851 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
852 Instruction := inConditionalJump;
853 ExpressionTree := ParseExpression(Compiler);
854 end;
855 First := Operations[Operations.Count - 1];
856 StartIndex := Operations.Count - 1;
857 Expect('do');
858 ParseOperation(Compiler);
859 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
860 Instruction := inJump;
861 GotoAddress := StartIndex;
862 end;
863 First.GotoAddress := Operations.Count;
864 end
865 else if NextCode = 'for' then begin
866 Expect('for');
867 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
868 Instruction := inExpressionEvaluation;
869 ExpressionTree := ParseExpression(Compiler);
870 if (ExpressionTree.NodeType <> ntOperator) and
871 (ExpressionTree.OperatorName <> ':=') then ErrorMessage('Expected assigment in for loop');
872 if TExpression(TExpression(ExpressionTree).SubItems[0]).NodeType <> ntVariable then
873 ErrorMessage('Index in FOR loop have to be variable');
874 LoopVaraible := TExpression(TExpression(ExpressionTree).SubItems[0]).Variable;
875 end;
876 Expect('to');
877 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
878 Instruction := inExpressionEvaluation;
879 ExpressionTree := TExpression.Create;
880 with ExpressionTree do begin
881 NodeType := ntOperator;
882 OperatorName := '=';
883 SubItems[0] := TExpression.Create;
884 with TExpression(SubItems[0]) do begin
885 NodeType := ntVariable;
886 Variable := LoopVaraible;
887 end;
888 SubItems[1] := ParseExpression(Compiler);
889 end;
890 Negative := True;
891 end;
892 First := Operations[Operations.Count - 1];
893 StartIndex := Operations.Count - 1;
894 Expect('do');
895 ParseOperation(Compiler);
896 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
897 Instruction := inExpressionEvaluation;
898 ExpressionTree := TExpression.Create;
899 with ExpressionTree do begin
900 NodeType := ntOperator;
901 OperatorName := ':=';
902 SubItems[0] := TExpression.Create;
903 with TExpression(SubItems[0]) do begin
904 NodeType := ntVariable;
905 Variable := LoopVaraible;
906 end;
907 SubItems[1] := TExpression.Create;
908 with TExpression(SubItems[1]) do begin
909 NodeType := ntOperator;
910 OperatorName := '+';
911 SubItems[0] := TExpression.Create;
912 with TExpression(SubItems[0]) do begin
913 NodeType := ntVariable;
914 Variable := LoopVaraible;
915 end;
916 SubItems[1] := TExpression.Create;
917 with TExpression(SubItems[1]) do begin
918 NodeType := ntConstant;
919 SetLength(Value, 1);
920 Value[0] := 1;
921 end;
922 end;
923 end;
924 end;
925 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
926 Instruction := inJump;
927 GotoAddress := StartIndex;
928 end;
929 First.GotoAddress := Operations.Count;
930 end
931 else begin
932 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
933 Instruction := inExpressionEvaluation;
934 ExpressionTree := ParseExpression(Compiler);
935 end;
936 end;
937 end;
938end;
939
940procedure TCommonBlock.ParseProgramCode(Compiler: TCompiler);
941begin
942 with Compiler do begin
943 Expect('begin');
944 while NextCode <> 'end' do begin
945 ParseOperation(Compiler);
946 Expect(';');
947 end;
948 Expect('end');
949 with TOperation(Operations[Operations.Add(TOperation.Create)]) do begin
950 Instruction := inReturn;
951 end;
952 end;
953 CheckReferences;
954end;
955
956{ TTypeList }
957
958procedure TTypeList.Parse(Compiler: TCompiler);
959begin
960 with Compiler do begin
961 Expect('type');
962 while IsIdentificator(NextCode) do
963 with TType(Items[Add(TType.Create)]) do begin
964 Parent := Self;
965 Parse(Compiler);
966 end;
967 end;
968end;
969
970function TTypeList.Search(Name: string): TType;
971var
972 I: Integer;
973begin
974 I := 0;
975 while (I < Count) and (TType(Items[I]).Name <> Name) do Inc(I);
976 if I < Count then Result := Items[I] else begin
977 if Assigned(Parent.Parent) then Result := Parent.Parent.Types.Search(Name)
978 else begin
979 Result := nil;
980 end;
981 end;
982end;
983
984{ TVariableList }
985
986procedure TVariableList.Parse(Compiler: TCompiler);
987var
988 Identifiers: TStringList;
989 NewValueType: TType;
990 TypeName: string;
991 VariableName: string;
992 Variable: TVariable;
993 I: Integer;
994begin
995 Identifiers := TStringList.Create;
996 with Compiler do begin
997 Expect('var');
998 while IsIdentificator(NextCode) do begin
999 VariableName := ReadCode;
1000 Variable := Search(VariableName);
1001 if not Assigned(Variable) then begin
1002 Identifiers.Add(VariableName);
1003 while NextCode = ',' do begin
1004 Expect(',');
1005 Identifiers.Add(ReadCode);
1006 end;
1007 end else ErrorMessage('Pøedefinování existující promìnné.');
1008 Expect(':');
1009 TypeName := ReadCode;
1010 NewValueType := Parent.Types.Search(TypeName);
1011 if NewValueType = nil then ErrorMessage('Typ ' + TypeName + ' nebyl definován.')
1012 else for I := 0 to Identifiers.Count - 1 do
1013 with TVariable(Items[Add(TVariable.Create)]) do begin
1014 Name := Identifiers[I];
1015 ValueType := NewValueType;
1016 end;
1017 Expect(';');
1018 end;
1019 end;
1020 Identifiers.Destroy;
1021end;
1022
1023function TVariableList.Search(Name: string): TVariable;
1024var
1025 I: Integer;
1026begin
1027 I := 0;
1028 while (I < Count) and (TVariable(Items[I]).Name <> Name) do Inc(I);
1029 if I < Count then Result := Items[I] else begin
1030 if Assigned(Parent.Parent) then Result := Parent.Parent.Variables.Search(Name)
1031 else begin
1032 Result := nil;
1033 end;
1034 end;
1035end;
1036
1037{ TVariable }
1038
1039procedure TVariable.Parse(Compiler: TCompiler);
1040begin
1041end;
1042
1043{ TType }
1044
1045procedure TType.Parse(Compiler: TCompiler);
1046begin
1047 with Compiler do begin
1048 Name := NextCode;
1049 Expect('=');
1050 UsedType := Parent.Search(NextCode);
1051 end;
1052end;
1053
1054{ TFunctionList }
1055
1056procedure TFunctionList.Parse(Compiler: TCompiler);
1057begin
1058
1059end;
1060
1061function TFunctionList.Search(Name: string): TFunction;
1062var
1063 I: Integer;
1064begin
1065 I := 0;
1066 while (I < Count) and (TFunction(Items[I]).Name <> Name) do Inc(I);
1067 if I < Count then Result := Items[I] else begin
1068 if Assigned(Parent.Parent) then Result := Parent.Parent.Methods.Search(Name)
1069 else begin
1070 Result := nil;
1071 end;
1072 end;
1073end;
1074
1075{ TExpression }
1076
1077constructor TExpression.Create;
1078begin
1079 SubItems := TList.Create;
1080 SubItems.Count := 2;
1081end;
1082
1083destructor TExpression.Destroy;
1084begin
1085 SubItems.Destroy;
1086 inherited;
1087end;
1088
1089procedure TExpression.GenerateAssembler(Compiler: TCompiler; LabelPrefix: string);
1090var
1091 I: Integer;
1092begin
1093 with Compiler do
1094 case NodeType of
1095 ntNone: ;
1096 ntVariable: if Assigned(Variable) then AddInstruction('', 'GETVAR', Variable.Name, '');
1097 nTFunction: AddInstruction('', 'CALL', Method.Name, '');
1098 ntConstant: AddInstruction('', 'CONST', '', '');
1099 ntOperator: begin
1100 for I := 0 to SubItems.Count - 1 do
1101 TExpression(SubItems[I]).GenerateAssembler(Compiler, LabelPrefix);
1102 if OperatorName = '+' then AddInstruction('', 'ADD', '', '')
1103 else if OperatorName = '-' then AddInstruction('', 'SUB', '', '')
1104 else if OperatorName = '*' then AddInstruction('', 'MUL', '', '')
1105 else if OperatorName = '/' then AddInstruction('', 'DIV', '', '')
1106 else if OperatorName = 'div' then AddInstruction('', 'DIV', '', '')
1107 else if OperatorName = 'mod' then AddInstruction('', 'MOD', '', '')
1108 else if OperatorName = 'xor' then AddInstruction('', 'XOR', '', '')
1109 else if OperatorName = 'or' then AddInstruction('', 'OR', '', '')
1110 else if OperatorName = 'and' then AddInstruction('', 'AND', '', '')
1111 else if OperatorName = 'not' then AddInstruction('', 'NEG', '', '')
1112 else if OperatorName = ':=' then AddInstruction('', 'ST', '', '')
1113 else if OperatorName = '>' then AddInstruction('', 'CP', '', '')
1114 else if OperatorName = '>=' then AddInstruction('', 'CP', '', '')
1115 else if OperatorName = '<' then AddInstruction('', 'CP', '', '')
1116 else if OperatorName = '<=' then AddInstruction('', 'CP', '', '')
1117 else if OperatorName = '=' then AddInstruction('', 'TST', '', '')
1118 else if OperatorName = '<>' then AddInstruction('', 'CP', '', '');
1119 end;
1120 end;
1121end;
1122
1123{ TAssemblerLine }
1124
1125function TAssemblerLine.AsString: string;
1126begin
1127 if LabelName = '' then LabelName := #9 else
1128 LabelName := LabelName + ':'#9;
1129 if Operand2 <> '' then Operand1 := Operand1 + ', ';
1130
1131 Result := LabelName + Instruction + ' ' + Operand1 + Operand2;
1132end;
1133
1134end.
Note: See TracBrowser for help on using the repository browser.