Menu

[327ada]: / Source / VCL / SynEdit / Source / SynHighlighterHashEntries.pas  Maximize  Restore  History

Download this file

226 lines (195 with data), 8.0 kB

  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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
{-------------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: SynHighlighterHashEntries.pas, released 2000-04-21.
The Initial Author of this file is Michael Hieke.
Portions created by Michael Hieke are Copyright 2000 Michael Hieke.
Unicode translation by Maël Hörz.
All Rights Reserved.
Contributors to the SynEdit project are listed in the Contributors.txt file.
Alternatively, the contents of this file may be used under the terms of the
GNU General Public License Version 2 or later (the "GPL"), in which case
the provisions of the GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms
of the GPL and not to allow others to use your version of this file
under the MPL, indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by the GPL.
If you do not delete the provisions above, a recipient may use your version
of this file under either the MPL or the GPL.
$Id: SynHighlighterHashEntries.pas,v 1.5.2.3 2008/09/14 16:25:00 maelh Exp $
You may retrieve the latest version of this file at the SynEdit home page,
located at http://SynEdit.SourceForge.net
Known Issues:
-------------------------------------------------------------------------------}
{
@abstract(Support classes for SynEdit highlighters that create the keyword lists at runtime.)
@author(Michael Hieke)
@created(2000-04-21)
@lastmod(2001-09-07)
The classes in this unit can be used to use the hashing algorithm while still
having the ability to change the set of keywords.
}
unit SynHighlighterHashEntries;
{$I SynEdit.inc}
interface
uses
SynEditTypes,
SynUnicode,
Classes;
type
{ Class to hold the keyword to recognize, its length and its token kind. The
keywords that have the same hashvalue are stored in a single-linked list,
with the Next property pointing to the next entry. The entries are ordered
over the keyword length. }
TSynHashEntry = class(TObject)
protected
{ Points to the next keyword entry with the same hashvalue. }
fNext: TSynHashEntry;
{ Length of the keyword. }
fKeyLen: integer;
{ The keyword itself. }
fKeyword: string;
{ Keyword token kind, has to be typecasted to the real token kind type. }
fKind: integer;
public
{ Adds a keyword entry with the same hashvalue. Depending on the length of
the two keywords it might return Self and store NewEntry in the Next
pointer, or return NewEntry and make the Next property of NewEntry point
to Self. This way the order of keyword length is preserved. }
function AddEntry(NewEntry: TSynHashEntry): TSynHashEntry; virtual;
{ Creates a keyword entry for the given keyword and token kind. }
constructor Create(const AKey: string; AKind: integer);
{ Destroys the keyword entry and all other keyword entries Next points to. }
destructor Destroy; override;
public
{ The keyword itself. }
property Keyword: string read fKeyword;
{ Length of the keyword. }
property KeywordLen: integer read fKeyLen;
{ Keyword token kind, has to be typecasted to the real token kind type. }
property Kind: integer read fKind;
{ Points to the next keyword entry with the same hashvalue. }
property Next: TSynHashEntry read fNext;
end;
{ A list of keyword entries, stored as single-linked lists under the hashvalue
of the keyword. }
TSynHashEntryList = class(TList)
protected
{ Returns the first keyword entry for a given hashcalue, or nil. }
function Get(HashKey: Integer): TSynHashEntry;
{ Adds a keyword entry under its hashvalue. Will grow the list count when
necessary, so the maximum hashvalue should be limited outside. The correct
order of keyword entries is maintained. }
procedure Put(HashKey: Integer; Entry: TSynHashEntry);
public
{ Clears the list and frees all contained keyword entries. }
procedure Clear; override;
public
{ Type-safe access to the first keyword entry for a hashvalue. }
property Items[Index: integer]: TSynHashEntry read Get write Put; default;
end;
{ Procedural type for adding keyword entries to a TSynHashEntryList when
iterating over all the keywords contained in a string. }
TEnumerateKeywordEvent = procedure(AKeyword: string; AKind: integer)
of object;
{ This procedure will call AKeywordProc for all keywords in KeywordList. A
keyword is considered any number of successive chars that are contained in
Identifiers, with chars not contained in Identifiers before and after them. }
procedure EnumerateKeywords(AKind: integer; KeywordList: string;
IsIdentChar: TCategoryMethod; AKeywordProc: TEnumerateKeywordEvent);
implementation
uses
SysUtils;
procedure EnumerateKeywords(AKind: integer; KeywordList: string;
IsIdentChar: TCategoryMethod; AKeywordProc: TEnumerateKeywordEvent);
var
pStart, pEnd: PWideChar;
Keyword: string;
begin
if Assigned(AKeywordProc) and (KeywordList <> '') then
begin
pEnd := PWideChar(KeywordList);
pStart := pEnd;
repeat
// skip over chars that are not in Identifiers
while (pStart^ <> #0) and not IsIdentChar(pStart^) do
Inc(pStart);
if pStart^ = #0 then break;
// find the last char that is in Identifiers
pEnd := pStart + 1;
while (pEnd^ <> #0) and IsIdentChar(pEnd^) do
Inc(pEnd);
// call the AKeywordProc with the keyword
SetString(Keyword, pStart, pEnd - pStart);
AKeywordProc(Keyword, AKind);
Keyword := '';
// pEnd points to a char not in Identifiers, restart after that
pStart := pEnd + 1;
until (pStart^ = #0) or (pEnd^ = #0);
end;
end;
{ TSynHashEntry }
constructor TSynHashEntry.Create(const AKey: string; AKind: integer);
begin
inherited Create;
fKeyLen := Length(AKey);
fKeyword := AKey;
fKind := AKind;
end;
destructor TSynHashEntry.Destroy;
begin
fNext.Free;
inherited Destroy;
end;
function TSynHashEntry.AddEntry(NewEntry: TSynHashEntry): TSynHashEntry;
begin
Result := Self;
if Assigned(NewEntry) then
begin
if WideCompareText(NewEntry.Keyword, fKeyword) = 0 then
raise Exception.CreateFmt('Keyword "%s" already in list', [fKeyword]);
if NewEntry.fKeyLen < fKeyLen then
begin
NewEntry.fNext := Self;
Result := NewEntry;
end else if Assigned(fNext) then
fNext := fNext.AddEntry(NewEntry)
else
fNext := NewEntry;
end;
end;
{ TSynHashEntryList }
procedure TSynHashEntryList.Clear ;
var
i: integer;
begin
for i := 0 to Count - 1 do
TSynHashEntry(Items[i]).Free;
inherited Clear;
end;
function TSynHashEntryList.Get(HashKey: Integer): TSynHashEntry;
begin
if (HashKey >= 0) and (HashKey < Count) then
Result := inherited Items[HashKey]
else
Result := nil;
end;
procedure TSynHashEntryList.Put(HashKey: Integer; Entry: TSynHashEntry);
var
ListEntry: TSynHashEntry;
begin
if HashKey >= Count then
Count := HashKey + 1;
ListEntry := TSynHashEntry(inherited Items[HashKey]);
// if there is already a hashentry for this hashvalue let it decide
// where to put the new entry in its single linked list
if Assigned(ListEntry) then
Entry := ListEntry.AddEntry(Entry);
inherited Items[HashKey] := Entry;
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.