source: branches/Analyzátor gramatiky/UGrammer.pas

Last change on this file was 32, checked in by george, 15 years ago
  • Průběžné uložení.
File size: 10.5 KB
Line 
1unit UGrammer;
2
3{$MODE Delphi}
4
5interface
6
7uses
8 Classes, ComCtrls, SysUtils, fgl, UParser;
9
10type
11 TGrammerRule = class;
12
13 TPathItem = class
14 public
15 Rule: TGrammerRule;
16 ItemIndex: Integer;
17 Affected: Boolean;
18 CharIndex: Integer;
19 procedure Assign(Source: TPathItem);
20 end;
21
22 TPathItemList = specialize TFPGObjectList<TPathItem>;
23
24 TGrammerPath = class
25 Items: TPathItemList;
26 procedure Assign(Source: TGrammerPath);
27 procedure Next;
28 constructor Create;
29 destructor Destroy; override;
30 end;
31
32 TPossibleCharacter = class
33 Character: Char;
34 RulePath: TGrammerPath;
35 procedure Assign(Source: TPossibleCharacter);
36 constructor Create;
37 destructor Destroy; override;
38 end;
39
40 TPossibleCharacterList = specialize TFPGObjectList<TPossibleCharacter>;
41
42 TPossibleCharacters = class
43 Items: TPossibleCharacterList;
44 procedure Assign(Source: TPossibleCharacters);
45 constructor Create;
46 destructor Destroy; override;
47 end;
48
49 TRuleType = (rtSequence, rtAlternative);
50 TRuleItemType = (itTerminal, itNonterminal);
51
52 TGrammerItem = class
53 private
54 Processed: Boolean;
55 Parent: TGrammerRule;
56 public
57 ItemType: TRuleItemType;
58 Text: string;
59 Rule: TGrammerRule;
60 RuleName: string;
61 Optional: Boolean;
62 Repetition: Boolean;
63// procedure GetPossibleCharacters(Path: TGrammerPath; var Characters: TPossibleCharacters);
64 constructor Create;
65 end;
66
67 TGrammerItemList = specialize TFPGObjectList<TGrammerItem>;
68
69 { TGrammerRule }
70
71 TGrammerRule = class
72 private
73 public
74 Token: Boolean;
75 Parent: TGrammerRule;
76 Name: string;
77 RuleType: TRuleType;
78 Items: TGrammerItemList;
79 procedure ClearProcessed;
80 function Add: TGrammerItem;
81 procedure AddTerminal(AText: string; AOptional, ARepetition: Boolean);
82 procedure AddTerminalText(Text: string);
83 procedure AddRule(ARule: TGrammerRule; AOptional, ARepetition: Boolean);
84 procedure ProcessCharacter(Character: Char);
85// procedure GetPossibleCharacters(Path: TGrammerPath;
86// var Characters: TPossibleCharacters; UseIndex: Integer = 0; UseCharIndex: Integer = -1);
87 function Check(Path: TGrammerPath; Token: string;
88 UseIndex: Integer = 0; UseCharIndex: Integer = -1): Boolean;
89 constructor Create;
90 destructor Destroy; override;
91 end;
92
93 TGrammerRuleList = specialize TFPGObjectList<TGrammerRule>;
94
95 TGrammer = class
96 public
97 Rules: TGrammerRuleList;
98 TopRule: TGrammerRule;
99 constructor Create;
100 procedure ClearProcessed;
101 procedure CorrectRuleLinks;
102 destructor Destroy; override;
103 end;
104
105
106implementation
107
108{ TGrammerRule }
109
110function TGrammerRule.Add: TGrammerItem;
111begin
112 Result := TGrammerItem.Create;
113 Items.Add(Result);
114 Result.Parent := Self;
115end;
116
117procedure TGrammerRule.AddRule(ARule: TGrammerRule; AOptional,
118 ARepetition: Boolean);
119begin
120 with Add do begin
121 ItemType := itNonterminal;
122 Rule := ARule;
123 Optional := AOptional;
124 Repetition := ARepetition;
125 Parent := Self;
126 end;
127end;
128
129procedure TGrammerRule.AddTerminal(AText: string; AOptional, ARepetition: Boolean);
130begin
131 with Add do begin
132 ItemType := itTerminal;
133 Text := AText;
134 Optional := AOptional;
135 Repetition := ARepetition;
136 Parent := Self;
137 end;
138end;
139
140procedure TGrammerRule.AddTerminalText(Text: string);
141var
142 I: Integer;
143begin
144 for I := 1 to Length(Text) do
145 AddTerminal(Text[I], False, False);
146end;
147
148procedure TGrammerRule.ClearProcessed;
149var
150 I: Integer;
151begin
152 for I := 0 to Items.Count - 1 do
153 Items[I].Processed := False;
154end;
155
156constructor TGrammerRule.Create;
157begin
158 Parent := nil;
159 Items := TGrammerItemList.Create;
160end;
161
162destructor TGrammerRule.Destroy;
163begin
164 Items.Destroy;
165 inherited;
166end;
167
168(*
169procedure TGrammerRule.GetPossibleCharacters(Path: TGrammerPath;
170 var Characters: TPossibleCharacters; UseIndex: Integer = 0; UseCharIndex: Integer = -1);
171var
172 I: Integer;
173 NextItemIndex, NextCharIndex: Integer;
174 NextRule: TGrammerRule;
175 TempPath: TGrammerPath;
176begin
177 TempPath := TGrammerPath.Create;
178 with Path.Items[Path.Items.Add(TPathItem.Create)] do begin
179 Rule := Self;
180 ItemIndex := UseIndex;
181 CharIndex := UseCharIndex;
182 Affected := True;
183 end;
184
185 case RuleType of
186 rtAlternative: begin
187 if UseIndex > 0 then begin
188 // Forward generation to upper item
189 Path.Items.Delete(Path.Items.Count - 1);
190 with Path.Items[Path.Items.Count - 1] do begin
191 NextItemIndex := ItemIndex;
192 NextCharIndex := CharIndex;
193 NextRule := Rule;
194 end;
195 Path.Items.Delete(Path.Items.Count - 1);
196 NextRule.GetPossibleCharacters(Path, Characters, NextItemIndex + 1, NextCharIndex);
197 end else begin
198 // Generate alternatives
199 for I := 0 to Items.Count - 1 do begin
200 Path.Items[Path.Items.Count - 1].ItemIndex := I;
201 //Inc(Path.Items[High(Path.Items)].CharIndex);
202 Items[I].GetPossibleCharacters(Path, Characters);
203 end;
204 end;
205 end;
206 rtSequence: begin
207 TempPath.Assign(Path);
208 if UseIndex >= Items.Count then begin
209 // Forward generation to upper item
210 Path.Items.Delete(Path.Items.Count - 1);
211 with Path.Items[Path.Items.Count - 1] do begin
212 NextItemIndex := ItemIndex;
213 NextCharIndex := CharIndex;
214 NextRule := Rule;
215 end;
216 Path.Items.Delete(Path.Items.Count - 1);
217 NextRule.GetPossibleCharacters(Path, Characters, NextItemIndex + 1, NextCharIndex);
218 end else begin
219 Path.Items[Path.Items.Count - 1].ItemIndex := UseIndex;
220 Items[UseIndex].GetPossibleCharacters(Path, Characters);
221 end;
222 // Check repetition
223 if (UseIndex > 0) and not Items[UseIndex - 1].Processed then
224 if Items[UseIndex - 1].Repetition then begin
225 TempPath.Items[TempPath.Items.Count - 1].ItemIndex := UseIndex - 1;
226 Items[UseIndex - 1].GetPossibleCharacters(TempPath, Characters);
227 end;
228 end;
229 end;
230 TempPath.Destroy;
231end;
232*)
233
234procedure TGrammerRule.ProcessCharacter(Character: Char);
235begin
236end;
237
238function TGrammerRule.Check(Path: TGrammerPath; Token: string;
239 UseIndex: Integer; UseCharIndex: Integer): Boolean;
240begin
241
242end;
243
244{ TGrammer }
245
246procedure TGrammer.ClearProcessed;
247var
248 I: Integer;
249begin
250 for I := 0 to Rules.Count - 1 do
251 Rules[I].ClearProcessed;
252end;
253
254procedure TGrammer.CorrectRuleLinks;
255var
256 I: Integer;
257 II: Integer;
258 J: Integer;
259begin
260 for I := 0 to Rules.Count - 1 do with Rules[I] do begin
261 for II := 0 to Items.Count - 1 do with Items[II] do begin
262 if (ItemType = itNonterminal) and (not Assigned(Rule)) then begin
263 J := 0;
264 while (J < Rules.Count) and (Rules[J].Name <> RuleName) do Inc(J);
265 if J < Rules.Count then Rule := Rules[J] else
266 raise Exception.Create('Rule link correction failed on rule ' +
267 IntToStr(I) + ' item ' + IntToStr(II));
268 end;
269 end;
270 end;
271end;
272
273constructor TGrammer.Create;
274begin
275 Rules := TGrammerRuleList.Create;
276end;
277
278destructor TGrammer.Destroy;
279begin
280 Rules.Destroy;
281 inherited;
282end;
283
284{ TGrammerItem }
285
286constructor TGrammerItem.Create;
287begin
288 Rule := nil;
289end;
290
291(*
292procedure TGrammerItem.GetPossibleCharacters(Path: TGrammerPath;
293 var Characters: TPossibleCharacters);
294var
295 Found: Boolean;
296 NextItemIndex, NextCharIndex: Integer;
297 NextRule: TGrammerRule;
298begin
299 Processed := True;
300 case ItemType of
301 itTerminal: begin
302 Characters.Items.Add(TPossibleCharacter.Create);
303 Characters.Items[Characters.Items.Count - 1].Character := Character;
304 Characters.Items[Characters.Items.Count - 1].RulePath.Assign(Path);
305 with Characters.Items[Characters.Items.Count - 1].RulePath do begin
306 Inc(Items[Items.Count - 1].ItemIndex);
307 end;
308 end;
309 itNonterminal: begin
310 Rule.GetPossibleCharacters(Path, Characters);
311 end;
312 end;
313 if Optional then begin
314 // Forward generation to upper item
315 //SetLength(Path.Items, Length(Path.Items) - 1);
316 with Path.Items[Path.Items.Count - 1] do begin
317 NextItemIndex := ItemIndex;
318 NextCharIndex := CharIndex;
319 NextRule := Rule;
320 end;
321 Path.Items.Delete(Path.Items.Count - 1);
322 NextRule.GetPossibleCharacters(Path, Characters, NextItemIndex + 1, NextCharIndex);
323 end;
324end;
325*)
326
327{ TGrammerPath }
328
329procedure TGrammerPath.Assign(Source: TGrammerPath);
330var
331 I: Integer;
332begin
333 for I := 0 to Items.Count - 1 do
334 Items[I].Destroy;
335 Items.Count := Source.Items.Count;
336 for I := 0 to Items.Count - 1 do begin
337 Items[I] := TPathItem.Create;
338 Items[I].Assign(Source.Items[I]);
339 end;
340end;
341
342procedure TGrammerPath.Next;
343var
344 Index: Integer;
345 Success: Boolean;
346begin
347 Success := False;
348 Index := Items.Count - 1;
349 while not Success and (Index >= 0) do begin
350 with Items[Index] do if Rule.Items[ItemIndex].Repetition then begin
351 Success := True;
352 //Inc(CharIndex);
353 end else begin
354 if ((ItemIndex + 1) < Rule.Items.Count) and (Rule.RuleType = rtSequence) then begin
355 Inc(ItemIndex);
356 //Inc(CharIndex);
357 Success := True;
358 end else Dec(Index);
359 end;
360 end;
361 Items.Count := Index + 1;
362end;
363
364constructor TGrammerPath.Create;
365begin
366 Items := TPathItemList.Create;
367end;
368
369destructor TGrammerPath.Destroy;
370begin
371 Items.Destroy;
372 inherited Destroy;
373end;
374
375{ TPathItem }
376
377procedure TPathItem.Assign(Source: TPathItem);
378begin
379 Rule := Source.Rule;
380 ItemIndex := Source.ItemIndex;
381 CharIndex := Source.CharIndex;
382 Affected := Source.Affected;
383end;
384
385{ TPossibleCharacter }
386
387procedure TPossibleCharacter.Assign(Source: TPossibleCharacter);
388begin
389 Character := Source.Character;
390 RulePath.Assign(Source.RulePath);
391end;
392
393constructor TPossibleCharacter.Create;
394begin
395 RulePath := TGrammerPath.Create;
396end;
397
398destructor TPossibleCharacter.Destroy;
399begin
400 RulePath.Destroy;
401 inherited Destroy;
402end;
403
404{ TPossibleCharacters }
405
406procedure TPossibleCharacters.Assign(Source: TPossibleCharacters);
407var
408 I: Integer;
409begin
410 Items.Count := Source.Items.Count;
411 for I := 0 to Items.Count - 1 do
412 Items[I].Assign(Source.Items[I]);
413end;
414
415constructor TPossibleCharacters.Create;
416begin
417 Items := TPossibleCharacterList.Create;
418end;
419
420destructor TPossibleCharacters.Destroy;
421begin
422 Items.Destroy;
423 inherited Destroy;
424end;
425
426end.
Note: See TracBrowser for help on using the repository browser.