-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCompilerLib.pas
161 lines (120 loc) · 5.06 KB
/
CompilerLib.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
library CompilerLib;
{$mainresource Resources\IconRes.res}
//TODO: Ñäåëàòü íîðìàëüíî try..except, try..finally
//TODO: Ñäåëàòü çíàêè + äëÿ char è string
//TODO: Ðåàëèçîâàòü ïåðå÷èñëèìûé òèï
// type Months = (January,February,March,April,May,June,July,August,September,October,November,December);
uses
PABCSystem,
System,
System.IO,
System.Collections,
System.Collections.Generic,
ASemanticTree,
ASyntaxTree,
ScannerUnit,
SyntaxAnalyze,
TreeConverter,
CodeGen,
CommonUnit;
const
LibSource = 'LibSource';
var
Scanner: GScanner;
Parser: GParser;
Converter: GConverter;
CodeGenerator: GCodeGenerator;
type
MessageType = (Info, Warning, Error);
MessageInfo = class
MType: MessageType;
Text: string;
Loc: Location;
public
constructor Create(Text: string);
constructor Create(Text: string; MType: MessageType);
constructor Create(Text: string; MType: MessageType; Loc: Location);
end;
MessageProc = procedure(Message: MessageInfo);
Compiler = class
private
OutputProc : MessageProc;
function GetSyntaxTree(UnitName: string; Dir: string): UnitTree;
public
procedure CompilerMessage(msg: string);
procedure Compile(Options: CompilerOptions; OutputProc: MessageProc);
end;
var Options : CompilerOptions;
constructor MessageInfo.Create(Text: string);
begin
self.Text := Text;
self.MType := MessageType.Info;
end;
constructor MessageInfo.Create(Text: string; MType: MessageType);
begin
self.Text := Text;
self.MType := MType;
end;
constructor MessageInfo.Create(Text: string; MType: MessageType; Loc: Location);
begin
self.Text := Text;
self.MType := MType;
self.Loc := Loc;
end;
procedure Compiler.CompilerMessage(msg: string);
begin
OutputProc(new MessageInfo(msg));
end;
/// ôóíêöèÿ êîòîðóþ âûçûâàåò ñåìàíòè÷åñêèé àíàëèçàòîð äëÿ çàãðóçêè â íåãî ñèíòàêñè÷åñêîãî äåðåâî íóæíîãî ìîäóëÿ
function Compiler.GetSyntaxTree(UnitName: string; Dir: string): UnitTree;
begin
// Ãäå áóäåì èñêàòü Unit
var UnitSearchPaths := new List<string>;
UnitSearchPaths.Add(Dir); // Ïàïêà ãäå ëåæèò ôàéë â êîòîðîì âêëþ÷åí äàííûé Unit
UnitSearchPaths.Add(Path.Combine(Path.GetDirectoryName(GetEXEFilename), LibSource));
UnitSearchPaths.Add(Environment.CurrentDirectory); // òåêóùàÿ ïàïêà
UnitSearchPaths.Add(Path.GetDirectoryName(GetEXEFilename)); // ãäå íàõîäèòñÿ ñàì êîìïèëÿòîð
foreach s: string in UnitSearchPaths do
begin
var fname := Path.Combine(s, UnitName + '.pas');
if &File.Exists(fname) then
begin
var scan := new GScanner(fname, Options.DefineList);
var pars := new GParser(scan.Tokens, fname);
Result := (pars.SyntaxTree as UnitTree);
end;
end;
if not (Result is UnitTree) then Result := nil;
end;
procedure Compiler.Compile(Options: CompilerOptions; OutputProc: MessageProc);
begin
CommonUnit.Options := Options;
self.OutputProc := OutputProc;
CompilerMessage(Format('Ñòàðò êîìïèëÿöèè "{0}"...', Path.GetFileName(Options.SourceFile)));
// Êîìïèëÿòîð ðàáîòàåò â 4 ïðîõîäà:
// Ëåêñè÷åñêèé àíàëèç. Íà ýòîì ýòàïå ïîñëåäîâàòåëüíîñòü ñèìâîëîâ èñõîäíîãî ôàéëà ïðåîáðàçóåòñÿ â ïîñëåäîâàòåëüíîñòü ëåêñåì.
// Âûïîëíÿåò åù¸ ôóíêöèè ïðåïðîöåññîðà
var startCompileTime := Milliseconds;
Scanner := new GScanner(Options.SourceFile, Options.DefineList);
var ScanTime := Milliseconds - startCompileTime;
// Ñèíòàêñè÷åñêèé (ãðàììàòè÷åñêèé) àíàëèç. Ïîñëåäîâàòåëüíîñòü ëåêñåì ïðåîáðàçóåòñÿ â äåðåâî ðàçáîðà.
Parser := new GParser(Scanner.Tokens, Options.SourceFile);
var ParsTime := Milliseconds - (ScanTime + startCompileTime);
// Ñåìàíòè÷åñêèé àíàëèç. Äåðåâî ðàçáîðà îáðàáàòûâàåòñÿ ñ öåëüþ óñòàíîâëåíèÿ åãî ñåìàíòèêè (ñìûñëà)
Converter := new GConverter(Parser.SyntaxTree, GetSyntaxTree);
var TreeConvertTime := Milliseconds - (ScanTime + startCompileTime + ParsTime);
// Ãåíåðàöèÿ êîäà. Èç ñåìàíòè÷åñêîãî äåðåâà ïîðîæäàåòñÿ MSIL êîä.
if (Converter.SemanticTree is SUnitTree) then raise new Exception('îæèäàëàñü ïðîãðàììà èëè áèáëèîòåêà, à íå ìîäóëü.');
CodeGenerator := new GCodeGenerator(Options.OutFile, Converter.SemanticTree);
var CodeGenTime := Milliseconds - (ScanTime + startCompileTime + ParsTime + TreeConvertTime);
// ===========================================================================
CompilerMessage(Format('Êîìïèëÿöèÿ "{0}" çàâåðøåíà óñïåøíî.', Path.GetFileName(Options.SourceFile)));
CompilerMessage(' ÂÐÅÌß ÐÀÁÎÒÛ ');
CompilerMessage(Format('1.Ñêàíèðîâàíèå è ïðåïðîöåññîð :{0} ìñ ({1:f2}%)', ScanTime, (ScanTime / Milliseconds) * 100));
CompilerMessage(Format('2.Ïàðñèíã :{0} ìñ ({1:f2}%)', ParsTime, (ParsTime / Milliseconds) * 100));
CompilerMessage(Format('3.Êîíâåðòèðîâàíèå äåðåâà è îïòèìèçàöèÿ :{0} ìñ ({1:f2}%)', TreeConvertTime, (TreeConvertTime / Milliseconds) * 100));
CompilerMessage(Format('4.Êîäîãåíåðàöèÿ :{0} ìñ ({1:f2}%)', CodeGenTime, (CodeGenTime / Milliseconds) * 100));
CompilerMessage(Format(' Îáùåå âðåìÿ ðàáîòû ïðîãðàììû :{0} ìñ', Milliseconds));
end;
begin
end.