1 | unit UProgram;
|
---|
2 |
|
---|
3 | {$MODE Delphi}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses
|
---|
8 | Classes, ComCtrls, SysUtils, UGrammer, fgl;
|
---|
9 |
|
---|
10 | type
|
---|
11 | TProgramItem = class;
|
---|
12 |
|
---|
13 | TProgramItemList = specialize TFPGObjectList<TProgramItem>;
|
---|
14 |
|
---|
15 | TProgramItem = class
|
---|
16 | public
|
---|
17 | RuleBefore: TGrammerRule;
|
---|
18 | Items: TProgramItemList;
|
---|
19 | ItemType: TRuleItemType;
|
---|
20 | Rule: TGrammerRule;
|
---|
21 | Value: string;
|
---|
22 | procedure Delete;
|
---|
23 | procedure DeleteItem(Index: Integer);
|
---|
24 | procedure DeleteNonterminal(ARule: TGrammerRule);
|
---|
25 | procedure DeleteEmpty;
|
---|
26 | procedure MergeNonterminal(ARule: TGrammerRule);
|
---|
27 | procedure Join(ARule: TGrammerRule; ItemIndex: Integer);
|
---|
28 | function MergeToTerminal: string;
|
---|
29 | constructor Create;
|
---|
30 | destructor Destroy; override;
|
---|
31 | procedure Assign(Source: TProgramItem);
|
---|
32 | end;
|
---|
33 |
|
---|
34 | TProgram = class
|
---|
35 | public
|
---|
36 | TopItem: TProgramItem;
|
---|
37 | constructor Create;
|
---|
38 | procedure Insert(Path: TGrammerPath; Character: Char);
|
---|
39 | procedure Parse(Grammer: TGrammer; Tokens: TStringList);
|
---|
40 | destructor Destroy; override;
|
---|
41 | end;
|
---|
42 |
|
---|
43 | implementation
|
---|
44 |
|
---|
45 | { TProgram }
|
---|
46 |
|
---|
47 | constructor TProgram.Create;
|
---|
48 | begin
|
---|
49 | TopItem := TProgramItem.Create;
|
---|
50 | end;
|
---|
51 |
|
---|
52 | destructor TProgram.Destroy;
|
---|
53 | begin
|
---|
54 | TopItem.Free;
|
---|
55 | inherited;
|
---|
56 | end;
|
---|
57 |
|
---|
58 | procedure TProgram.Insert(Path: TGrammerPath; Character: Char);
|
---|
59 | var
|
---|
60 | I: Integer;
|
---|
61 | SelectedProgramItem: TProgramItem;
|
---|
62 | begin
|
---|
63 | SelectedProgramItem := TopItem;
|
---|
64 | for I := 0 to Path.Items.Count - 1 do
|
---|
65 | with Path.Items[I] do begin
|
---|
66 | SelectedProgramItem.ItemType := itNonterminal;
|
---|
67 | if not Assigned(SelectedProgramItem.Rule) then SelectedProgramItem.Rule := Rule;
|
---|
68 | if SelectedProgramItem.Rule = Rule then begin
|
---|
69 | // if (Rule.RuleType = rtSequence) or (SelectedProgramItem.Rule = SelectedProgramItem.RuleBefore) then begin
|
---|
70 | if SelectedProgramItem.Items.Count < (CharIndex + 1) then
|
---|
71 | SelectedProgramItem.Items.Count := CharIndex + 1;
|
---|
72 | if not Assigned(SelectedProgramItem.Items[CharIndex]) then
|
---|
73 | SelectedProgramItem.Items[CharIndex] := TProgramItem.Create;
|
---|
74 | SelectedProgramItem := SelectedProgramItem.Items[CharIndex];
|
---|
75 | (* end else begin
|
---|
76 | SelectedProgramItem.Items.Count := SelectedProgramItem.Items.Count + 1;
|
---|
77 | if not Assigned(SelectedProgramItem.Items[SelectedProgramItem.Items.Count - 1]) then
|
---|
78 | SelectedProgramItem.Items[SelectedProgramItem.Items.Count - 1] := TProgramItem.Create;
|
---|
79 | SelectedProgramItem := TProgramItem(SelectedProgramItem.Items[SelectedProgramItem.Items.Count - 1]);
|
---|
80 | end;
|
---|
81 | *)
|
---|
82 | end;
|
---|
83 | end;
|
---|
84 | with SelectedProgramItem do begin
|
---|
85 | ItemType := itTerminal;
|
---|
86 | Value := Character;
|
---|
87 | end;
|
---|
88 | end;
|
---|
89 |
|
---|
90 | procedure TProgram.Parse(Grammer: TGrammer; Tokens: TStringList);
|
---|
91 | var
|
---|
92 | Path: TGrammerPath;
|
---|
93 | I, II: Integer;
|
---|
94 | UseIndex: Integer;
|
---|
95 | UseCharIndex: Integer;
|
---|
96 | UseRule: TGrammerRule;
|
---|
97 | Level: array of Integer;
|
---|
98 | begin
|
---|
99 | Path := TGrammerPath.Create;
|
---|
100 | with Path.Items[Path.Items.Add(TPathItem.Create)] do begin
|
---|
101 | Rule := Grammer.TopRule;
|
---|
102 | ItemIndex := 0;
|
---|
103 | CharIndex := -1;
|
---|
104 | end;
|
---|
105 |
|
---|
106 | for I := 0 to Tokens.Count - 1 do begin
|
---|
107 | UseIndex := Path.Items[Path.Items.Count - 1].ItemIndex;
|
---|
108 | UseCharIndex := Path.Items[Path.Items.Count - 1].CharIndex;
|
---|
109 | UseRule := Path.Items[Path.Items.Count - 1].Rule;
|
---|
110 | Path.Items.Delete(Path.Items.Count - 1);
|
---|
111 | Grammer.ClearProcessed;
|
---|
112 | if UseRule.Check(Path, Tokens[I], UseIndex, UseCharIndex) then
|
---|
113 | begin
|
---|
114 |
|
---|
115 | end else begin
|
---|
116 | //raise Exception.Create('Parse error. Expected "' + Tokens[I] + '" but found "' + Text[I] + '".');
|
---|
117 | //MainForm.StatusBar1.SimpleText := 'Parse error. Expected "' + ExpectedCharacters + '" but found "' + Text[I] + '".';
|
---|
118 | break;
|
---|
119 | end;
|
---|
120 | end;
|
---|
121 | Path.Destroy;
|
---|
122 | end;
|
---|
123 |
|
---|
124 | procedure TProgramItem.MergeNonterminal(ARule: TGrammerRule);
|
---|
125 | var
|
---|
126 | I: Integer;
|
---|
127 | begin
|
---|
128 | for I := 0 to Items.Count - 1 do
|
---|
129 | with Items[I] do begin
|
---|
130 | if ItemType = itNonterminal then begin
|
---|
131 | if Rule.Name = ARule.Name then begin
|
---|
132 | ItemType := itTerminal;
|
---|
133 | Value := MergeToTerminal;
|
---|
134 | end else MergeNonterminal(ARule);
|
---|
135 | end;
|
---|
136 | end;
|
---|
137 | end;
|
---|
138 |
|
---|
139 | { TProgramItem }
|
---|
140 |
|
---|
141 | procedure TProgramItem.Assign(Source: TProgramItem);
|
---|
142 | begin
|
---|
143 |
|
---|
144 | end;
|
---|
145 |
|
---|
146 | constructor TProgramItem.Create;
|
---|
147 | begin
|
---|
148 | Items := TProgramItemList.Create;
|
---|
149 | end;
|
---|
150 |
|
---|
151 | procedure TProgramItem.Delete;
|
---|
152 | var
|
---|
153 | I: Integer;
|
---|
154 | begin
|
---|
155 | for I := 0 to Items.Count - 1 do
|
---|
156 | with Items[I] do begin
|
---|
157 | if ItemType = itNonterminal then Delete;
|
---|
158 | end;
|
---|
159 | end;
|
---|
160 |
|
---|
161 | procedure TProgramItem.DeleteEmpty;
|
---|
162 | var
|
---|
163 | I: Integer;
|
---|
164 | begin
|
---|
165 | I := 0;
|
---|
166 | while I < Items.Count do
|
---|
167 | with Items[I] do begin
|
---|
168 | if ItemType = itNonterminal then begin
|
---|
169 | if Items.Count = 0 then begin
|
---|
170 | Self.DeleteItem(I);
|
---|
171 | end else begin
|
---|
172 | DeleteEmpty;
|
---|
173 | Inc(I);
|
---|
174 | end;
|
---|
175 | end else Inc(I);
|
---|
176 | end;
|
---|
177 | end;
|
---|
178 |
|
---|
179 | procedure TProgramItem.DeleteItem(Index: Integer);
|
---|
180 | begin
|
---|
181 | if Items[Index].ItemType = itNonterminal then
|
---|
182 | Items[Index].Delete;
|
---|
183 | Items.Delete(Index);
|
---|
184 | end;
|
---|
185 |
|
---|
186 | procedure TProgramItem.DeleteNonterminal(ARule: TGrammerRule);
|
---|
187 | var
|
---|
188 | I: Integer;
|
---|
189 | begin
|
---|
190 | I := 0;
|
---|
191 | while I < Items.Count do
|
---|
192 | with Items[I] do begin
|
---|
193 | if ItemType = itNonterminal then begin
|
---|
194 | if Rule.Name = ARule.Name then begin
|
---|
195 | Self.DeleteItem(I);
|
---|
196 | end else begin
|
---|
197 | DeleteNonterminal(ARule);
|
---|
198 | Inc(I);
|
---|
199 | end;
|
---|
200 | end else Inc(I);
|
---|
201 | end;
|
---|
202 | end;
|
---|
203 |
|
---|
204 | destructor TProgramItem.Destroy;
|
---|
205 | begin
|
---|
206 | Items.Destroy;
|
---|
207 | inherited;
|
---|
208 | end;
|
---|
209 |
|
---|
210 | procedure TProgramItem.Join(ARule: TGrammerRule; ItemIndex: Integer);
|
---|
211 | var
|
---|
212 | SubProgramItem: TProgramItem;
|
---|
213 | I: Integer;
|
---|
214 | begin
|
---|
215 | if (ItemType = itNonterminal) and (Rule = ARule) then begin
|
---|
216 | SubProgramItem := Items[ItemIndex];
|
---|
217 | RuleBefore := SubProgramItem.RuleBefore;
|
---|
218 | Rule := SubProgramItem.Rule;
|
---|
219 | ItemType := SubProgramItem.ItemType;
|
---|
220 | Value := SubProgramItem.Value;
|
---|
221 | Items[ItemIndex] := nil;
|
---|
222 | for I := 0 to Items.Count - 1 do
|
---|
223 | if Assigned(Items[I]) then Items[I].Free;
|
---|
224 | Items := SubProgramItem.Items;
|
---|
225 | end;
|
---|
226 | for I := 0 to Items.Count - 1 do
|
---|
227 | Items[I].Join(ARule, ItemIndex);
|
---|
228 | end;
|
---|
229 |
|
---|
230 | function TProgramItem.MergeToTerminal: string;
|
---|
231 | var
|
---|
232 | I: Integer;
|
---|
233 | begin
|
---|
234 | Result := '';
|
---|
235 | for I := 0 to Items.Count - 1 do
|
---|
236 | with Items[I] do begin
|
---|
237 | if ItemType = itTerminal then Result := Result + Value
|
---|
238 | else Result := Result + MergeToTerminal;
|
---|
239 | end;
|
---|
240 | end;
|
---|
241 |
|
---|
242 | end.
|
---|