1 | unit UBuilder;
|
---|
2 |
|
---|
3 | {$mode delphi}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses
|
---|
8 | Classes, SysUtils, UGrammer, StrUtils;
|
---|
9 |
|
---|
10 | type
|
---|
11 |
|
---|
12 | { TBuilder }
|
---|
13 |
|
---|
14 | TBuilder = class
|
---|
15 | private
|
---|
16 | LocalFunctions: string;
|
---|
17 | LocalFunctionIndex: Integer;
|
---|
18 | function Indent(Count: Integer): string;
|
---|
19 | function GetItemString(Item: TRuleItem; Required: Boolean; IndentLevel: Integer): string;
|
---|
20 | function StringText(const Text: string; Escaped: Boolean): string;
|
---|
21 | procedure BuildMain(FileName: string);
|
---|
22 | procedure BuildParser(FileName: string);
|
---|
23 | function BuildParserItems(Items: TRuleItems; Required: Boolean; IndentLevel: Integer): string;
|
---|
24 | procedure BuildSource(FileName: string);
|
---|
25 | procedure BuildTokenizer(FileName: string);
|
---|
26 | function BuildTokenizerItems(SourceFile: TStrings; Items: TRuleItems): string;
|
---|
27 | public
|
---|
28 | Grammer: TGrammer;
|
---|
29 | procedure BuildCompiler;
|
---|
30 | end;
|
---|
31 |
|
---|
32 |
|
---|
33 | const
|
---|
34 | BooleanText: array[Boolean] of string = ('False', 'True');
|
---|
35 |
|
---|
36 | implementation
|
---|
37 |
|
---|
38 | function TBuilder.Indent(Count: Integer): string;
|
---|
39 | begin
|
---|
40 | Result := DupeString(' ', Count);
|
---|
41 | end;
|
---|
42 |
|
---|
43 | function TBuilder.GetItemString(Item: TRuleItem; Required: Boolean; IndentLevel: Integer): string;
|
---|
44 | begin
|
---|
45 | Result := '';
|
---|
46 | case Item.RuleItemType of
|
---|
47 | ritTerminal: Result := 'Expect(''' +
|
---|
48 | StringText(Item.Terminal, Item.EscapedStrings) + ''', Required and ' + BooleanText[Required] + ')';
|
---|
49 | ritNonTerminal: Result := 'Parse' + Item.NonTerminal.Name + '(Required and ' + BooleanText[Required] + ')';
|
---|
50 | ritTerminalRange: Result := 'ExpectRange(''' +
|
---|
51 | StringText(Item.TerminalFrom, Item.EscapedStrings) + ''', ''' +
|
---|
52 | StringText(Item.TerminalTo, Item.EscapedStrings) + ''', Required and ' + BooleanText[Required] + ')';
|
---|
53 | ritSubItems: begin
|
---|
54 | LocalFunctions := LocalFunctions + 'function ParseSubitems' + IntToStr(LocalFunctionIndex) + '(Required: Boolean = False): Boolean;' + LineEnding;
|
---|
55 | LocalFunctions := LocalFunctions + 'var' + LineEnding;
|
---|
56 | LocalFunctions := LocalFunctions + ' OldPosition: TPosition;' + LineEnding;
|
---|
57 | LocalFunctions := LocalFunctions + 'begin' + LineEnding;
|
---|
58 | LocalFunctions := LocalFunctions + ' Result := True;' + LineEnding;
|
---|
59 | LocalFunctions := LocalFunctions + BuildParserItems(Item.SubItems, Required, 1);
|
---|
60 | LocalFunctions := LocalFunctions + 'end;' + LineEnding + LineEnding;
|
---|
61 |
|
---|
62 | Result := Result + 'ParseSubitems' + IntToStr(LocalFunctionIndex) + '(Required and ' + BooleanText[Required] + ')';
|
---|
63 | Inc(LocalFunctionIndex);
|
---|
64 | end;
|
---|
65 | end;
|
---|
66 | end;
|
---|
67 |
|
---|
68 | function TBuilder.StringText(const Text: string; Escaped: Boolean): string;
|
---|
69 | begin
|
---|
70 | Result := Text;
|
---|
71 | Result := StringReplace(Result, '''', '''''', [rfReplaceAll]);
|
---|
72 | if Escaped then begin
|
---|
73 | Result := StringReplace(Result, '\n', '''#10''', [rfReplaceAll]);
|
---|
74 | Result := StringReplace(Result, '\r', '''#13''', [rfReplaceAll]);
|
---|
75 | Result := StringReplace(Result, '\t', '''#9''', [rfReplaceAll]);
|
---|
76 | Result := StringReplace(Result, '\\', '\', [rfReplaceAll]);
|
---|
77 | end;
|
---|
78 | end;
|
---|
79 |
|
---|
80 | procedure TBuilder.BuildParser(FileName: string);
|
---|
81 | var
|
---|
82 | ParserFile: TStringList;
|
---|
83 | Rule: TRule;
|
---|
84 | FunctionBody: string;
|
---|
85 | begin
|
---|
86 | ParserFile := TStringList.Create;
|
---|
87 | with ParserFile do begin
|
---|
88 | Add('unit Parser;');
|
---|
89 | Add('');
|
---|
90 | Add('{$MODE Delphi}');
|
---|
91 | Add('');
|
---|
92 | Add('interface');
|
---|
93 | Add('');
|
---|
94 | Add('uses');
|
---|
95 | Add(' SysUtils, Tokenizer, Types;');
|
---|
96 | Add('');
|
---|
97 | Add('type');
|
---|
98 | Add(' TPosition = record');
|
---|
99 | Add(' Index: Integer;');
|
---|
100 | Add(' Pos: TPoint;');
|
---|
101 | Add(' procedure Calc(Text: string);');
|
---|
102 | Add(' end;');
|
---|
103 | Add('');
|
---|
104 | Add(' TParser = class');
|
---|
105 | Add(' Tokenizer: TTokenizer;');
|
---|
106 | Add(' Content: string;');
|
---|
107 | Add(' FileName: string;');
|
---|
108 | Add(' Position: TPosition;');
|
---|
109 | Add(' procedure Error(Text: string);');
|
---|
110 | Add(' function Expect(Text: string; Required: Boolean = False): Boolean;');
|
---|
111 | Add(' function ExpectRange(CharFrom, CharTo: Char; Required: Boolean = False): Boolean;');
|
---|
112 | for Rule in Grammer.Rules do
|
---|
113 | //if Rule.Level = rlParser then
|
---|
114 | Add(' function Parse' + Rule.Name + '(Required: Boolean = False): Boolean;');
|
---|
115 | Add(' constructor Create;');
|
---|
116 | Add(' destructor Destroy; override;');
|
---|
117 | Add(' end;');
|
---|
118 | Add('');
|
---|
119 | Add('');
|
---|
120 | Add('implementation');
|
---|
121 | Add('');
|
---|
122 | Add('procedure TPosition.Calc(Text: string);');
|
---|
123 | Add('var');
|
---|
124 | Add(' I: Integer;');
|
---|
125 | Add('begin');
|
---|
126 | Add(' for I := 1 to Length(Text) do begin');
|
---|
127 | Add(' Inc(Pos.X);');
|
---|
128 | Add(' Inc(Index);');
|
---|
129 | Add(' if Text[I] = LineEnding then begin');
|
---|
130 | Add(' Pos.X := 1;');
|
---|
131 | Add(' Inc(Pos.Y);');
|
---|
132 | Add(' end;');
|
---|
133 | Add(' end;');
|
---|
134 | Add('end;');
|
---|
135 | Add('');
|
---|
136 | Add('constructor TParser.Create;');
|
---|
137 | Add('begin');
|
---|
138 | Add(' Position.Index := 1;');
|
---|
139 | Add(' Position.Pos := Point(1, 1);');
|
---|
140 | Add(' Tokenizer := TTokenizer.Create;');
|
---|
141 | Add('end;');
|
---|
142 | Add('');
|
---|
143 | Add('destructor TParser.Destroy;');
|
---|
144 | Add('begin');
|
---|
145 | Add(' FreeAndNil(Tokenizer);');
|
---|
146 | Add('end;');
|
---|
147 | Add('');
|
---|
148 | Add('procedure TParser.Error(Text: string);');
|
---|
149 | Add('begin');
|
---|
150 | Add(' WriteLn(FileName + ''('' + IntToStr(Position.Pos.X) + '','' + IntToStr(Position.Pos.Y) + '') Error: '' + Text);');
|
---|
151 | Add('end;');
|
---|
152 | Add('');
|
---|
153 | Add('function TParser.Expect(Text: string; Required: Boolean = False): Boolean;');
|
---|
154 | Add('var');
|
---|
155 | Add(' ReadText: string;');
|
---|
156 | Add(' StartPos: TPosition;');
|
---|
157 | Add('begin');
|
---|
158 | Add(' StartPos := Position;');
|
---|
159 | Add(' ReadText := Copy(Content, Position.Index, Length(Text));');
|
---|
160 | Add(' Position.Calc(Text);');
|
---|
161 | Add(' Result := Text = ReadText;');
|
---|
162 | Add(' if not Result then begin');
|
---|
163 | Add(' Position := StartPos;');
|
---|
164 | Add(' if Required then Error(''Expected "'' + Text + ''" but found "'' + ReadText + ''".'');');
|
---|
165 | Add(' end else WriteLn(''Expect: '' + Text);');
|
---|
166 | Add('end;');
|
---|
167 | Add('');
|
---|
168 | Add('function TParser.ExpectRange(CharFrom, CharTo: char; Required: Boolean = False): Boolean;');
|
---|
169 | Add('var');
|
---|
170 | Add(' ReadChar: Char;');
|
---|
171 | Add(' StartPos: TPosition;');
|
---|
172 | Add('begin');
|
---|
173 | Add(' StartPos := Position;');
|
---|
174 | Add(' ReadChar := Content[Position.Index];');
|
---|
175 | Add(' Position.Calc(Content[Position.Index]);');
|
---|
176 | Add(' Result := (ReadChar >= CharFrom) and (ReadChar <= CharTo);');
|
---|
177 | Add(' if not Result then begin');
|
---|
178 | Add(' Position := StartPos;');
|
---|
179 | Add(' if Required then Error(''Expected "'' + CharFrom + ''" to "'' + CharTo + ''" but found "'' + ReadChar + ''".'');');
|
---|
180 | Add(' end else WriteLn(''ExpectRange: '' + CharFrom + ''..'' + CharTo + '': '' + ReadChar);');
|
---|
181 | Add('end;');
|
---|
182 | Add('');
|
---|
183 | for Rule in Grammer.Rules do
|
---|
184 | //if Rule.Level = rlParser then
|
---|
185 | begin
|
---|
186 | LocalFunctionIndex := 1;
|
---|
187 | LocalFunctions := '';
|
---|
188 | FunctionBody := BuildParserItems(Rule.Items, True, 1);
|
---|
189 | Text := Text + 'function TParser.Parse' + Rule.Name + '(Required: Boolean = False): Boolean;' + LineEnding;
|
---|
190 | Text := Text + LocalFunctions;
|
---|
191 | Text := Text + 'var' + LineBreak;
|
---|
192 | Text := Text + ' OldPosition: TPosition;' + LineEnding;
|
---|
193 | Text := Text + 'begin' + LineEnding;
|
---|
194 | //Text := Text + ' WriteLn(''Rule check: ' + Rule.Name + ''');';
|
---|
195 | Text := Text + ' Result := True;' + LineEnding;
|
---|
196 | Text := Text + FunctionBody;
|
---|
197 | Text := Text + ' if Result then WriteLn(''Rule: ' + Rule.Name + ''');';
|
---|
198 | Text := Text + 'end;' + LineEnding + LineEnding;
|
---|
199 | end;
|
---|
200 | Add('');
|
---|
201 | Add('end.');
|
---|
202 | SaveToFile(FileName);
|
---|
203 | end;
|
---|
204 | FreeAndNil(ParserFile);
|
---|
205 | end;
|
---|
206 |
|
---|
207 | function TBuilder.BuildParserItems(Items: TRuleItems; Required: Boolean; IndentLevel: Integer): string;
|
---|
208 | var
|
---|
209 | I: Integer;
|
---|
210 | Item: TRuleItem;
|
---|
211 | ItemRequired: Boolean;
|
---|
212 | Line: string;
|
---|
213 | begin
|
---|
214 | Result := Indent(IndentLevel) + 'OldPosition := Position;' + LineEnding;
|
---|
215 | I := 0;
|
---|
216 | for Item in Items do begin
|
---|
217 | ItemRequired := not Item.Optional and Required;
|
---|
218 | Line := '';
|
---|
219 | case Items.RuleType of
|
---|
220 | rtOr: begin
|
---|
221 | Line := Line + Indent(IndentLevel);
|
---|
222 | if I > 0 then Line := Line + 'else ';
|
---|
223 | Line := Line + 'if ' + GetItemString(Item, False, IndentLevel) +
|
---|
224 | ' then Exit';
|
---|
225 | end;
|
---|
226 | rtAnd: begin
|
---|
227 | if not Item.Optional then
|
---|
228 | Line := Line + Indent(IndentLevel) + 'Result := Result and ';
|
---|
229 | if Item.Repetitive then begin
|
---|
230 | if not Item.Optional then
|
---|
231 | Line := Line + Indent(IndentLevel) + GetItemString(Item, ItemRequired, IndentLevel) + ';' + LineEnding;
|
---|
232 | Line := Line + Indent(IndentLevel) + 'repeat' + LineEnding;
|
---|
233 | Inc(IndentLevel);
|
---|
234 | Line := Line + Indent(IndentLevel) + 'if not ';
|
---|
235 | ItemRequired := False;
|
---|
236 | end else
|
---|
237 | if Item.Optional then Line := Line + Indent(IndentLevel);
|
---|
238 | Line := Line + GetItemString(Item, ItemRequired, IndentLevel);
|
---|
239 | if Item.Repetitive then begin
|
---|
240 | Dec(IndentLevel);
|
---|
241 | Line := Line + ' then Break;' + LineEnding +
|
---|
242 | Indent(IndentLevel) + 'until False';
|
---|
243 | end;
|
---|
244 | Line := Line + ';' + LineEnding +
|
---|
245 | Indent(IndentLevel) + 'if not Result then begin' + LineEnding +
|
---|
246 | Indent(IndentLevel + 1) + 'Position := OldPosition;' + LineEnding +
|
---|
247 | Indent(IndentLevel + 1) + 'Exit;' + LineEnding +
|
---|
248 | Indent(IndentLevel) + 'end;';
|
---|
249 |
|
---|
250 | // Check white spaces
|
---|
251 | if Assigned(Items.Grammer.WhiteSpaceRule) and Items.WithWhiteSpeaces
|
---|
252 | then begin
|
---|
253 | Line := Line + Indent(IndentLevel) + 'repeat' + LineEnding;
|
---|
254 | Inc(IndentLevel);
|
---|
255 | Line := Line + Indent(IndentLevel) + 'if not Parse' +
|
---|
256 | Items.Grammer.WhiteSpaceRule.Name + '(False)' +
|
---|
257 | ' then Break;' + LineEnding;
|
---|
258 | Dec(IndentLevel);
|
---|
259 | Line := Line + Indent(IndentLevel) + 'until False;' + LineEnding;
|
---|
260 | end;
|
---|
261 | end;
|
---|
262 | end;
|
---|
263 | Result := Result + Line + LineEnding;
|
---|
264 | Inc(I);
|
---|
265 | end;
|
---|
266 | case Items.RuleType of
|
---|
267 | rtOr: begin
|
---|
268 | Result := Result + Indent(IndentLevel) + 'else begin' + LineEnding;
|
---|
269 | Result := Result + Indent(IndentLevel) + ' if Required then Error(''Unexpected token'');' + LineEnding;
|
---|
270 | Result := Result + Indent(IndentLevel) + ' Result := False;' + LineEnding;
|
---|
271 | Result := Result + Indent(IndentLevel) + 'end;' + LineEnding;
|
---|
272 | end;
|
---|
273 | end;
|
---|
274 | end;
|
---|
275 |
|
---|
276 | procedure TBuilder.BuildMain(FileName: string);
|
---|
277 | var
|
---|
278 | ParserFile: TStringList;
|
---|
279 | begin
|
---|
280 | ParserFile := TStringList.Create;
|
---|
281 | with ParserFile do begin
|
---|
282 | Add('program Compiler;');
|
---|
283 | Add('');
|
---|
284 | Add('{$MODE Delphi}');
|
---|
285 | Add('');
|
---|
286 | Add('uses');
|
---|
287 | Add(' Source, Parser, Tokenizer, SysUtils;');
|
---|
288 | Add('');
|
---|
289 | Add('procedure Compile(FileName: string);');
|
---|
290 | Add('var');
|
---|
291 | Add(' SourceFile: file of Char;');
|
---|
292 | Add(' Parser: TParser;');
|
---|
293 | Add(' I: Integer;');
|
---|
294 | Add('begin');
|
---|
295 | Add(' AssignFile(SourceFile, FileName);');
|
---|
296 | Add(' Reset(SourceFile);');
|
---|
297 | Add(' Parser := TParser.Create;');
|
---|
298 | Add(' Parser.FileName := ExtractFileName(FileName);');
|
---|
299 | Add(' SetLength(Parser.Content, FileSize(SourceFile));');
|
---|
300 | Add(' I := 1;');
|
---|
301 | Add(' while not Eof(SourceFile) do begin');
|
---|
302 | Add(' Read(SourceFile, Parser.Content[I]);');
|
---|
303 | Add(' Inc(I);');
|
---|
304 | Add(' end;');
|
---|
305 | Add(' CloseFile(SourceFile);');
|
---|
306 | if Assigned(Grammer.TopRule) then
|
---|
307 | Add(' Parser.Parse' + Grammer.TopRule.Name + '(True);');
|
---|
308 | Add(' FreeAndNil(Parser);');
|
---|
309 | Add('end;');
|
---|
310 | Add('');
|
---|
311 | Add('begin');
|
---|
312 | Add(' if ParamCount > 0 then');
|
---|
313 | Add(' Compile(ParamStr(1))');
|
---|
314 | Add(' else WriteLn(''File name not specified as parameter.'');');
|
---|
315 | Add('end.');
|
---|
316 | SaveToFile(FileName);
|
---|
317 | end;
|
---|
318 | FreeAndNil(ParserFile);
|
---|
319 | end;
|
---|
320 |
|
---|
321 | procedure TBuilder.BuildSource(FileName: string);
|
---|
322 | var
|
---|
323 | Rule: TRule;
|
---|
324 | Item: TRuleItem;
|
---|
325 | SourceFile: TStringList;
|
---|
326 | TypeSectionStarted: Boolean;
|
---|
327 | I: Integer;
|
---|
328 | begin
|
---|
329 | SourceFile := TStringList.Create;
|
---|
330 | with SourceFile do begin
|
---|
331 | Add('unit Source;');
|
---|
332 | Add('');
|
---|
333 | Add('{$MODE Delphi}');
|
---|
334 | Add('');
|
---|
335 | Add('interface');
|
---|
336 | Add('');
|
---|
337 | Add('uses');
|
---|
338 | Add(' fgl;');
|
---|
339 | Add('');
|
---|
340 | TypeSectionStarted := False;
|
---|
341 | for Rule in Grammer.Rules do
|
---|
342 | //if Rule.CreateSourceNode then
|
---|
343 | begin
|
---|
344 | if not TypeSectionStarted then begin
|
---|
345 | Add('type');
|
---|
346 | TypeSectionStarted := True;
|
---|
347 | end;
|
---|
348 | Add(' T' + Rule.Name + ' = class;');
|
---|
349 | end;
|
---|
350 | Add('');
|
---|
351 | for Rule in Grammer.Rules do
|
---|
352 | //if Rule.CreateSourceNode then
|
---|
353 | begin
|
---|
354 | Add(' T' + Rule.Name + ' = class');
|
---|
355 | I := 1;
|
---|
356 | for Item in Rule.Items do begin
|
---|
357 | if Item.RuleItemType = ritNonTerminal then
|
---|
358 | if Item.Repetitive then
|
---|
359 | Add(' ' + Item.NonTerminal.Name + IntToStr(I) + ': TFPGObjectList<T' + Item.NonTerminal.Name + '>;')
|
---|
360 | else Add(' ' + Item.NonTerminal.Name + IntToStr(I) + ': T' + Item.NonTerminal.Name + ';');
|
---|
361 | Inc(I);
|
---|
362 | end;
|
---|
363 | Add(' end;' + LineEnding);
|
---|
364 | end;
|
---|
365 | Add('');
|
---|
366 | Add('implementation');
|
---|
367 | Add('');
|
---|
368 |
|
---|
369 | Add('end.');
|
---|
370 |
|
---|
371 | SaveToFile(FileName);
|
---|
372 | end;
|
---|
373 | FreeAndNil(SourceFile);
|
---|
374 | end;
|
---|
375 |
|
---|
376 | function TBuilder.BuildTokenizerItems(SourceFile: TStrings; Items: TRuleItems): string;
|
---|
377 | var
|
---|
378 | Item: TRuleItem;
|
---|
379 | Line: string;
|
---|
380 | begin
|
---|
381 | Result := '';
|
---|
382 | Line := '';
|
---|
383 | with SourceFile do begin
|
---|
384 | for Item in Items do begin
|
---|
385 | case Item.RuleItemType of
|
---|
386 | ritTerminal: Line := Line + '(Value = ''' + StringText(Item.Terminal, Item.EscapedStrings) + ''')';
|
---|
387 | ritNonTerminal: Line := Line + 'Is' + Item.NonTerminalName + '(Value)';
|
---|
388 | ritTerminalRange: Line := Line + '((Value > ''' + StringText(Item.TerminalFrom, Item.EscapedStrings) + ''') and (Value < ''' + StringText(Item.TerminalTo, Item.EscapedStrings) + '''))';
|
---|
389 | ritSubItems: Line := Line + '(' + BuildTokenizerItems(SourceFile, Item.SubItems) + ')';
|
---|
390 | end;
|
---|
391 | if Item <> Items[Items.Count - 1] then
|
---|
392 | Line := Line + ' ' + RuleTypeText[Items.RuleType] + ' ';
|
---|
393 | if Length(Line) > 80 then begin
|
---|
394 | Result := Result + Line + LineEnding;
|
---|
395 | Line := '';
|
---|
396 | end;
|
---|
397 | end;
|
---|
398 | Result := Result + Line;
|
---|
399 | end;
|
---|
400 | end;
|
---|
401 |
|
---|
402 | procedure TBuilder.BuildTokenizer(FileName: string);
|
---|
403 | var
|
---|
404 | Rule: TRule;
|
---|
405 | SourceFile: TStringList;
|
---|
406 | begin
|
---|
407 | SourceFile := TStringList.Create;
|
---|
408 | with SourceFile do begin
|
---|
409 | Add('unit Tokenizer;');
|
---|
410 | Add('');
|
---|
411 | Add('{$MODE Delphi}');
|
---|
412 | Add('');
|
---|
413 | Add('interface');
|
---|
414 | Add('');
|
---|
415 | Add('uses');
|
---|
416 | Add(' fgl;');
|
---|
417 | Add('');
|
---|
418 | Add('type');
|
---|
419 | Add(' TTokenizer = class');
|
---|
420 | Add(' function ReadNext: string;');
|
---|
421 | Add(' function Expect(Text: string): Boolean;');
|
---|
422 | for Rule in Grammer.Rules do
|
---|
423 | if (Rule.Level = rlTokenizer) then begin
|
---|
424 | Add(' function Is' + Rule.Name + '(Value: Char): Boolean;');
|
---|
425 | end;
|
---|
426 | Add(' end;');
|
---|
427 | Add('');
|
---|
428 | Add('implementation');
|
---|
429 | Add('');
|
---|
430 | Add('function TTokenizer.ReadNext: string;');
|
---|
431 | Add('begin');
|
---|
432 | Add('end;');
|
---|
433 | Add('');
|
---|
434 | Add('function TTokenizer.Expect(Text: string): Boolean;');
|
---|
435 | Add('begin');
|
---|
436 | Add('end;');
|
---|
437 |
|
---|
438 |
|
---|
439 | for Rule in Grammer.Rules do
|
---|
440 | if Rule.Level = rlTokenizer then begin
|
---|
441 | Add('function TTokenizer.Is' + Rule.Name + '(Value: Char): Boolean;');
|
---|
442 | Add('begin');
|
---|
443 | Add(' Result := ' + BuildTokenizerItems(SourceFile, Rule.Items) + ';');
|
---|
444 | Add('end;' + LineEnding);
|
---|
445 | end;
|
---|
446 | Add('end.');
|
---|
447 |
|
---|
448 | SaveToFile(FileName);
|
---|
449 | end;
|
---|
450 | FreeAndNil(SourceFile);
|
---|
451 | end;
|
---|
452 |
|
---|
453 | procedure TBuilder.BuildCompiler;
|
---|
454 | var
|
---|
455 | OutputDir: string;
|
---|
456 | begin
|
---|
457 | OutputDir := 'Generated';
|
---|
458 | ForceDirectories(OutputDir);
|
---|
459 |
|
---|
460 | BuildMain(OutputDir + DirectorySeparator + 'Compiler.pas');
|
---|
461 | BuildSource(OutputDir + DirectorySeparator + 'Source.pas');
|
---|
462 | BuildParser(OutputDir + DirectorySeparator + 'Parser.pas');
|
---|
463 | BuildTokenizer(OutputDir + DirectorySeparator + 'Tokenizer.pas');
|
---|
464 | end;
|
---|
465 |
|
---|
466 |
|
---|
467 | end.
|
---|
468 |
|
---|