mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-05 22:58:12 +02:00
216 lines
7.5 KiB
ObjectPascal
216 lines
7.5 KiB
ObjectPascal
{-------------------------------------------------------------------------------
|
|
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.
|
|
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$
|
|
|
|
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
|
|
SysUtils, SynEditTypes, 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;
|
|
Identifiers: TSynIdentChars; AKeywordProc: TEnumerateKeywordEvent);
|
|
|
|
implementation
|
|
|
|
procedure EnumerateKeywords(AKind: integer; KeywordList: string;
|
|
Identifiers: TSynIdentChars; AKeywordProc: TEnumerateKeywordEvent);
|
|
var
|
|
pStart, pEnd: PChar;
|
|
Keyword: string;
|
|
begin
|
|
if Assigned(AKeywordProc) and (KeywordList <> '') then begin
|
|
pEnd := PChar(KeywordList);
|
|
pStart := pEnd;
|
|
repeat
|
|
// skip over chars that are not in Identifiers
|
|
while (pStart^ <> #0) and not (pStart^ in Identifiers) do
|
|
Inc(pStart);
|
|
if pStart^ = #0 then break;
|
|
// find the last char that is in Identifiers
|
|
pEnd := pStart + 1;
|
|
while (pEnd^ <> #0) and (pEnd^ in Identifiers) 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 CompareText(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 := TSynHashEntry(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.
|
|
|