| 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.
|
|---|