dexed/src/u_d2syn.pas

1248 lines
35 KiB
Plaintext

unit u_d2syn;
{$I u_defines.inc}
interface
uses
Classes, SysUtils, Graphics,
SynEditHighlighter, SynEditHighlighterFoldBase, SynEditTypes,
u_dlangutils, u_dlangmaps, u_common;
type
TTokenKind = (tkCommt, tkIdent, tkKeywd, tkStrng, tkBlank, tkSymbl, tkNumbr,
tkDDocs, tkSpecK, tkError, tkAsmbl, tkAttri, tkLost, tkTypes, tkCall);
TRangeKind = (rkString1, rkString2, rkBlockCom1, rkBlockCom2,
rkBlockDoc1, rkBlockDoc2, rkAsm, rkAttrib,
rkStringQParen, rkStringQSquare, rkStringQGe, rStringQCurly);
TRangeKinds = set of TRangeKind;
// defines the ranges which can be folded
TFoldKinds = set of (fkBrackets, fkComments1, fkComments2, fkStrings, fkRegion,
fkDDoc);
// internal class used to keep trace of the useful informations of the previous line
TSynD2SynRange = class(TSynCustomHighlighterRange)
private
namedRegionCount : Integer;
nestedCommentsCount : Integer;
nestedQParensStrings: Integer;
nestedQSquareStrings: Integer;
nestedQGeStrings : Integer;
nestedQCurlyStrings : Integer;
attribParenCount : Integer;
rangeKinds : TRangeKinds;
// double quoted multi-line string prefixed with 'r':
// => don't skip '"' following '\'
rString : boolean;
public
procedure Assign(source: TSynCustomHighlighterRange); override;
function Compare(range: TSynCustomHighlighterRange): integer; override;
procedure Clear; override;
//
procedure copyFrom(source: TSynD2SynRange);
function notInExclusiveRange(): boolean;
end;
TSynD2Syn = class (TSynCustomFoldHighlighter)
private
fWhiteAttrib: TSynHighlighterAttributes;
fNumbrAttrib: TSynHighlighterAttributes;
fSymblAttrib: TSynHighlighterAttributes;
fIdentAttrib: TSynHighlighterAttributes;
fCommtAttrib: TSynHighlighterAttributes;
fStrngAttrib: TSynHighlighterAttributes;
fKeywdAttrib: TSynHighlighterAttributes;
fDDocsAttrib: TSynHighlighterAttributes;
fAsblrAttrib: TSynHighlighterAttributes;
fSpeckAttrib: TSynHighlighterAttributes;
fErrorAttrib: TSynHighlighterAttributes;
fAttriAttrib: TSynHighlighterAttributes;
fLost_Attrib: TSynHighlighterAttributes;
fTypesAttrib: TSynHighlighterAttributes;
fFCallAttrib: TSynHighlighterAttributes;
fLineBuf: string;
fTokStart, fTokStop: Integer;
fTokKind: TTokenKind;
fCurrRange: TSynD2SynRange;
fFoldKinds: TFoldKinds;
fAttribLut: array[TTokenKind] of TSynHighlighterAttributes;
fPhobosStyleType: boolean;
procedure setFoldKinds(value: TFoldKinds);
procedure setWhiteAttrib(value: TSynHighlighterAttributes);
procedure setNumbrAttrib(value: TSynHighlighterAttributes);
procedure setSymblAttrib(value: TSynHighlighterAttributes);
procedure setIdentAttrib(value: TSynHighlighterAttributes);
procedure setCommtAttrib(value: TSynHighlighterAttributes);
procedure setStrngAttrib(value: TSynHighlighterAttributes);
procedure setKeywdAttrib(value: TSynHighlighterAttributes);
procedure setDDocsAttrib(value: TSynHighlighterAttributes);
procedure setAsblrAttrib(value: TSynHighlighterAttributes);
procedure setSpeckAttrib(value: TSynHighlighterAttributes);
procedure setErrorAttrib(value: TSynHighlighterAttributes);
procedure setAttriAttrib(value: TSynHighlighterAttributes);
procedure setTypesAttrib(value: TSynHighlighterAttributes);
procedure setFCallAttrib(value: TSynHighlighterAttributes);
procedure doAttribChange(sender: TObject);
procedure doChanged;
protected
function GetRangeClass: TSynCustomHighlighterRangeClass; override;
function GetIdentChars: TSynIdentChars; override;
published
property phobosStyleType: boolean read fPhobosStyleType write fPhobosStyleType stored true;
property foldKinds: TFoldKinds read fFoldKinds write setFoldKinds stored true;
property whites: TSynHighlighterAttributes read fWhiteAttrib write setWhiteAttrib stored true;
property numbers: TSynHighlighterAttributes read fNumbrAttrib write setNumbrAttrib stored true;
property symbols: TSynHighlighterAttributes read fSymblAttrib write setSymblAttrib stored true;
property identifiers: TSynHighlighterAttributes read fIdentAttrib write setIdentAttrib stored true;
property comments: TSynHighlighterAttributes read fCommtAttrib write setCommtAttrib stored true;
property strings: TSynHighlighterAttributes read fStrngAttrib write setStrngAttrib stored true;
property keywords: TSynHighlighterAttributes read fKeywdAttrib write setKeywdAttrib stored true;
property ddoc: TSynHighlighterAttributes read fDDocsAttrib write setDDocsAttrib stored true;
property inlineAsm: TSynHighlighterAttributes read fAsblrAttrib write setAsblrAttrib stored true;
property special: TSynHighlighterAttributes read fSpeckAttrib write setSpeckAttrib stored true;
property errors: TSynHighlighterAttributes read fErrorAttrib write setErrorAttrib stored true;
property attributes: TSynHighlighterAttributes read fAttriAttrib write setAttriAttrib stored true;
property types: TSynHighlighterAttributes read fTypesAttrib write setTypesAttrib stored true;
property calls: TSynHighlighterAttributes read fFCallAttrib write setFCallAttrib stored true;
property DefaultFilter stored false;
property enabled stored false;
public
constructor create(aOwner: TComponent); override;
destructor destroy; override;
procedure Assign(Source: TPersistent); override;
procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); override;
function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes; override;
procedure setLine(const NewValue: string; LineNumber: Integer); override;
procedure next; override;
function GetTokenAttribute: TSynHighlighterAttributes; override;
function GetToken: string; override;
function GetTokenKind: integer; override;
function GetTokenPos: Integer; override;
function GetEol: Boolean; override;
procedure SetRange(value: Pointer); override;
procedure ResetRange; override;
function GetRange: Pointer; override;
end;
implementation
procedure TSynD2SynRange.Assign(source: TSynCustomHighlighterRange);
var
rng: TSynD2SynRange;
begin
inherited;
if source is TSynD2SynRange then
begin
rng := TSynD2SynRange(source);
rangeKinds := rng.rangeKinds;
namedRegionCount := rng.namedRegionCount;
nestedQGeStrings:= rng.nestedQGeStrings;
nestedQParensStrings := rng.nestedQParensStrings;
nestedQSquareStrings := rng.nestedQSquareStrings;
nestedQCurlyStrings := rng.nestedQCurlyStrings;
end;
end;
function TSynD2SynRange.Compare(range: TSynCustomHighlighterRange): integer;
var
src_t: TSynD2SynRange;
const
cmpRes: array[boolean] of integer = (-1, 1);
begin
result := inherited Compare(range);
assert(range <> nil);
if not result.equals(0) then
exit;
if range is TSynD2SynRange then
begin
src_t := TSynD2SynRange(range);
if src_t.rangeKinds <> rangeKinds then
exit(1);
if src_t.rString <> rString then
exit(1);
if src_t.nestedCommentsCount <> nestedCommentsCount then
exit(cmpRes[src_t.nestedCommentsCount > nestedCommentsCount]);
if src_t.namedRegionCount <> namedRegionCount then
exit(cmpRes[src_t.namedRegionCount > namedRegionCount]);
end;
end;
procedure TSynD2SynRange.Clear;
begin
inherited;
nestedCommentsCount := 0;
namedRegionCount := 0;
nestedQGeStrings:= 0;
nestedQParensStrings := 0;
nestedQSquareStrings := 0;
nestedQCurlyStrings := 0;
rangeKinds := [];
rString := false;
end;
procedure TSynD2SynRange.copyFrom(source: TSynD2SynRange);
begin
if source.isAssigned then
begin
nestedCommentsCount := source.nestedCommentsCount;
namedRegionCount := source.namedRegionCount;
rangeKinds := source.rangeKinds;
nestedQGeStrings:= source.nestedQGeStrings;
nestedQParensStrings := source.nestedQParensStrings;
nestedQSquareStrings := source.nestedQSquareStrings;
nestedQCurlyStrings := source.nestedQCurlyStrings;
rString := source.rString;
end;
end;
function TSynD2SynRange.notInExclusiveRange(): boolean;
begin
result := rangeKinds - [rkAttrib, rkAsm] = [];
end;
constructor TSynD2Syn.create(aOwner: TComponent);
begin
inherited create(aOwner);
SetSubComponent(true);
DefaultFilter:= 'D source|*.d|D interface|*.di';
fFoldKinds := [fkBrackets,fkRegion];
WordBreakChars := WordBreakChars - ['@'];
fWhiteAttrib := TSynHighlighterAttributes.Create('White','White');
fNumbrAttrib := TSynHighlighterAttributes.Create('Numbr','Numbr');
fSymblAttrib := TSynHighlighterAttributes.Create('Symbl','Symbl');
fIdentAttrib := TSynHighlighterAttributes.Create('Ident','Ident');
fCommtAttrib := TSynHighlighterAttributes.Create('Commt','Commt');
fStrngAttrib := TSynHighlighterAttributes.Create('Strng','Strng');
fKeywdAttrib := TSynHighlighterAttributes.Create('Keywd','Keywd');
fDDocsAttrib := TSynHighlighterAttributes.Create('DDocs','DDocs');
fAsblrAttrib := TSynHighlighterAttributes.Create('Asblr','Asblr');
fSpeckAttrib := TSynHighlighterAttributes.Create('Speck','Speck');
fErrorAttrib := TSynHighlighterAttributes.Create('Error','Error');
fAttriAttrib := TSynHighlighterAttributes.Create('Attri','Attri');
fTypesAttrib := TSynHighlighterAttributes.Create('Types','Types');
fFCallAttrib := TSynHighlighterAttributes.Create('Calls','Calls');
fLost_Attrib := TSynHighlighterAttributes.Create('Lost','Lost');
fNumbrAttrib.Foreground := $000079F2;
fSymblAttrib.Foreground := clMaroon;
fIdentAttrib.Foreground := clBlack;
fCommtAttrib.Foreground := clGreen;
fStrngAttrib.Foreground := clBlue;
fKeywdAttrib.Foreground := clNavy;
fAsblrAttrib.Foreground := clGray;
fSpeckAttrib.Foreground := clNavy;
fAttriAttrib.Foreground := clNavy;
fLost_Attrib.Foreground := clLime;
fDDocsAttrib.Foreground := clTeal;
fTypesAttrib.Foreground := clBlack;
fFCallAttrib.Foreground := clBlack;
fLost_Attrib.Background := clBlack;
fCommtAttrib.Style := [fsItalic];
fKeywdAttrib.Style := [fsBold];
fAsblrAttrib.Style := [fsBold];
fSpeckAttrib.Style := [fsBold];
fAttriAttrib.Style := [fsBold];
fLost_Attrib.Style := [fsBold];
fTypesAttrib.Style := [fsBold];
fErrorAttrib.Foreground:= fIdentAttrib.Foreground;
fErrorAttrib.FrameStyle:= slsWaved;
fErrorAttrib.FrameColor:= clRed;
fErrorAttrib.FrameEdges:= sfeBottom;
AddAttribute(fWhiteAttrib);
AddAttribute(fNumbrAttrib);
AddAttribute(fSymblAttrib);
AddAttribute(fIdentAttrib);
AddAttribute(fCommtAttrib);
AddAttribute(fStrngAttrib);
AddAttribute(fKeywdAttrib);
AddAttribute(fDDocsAttrib);
AddAttribute(fAsblrAttrib);
AddAttribute(fSpeckAttrib);
AddAttribute(fErrorAttrib);
AddAttribute(fAttriAttrib);
AddAttribute(fTypesAttrib);
AddAttribute(fFCallAttrib);
fAttribLut[TTokenKind.tkident] := fIdentAttrib;
fAttribLut[TTokenKind.tkBlank] := fWhiteAttrib;
fAttribLut[TTokenKind.tkCommt] := fCommtAttrib;
fAttribLut[TTokenKind.tkKeywd] := fKeywdAttrib;
fAttribLut[TTokenKind.tkNumbr] := fNumbrAttrib;
fAttribLut[TTokenKind.tkStrng] := fStrngAttrib;
fAttribLut[TTokenKind.tksymbl] := fSymblAttrib;
fAttribLut[TTokenKind.tkDDocs] := fDDocsAttrib;
fAttribLut[TTokenKind.tkSpecK] := fSpeckAttrib;
fAttribLut[TTokenKind.tkError] := fErrorAttrib;
fAttribLut[TTokenKind.tkAsmbl] := fAsblrAttrib;
fAttribLut[TTokenKind.tkAttri] := fAttriAttrib;
fAttribLut[TTokenKind.tkTypes] := fTypesAttrib;
fAttribLut[TTokenKind.tkLost] := fLost_Attrib;
fAttribLut[TTokenKind.tkCall] := fFCallAttrib;
SetAttributesOnChange(@doAttribChange);
fTokStop := 1;
next;
end;
destructor TSynD2Syn.destroy;
begin
fLost_Attrib.Free;
fCurrRange.Free;
inherited;
end;
procedure TSynD2Syn.Assign(Source: TPersistent);
var
srcsyn: TSynD2Syn;
begin
inherited;
if Source is TSynD2Syn then
begin
srcsyn := TSynD2Syn(Source);
foldKinds := srcsyn.foldKinds;
fPhobosStyleType:=srcsyn.fPhobosStyleType;
end;
end;
function TSynD2Syn.GetRangeClass: TSynCustomHighlighterRangeClass;
begin
result := TSynD2SynRange;
end;
function TSynD2Syn.GetIdentChars: TSynIdentChars;
begin
result := ['_', 'A'..'Z', 'a'..'z', '0'..'9'];
end;
procedure TSynD2Syn.doChanged;
begin
BeginUpdate;
fUpdateChange := true;
EndUpdate;
end;
procedure TSynD2Syn.doAttribChange(sender: TObject);
begin
doChanged;
end;
procedure TSynD2Syn.setFoldKinds(value: TFoldKinds);
begin
fFoldKinds := value;
DoFoldConfigChanged(Self);
doChanged;
end;
procedure TSynD2Syn.setWhiteAttrib(value: TSynHighlighterAttributes);
begin
fWhiteAttrib.Assign(value);
end;
procedure TSynD2Syn.setNumbrAttrib(value: TSynHighlighterAttributes);
begin
fNumbrAttrib.Assign(value);
end;
procedure TSynD2Syn.setSymblAttrib(value: TSynHighlighterAttributes);
begin
fSymblAttrib.Assign(value);
end;
procedure TSynD2Syn.setIdentAttrib(value: TSynHighlighterAttributes);
begin
fIdentAttrib.Assign(value);
end;
procedure TSynD2Syn.setCommtAttrib(value: TSynHighlighterAttributes);
begin
fCommtAttrib.Assign(value);
end;
procedure TSynD2Syn.setStrngAttrib(value: TSynHighlighterAttributes);
begin
fStrngAttrib.Assign(value);
end;
procedure TSynD2Syn.setKeywdAttrib(value: TSynHighlighterAttributes);
begin
fKeywdAttrib.Assign(value);
end;
procedure TSynD2Syn.setDDocsAttrib(value: TSynHighlighterAttributes);
begin
fDDocsAttrib.Assign(value);
end;
procedure TSynD2Syn.setAsblrAttrib(value: TSynHighlighterAttributes);
begin
fAsblrAttrib.Assign(value);
end;
procedure TSynD2Syn.setSpeckAttrib(value: TSynHighlighterAttributes);
begin
fSpeckAttrib.Assign(value);
end;
procedure TSynD2Syn.setErrorAttrib(value: TSynHighlighterAttributes);
begin
fErrorAttrib.Assign(value);
end;
procedure TSynD2Syn.setAttriAttrib(value: TSynHighlighterAttributes);
begin
fAttriAttrib.Assign(value);
end;
procedure TSynD2Syn.setTypesAttrib(value: TSynHighlighterAttributes);
begin
fTypesAttrib.Assign(value);
end;
procedure TSynD2Syn.setFCallAttrib(value: TSynHighlighterAttributes);
begin
fFCallAttrib.Assign(value);
end;
procedure TSynD2Syn.setLine(const NewValue: string; LineNumber: Integer);
begin
inherited;
// note: the end of line is marked with a #10
// usually a TSynCustomFoldHighlighter rather tests 'length(line)' in 'Next()'
// but since the scanner works line by line, #10 is guaranteed not to
// appear at all excepted when added implictly, like here.
fLineBuf := NewValue + #10;
fTokStop := 1;
next;
end;
procedure TSynD2Syn.next;
var
reader: PChar = nil;
label
_notRawStrng, _notDotFloat;
procedure readerReset;
begin
fTokStop := fTokStart;
reader := @fLineBuf[fTokStop];
end;
function readerNext: PChar;
begin
Inc(reader);
Inc(fTokStop);
exit(reader);
end;
function readerPrev: PChar;
begin
Dec(reader);
Dec(fTokStop);
exit(reader);
end;
begin
fTokStart := fTokStop;
fTokStop := fTokStart;
// EOL
if fTokStop > length(fLineBuf) then
exit;
readerReset;
// script line
if LineIndex.equals(0) and fTokStart.equals(1) and readDelim(reader, fTokStop, '#!') then
begin
fTokKind := tkCommt;
readLine(reader, fTokStop);
exit;
end
else readerReset;
// spaces
if (isWhite(reader^)) then
begin
fTokKind := tkBlank;
while(true) do
begin
if isWhite(reader^) then
readerNext;
exit;
end;
end;
if fCurrRange.isNotAssigned then
fCurrRange := TSynD2SynRange.Create(nil);
// line comments / region beg-end
if fCurrRange.notInExclusiveRange() then
if readDelim(reader, fTokStop, '//') then
begin
fTokKind := tkCommt;
if readDelim(reader, fTokStop, '/') then
fTokKind := tkDDocs;
readLine(reader, fTokStop);
if (fkRegion in fFoldKinds) and (fTokStop - fTokStart > 4) then
begin
while isWhite(reader^) do
begin
Dec(reader);
Dec(fTokStop);
end;
Dec(reader, 3);
Dec(fTokStop, 3);
if reader[0..3] = '---+' then
begin
fCurrRange.namedRegionCount += 1;
StartCodeFoldBlock(nil);
end
else if (reader[0..3] = '----') and (fCurrRange.namedRegionCount > 0) then
begin
EndCodeFoldBlock();
fCurrRange.namedRegionCount -= 1;
end;
readLine(reader, fTokStop);
end;
exit;
end else readerReset;
// block comments 1
if fCurrRange.notInExclusiveRange() then
if readDelim(reader, fTokStop, '/*') then
begin
fTokKind := tkCommt;
if readDelim(reader, fTokStop, '*') then
if readDelim(reader, fTokStop, '/') then
exit
else
fTokKind := tkDDocs;
if readUntil(reader, fTokStop, '*/') then
exit;
if fTokKind = tkDDocs then
fCurrRange.rangeKinds += [rkBlockDoc1]
else
fCurrRange.rangeKinds += [rkBlockCom1];
readLine(reader, fTokStop);
if (fTokKind = tkCommt) then
StartCodeFoldBlock(nil, fkComments1 in fFoldKinds)
else if (fTokKind = tkDDocs) then
StartCodeFoldBlock(nil, fkDDoc in fFoldKinds);
exit;
end else readerReset;
if (rkBlockCom1 in fCurrRange.rangeKinds) or (rkBlockDoc1 in fCurrRange.rangeKinds) then
begin
if (rkBlockDoc1 in fCurrRange.rangeKinds) then
fTokKind := tkDDocs
else
fTokKind := tkCommt;
if readUntil(reader, fTokStop, '*/') then
begin
if (fTokKind = tkCommt) then
EndCodeFoldBlock(fkComments1 in fFoldKinds)
else if (fTokKind = tkDDocs) then
EndCodeFoldBlock(fkDDoc in fFoldKinds);
fCurrRange.rangeKinds -= [rkBlockDoc1, rkBlockCom1];
exit;
end;
readLine(reader, fTokStop);
exit;
end;
// block comments 2
if fCurrRange.notInExclusiveRange() then
if readDelim(reader, fTokStop, '/+') then
begin
fTokKind := tkCommt;
if readDelim(reader, fTokStop, '+') then
if readDelim(reader, fTokStop, '/') then
exit
else
fTokKind := tkDDocs;
inc(fCurrRange.nestedCommentsCount);
while (reader^ <> #10) and (fCurrRange.nestedCommentsCount > 0) do
begin
if readUntilAmong(reader, fTokStop, ['+', '/']) then
begin
if readDelim(reader, fTokStop, ['+', '/']) then
begin
if ((reader-1)^ = '/') and (reader^ = '+') then
begin
inc(fCurrRange.nestedCommentsCount);
readerNext;
continue;
end;
if ((reader-1)^ = '+') and (reader^ = '/') then
begin
dec(fCurrRange.nestedCommentsCount);
readerNext;
continue;
end;
end else readerNext;
end;
end;
if (fCurrRange.nestedCommentsCount > 0) then
begin
if fTokKind = tkDDocs then
fCurrRange.rangeKinds += [rkBlockDoc2]
else
fCurrRange.rangeKinds += [rkBlockCom2];
if (fTokKind = tkCommt) then
StartCodeFoldBlock(nil, fkComments2 in fFoldKinds)
else if (fTokKind = tkDDocs) then
StartCodeFoldBlock(nil, fkDDoc in fFoldKinds);
end;
exit;
end else readerReset;
if (rkBlockCom2 in fCurrRange.rangeKinds) or (rkBlockDoc2 in fCurrRange.rangeKinds) then
begin
if (rkBlockDoc2 in fCurrRange.rangeKinds) then
fTokKind := tkDDocs
else
fTokKind := tkCommt;
while (reader^ <> #10) and (fCurrRange.nestedCommentsCount > 0) do
begin
if readUntilAmong(reader, fTokStop, ['+', '/']) then
begin
if readDelim(reader, fTokStop, ['+', '/']) then
begin
if ((reader-1)^ = '/') and (reader^ = '+') then
begin
inc(fCurrRange.nestedCommentsCount);
readerNext;
continue;
end;
if ((reader-1)^ = '+') and (reader^ = '/') then
begin
dec(fCurrRange.nestedCommentsCount);
readerNext;
continue;
end;
end else readerNext;
end;
end;
if fCurrRange.nestedCommentsCount.equals(0) then
begin
if fTokKind = tkCommt then
EndCodeFoldBlock(fkComments2 in fFoldKinds)
else if fTokKind = tkDDocs then
EndCodeFoldBlock(fkDDoc in fFoldKinds);
fCurrRange.rangeKinds -= [rkBlockDoc2, rkBlockCom2];
end;
exit;
end;
// double quoted strings | raw double quoted strings
if (fCurrRange.notInExclusiveRange()) and readDelim(reader, fTokStop, stringPrefixes) then
begin
if readerPrev^ in ['r','x'] then
begin
fCurrRange.rString := reader^ = 'r';
if not (readerNext^ = '"') then
begin
fCurrRange.rString := false;
readerPrev;
goto _notRawStrng;
end;
end;
readerNext;
fTokKind := tkStrng;
while(true) do
begin
if not readUntilAmong(reader, fTokStop, stringStopChecks) then
break;
if (reader^ = '\') then
begin
readerNext;
if reader^ <> #10 then
begin
if fCurrRange.rString then
continue;
readerNext;
end;
end
else if reader^ = '"' then
begin
readerNext;
readDelim(reader, fTokStop, stringPostfixes);
fCurrRange.rString := false;
exit;
end;
end;
fCurrRange.rangeKinds += [rkString1];
StartCodeFoldBlock(nil, fkStrings in fFoldKinds);
exit;
end else _notRawStrng: readerReset;
if rkString1 in fCurrRange.rangeKinds then
begin
fTokKind := tkStrng;
while(true) do
begin
if not readUntilAmong(reader, fTokStop, stringStopChecks) then
break;
if reader^ = '\' then
begin
readerNext;
if reader^ <> #10 then
begin
if fCurrRange.rString then
continue;
readerNext;
end;
end
else if reader^ = '"' then
begin
readerNext;
fCurrRange.rangeKinds -= [rkString1];
readDelim(reader, fTokStop, stringPostfixes);
fCurrRange.rString := false;
EndCodeFoldBlock(fkStrings in fFoldKinds);
exit;
end
else break;
end;
readLine(reader, fTokStop);
exit;
end;
// backticks strings
if fCurrRange.notInExclusiveRange() and readDelim(reader, fTokStop, '`') then
begin
fTokKind := tkStrng;
if readUntil(reader, fTokStop, '`') then
begin
readDelim(reader, fTokStop, stringPostfixes);
exit;
end;
fCurrRange.rangeKinds += [rkString2];
readLine(reader, fTokStop);
StartCodeFoldBlock(nil, fkStrings in fFoldKinds);
exit;
end else readerReset;
if rkString2 in fCurrRange.rangeKinds then
begin
fTokKind := tkStrng;
if readUntil(reader, fTokStop, '`') then
begin
fCurrRange.rangeKinds -= [rkString2];
EndCodeFoldBlock(fkStrings in fFoldKinds);
readDelim(reader, fTokStop, stringPostfixes);
exit;
end;
readLine(reader, fTokStop);
exit;
end;
// token string
if readDelim(reader, fTokStop, 'q{') then
begin
fTokKind := tkSymbl;
StartCodeFoldBlock(nil, fkBrackets in fFoldKinds);
exit;
end else readerReset;
// q"( )" strings
if fCurrRange.notInExclusiveRange() and readDelim(reader, fTokStop, 'q"(') then
begin
fTokKind := tkStrng;
fCurrRange.nestedQParensStrings += 1;
if readUntil(reader, fTokStop, ')"') then
begin
fCurrRange.nestedQParensStrings -= 1;
if fCurrRange.nestedQParensStrings.equals(0) then
begin
readDelim(reader, fTokStop, stringPostfixes);
exit;
end;
end;
fCurrRange.rangeKinds += [rkStringQParen];
readLine(reader, fTokStop);
exit;
end else readerReset;
if rkStringQParen in fCurrRange.rangeKinds then
begin
fTokKind := tkStrng;
if readUntil(reader, fTokStop, ')"') then
begin
fCurrRange.nestedQParensStrings -= 1;
if fCurrRange.nestedQParensStrings.equals(0) then
begin
readDelim(reader, fTokStop, stringPostfixes);
fCurrRange.rangeKinds -= [rkStringQParen];
exit;
end;
end;
readLine(reader, fTokStop);
exit;
end;
// q"[ ]" strings
if fCurrRange.notInExclusiveRange() and readDelim(reader, fTokStop, 'q"[') then
begin
fTokKind := tkStrng;
fCurrRange.nestedQSquareStrings += 1;
if readUntil(reader, fTokStop, ']"') then
begin
fCurrRange.nestedQSquareStrings -= 1;
if fCurrRange.nestedQSquareStrings.equals(0) then
begin
readDelim(reader, fTokStop, stringPostfixes);
exit;
end;
end;
fCurrRange.rangeKinds += [rkStringQSquare];
readLine(reader, fTokStop);
exit;
end else readerReset;
if rkStringQSquare in fCurrRange.rangeKinds then
begin
fTokKind := tkStrng;
if readUntil(reader, fTokStop, ']"') then
begin
fCurrRange.nestedQSquareStrings -= 1;
if fCurrRange.nestedQSquareStrings.equals(0) then
begin
readDelim(reader, fTokStop, stringPostfixes);
fCurrRange.rangeKinds -= [rkStringQSquare];
exit;
end;
end;
readLine(reader, fTokStop);
exit;
end;
// q"< >" strings
if fCurrRange.notInExclusiveRange() and readDelim(reader, fTokStop, 'q"<') then
begin
fTokKind := tkStrng;
fCurrRange.nestedQGeStrings += 1;
if readUntil(reader, fTokStop, '>"') then
begin
fCurrRange.nestedQGeStrings -= 1;
if fCurrRange.nestedQGeStrings.equals(0) then
begin
readDelim(reader, fTokStop, stringPostfixes);
exit;
end;
end;
fCurrRange.rangeKinds += [rkStringQGe];
readLine(reader, fTokStop);
exit;
end else readerReset;
if rkStringQGe in fCurrRange.rangeKinds then
begin
fTokKind := tkStrng;
if readUntil(reader, fTokStop, ')"') then
begin
fCurrRange.nestedQGeStrings -= 1;
if fCurrRange.nestedQGeStrings.equals(0) then
begin
readDelim(reader, fTokStop, stringPostfixes);
fCurrRange.rangeKinds -= [rkStringQGe];
exit;
end;
end;
readLine(reader, fTokStop);
exit;
end;
// q"{ }" strings
if fCurrRange.notInExclusiveRange() and readDelim(reader, fTokStop, 'q"{') then
begin
fTokKind := tkStrng;
fCurrRange.nestedQCurlyStrings += 1;
if readUntil(reader, fTokStop, '}"') then
begin
fCurrRange.nestedQCurlyStrings -= 1;
if fCurrRange.nestedQCurlyStrings.equals(0) then
begin
readDelim(reader, fTokStop, stringPostfixes);
exit;
end;
end;
fCurrRange.rangeKinds += [rStringQCurly];
readLine(reader, fTokStop);
exit;
end else readerReset;
if rStringQCurly in fCurrRange.rangeKinds then
begin
fTokKind := tkStrng;
if readUntil(reader, fTokStop, '}"') then
begin
fCurrRange.nestedQCurlyStrings -= 1;
if fCurrRange.nestedQCurlyStrings.equals(0) then
begin
readDelim(reader, fTokStop, stringPostfixes);
fCurrRange.rangeKinds -= [rStringQCurly];
exit;
end;
end;
readLine(reader, fTokStop);
exit;
end;
// char literals
if fCurrRange.notInExclusiveRange() and readDelim(reader, fTokStop, #39) then
begin
fTokKind := tkStrng;
while true do
begin
if reader^ = '\' then
begin
readerNext;
if reader^ = #10 then
exit;
readerNext;
end;
if reader^ = #10 then
exit;
if reader^ = #39 then
break;
readerNext;
end;
readerNext;
exit;
end else readerReset;
// bin & hex literals
if reader^ = '0' then
if readerNext^ in ['b','B', 'x', 'X'] then
begin
fTokKind:= tkNumbr;
readerNext;
if (reader-1)^ in ['b','B'] then
readWhile(reader, fTokStop, ['0','1','_'])
else
readWhile(reader, fTokStop, hexaChars + ['.']);
// exponent, sign tokenized later as op and the value as number
if reader^ in ['P','p'] then
begin
readerNext;
exit;
end;
if not tryReadDelim(reader, fTokStop, 'uL')
and not tryReadDelim(reader, fTokStop, 'UL')
and not tryReadDelim(reader, fTokStop, 'Lu')
and not tryReadDelim(reader, fTokStop, 'LU')
and (reader^ in ['U', 'L', 'u', 'i']) then
readerNext;
if not isWhite(reader^) and not isOperator1(reader^) and
not isSymbol(reader^) then
begin
fTokKind:= tkError;
readUntilAmong(reader, fTokStop, [#0..#32] + symbChars);
end;
exit;
end
else readerPrev;
// int and float literals
if (reader^ = '.') or (isNumber(reader^)) then
begin
if (reader^= '.') then
begin
readerPrev;
if reader^= '.' then
begin
readerNext;
goto _notDotFloat;
end else
readerNext;
readerNext;
if not isNumber(reader^) then
begin
readerPrev;
goto _notDotFloat;
end else
readerPrev;
end;
fTokKind:= tkNumbr;
if reader^ <> '.' then
while isNumber(readerNext^) or (reader^ = '_') do (*!*);
if reader^ = '.' then
begin
if isNumber(readerNext^) then
begin
while isNumber(reader^) or (reader^ = '_') do
readerNext;
end else
readerPrev;
end;
if reader^= '.' then
begin
readerNext;
// .init .min .max etc.
if not isNumber(reader^) then
begin
readerPrev;
exit;
end;
readerPrev;
end;
// exponent, sign tokenized later as op and the value as number
if reader^ in ['E','e'] then
begin
readerNext;
exit;
end;
// try valid suffixes
if not tryReadDelim(reader, fTokStop, 'uL')
and not tryReadDelim(reader, fTokStop, 'UL')
and not tryReadDelim(reader, fTokStop, 'Lu')
and not tryReadDelim(reader, fTokStop, 'LU')
and not tryReadDelim(reader, fTokStop, 'fi')
and not tryReadDelim(reader, fTokStop, 'Fi')
and not tryReadDelim(reader, fTokStop, 'Li')
and (reader^ in ['U','L','u', 'i', 'f','F']) then
readerNext;
if not isWhite(reader^) and not isOperator1(reader^) and
(not isSymbol(reader^) or (reader^ = '.')) then
begin
fTokKind:= tkError;
readUntilAmong(reader, fTokStop, [#0..#32] + symbChars - ['.']);
end;
if (fTokStop - fTokStart = 10) and (fLineBuf[fTokStart..fTokStop-1] = '4815162342') then
fTokKind:=tkLost;
exit;
end;
_notDotFloat:
// symbols
if isSymbol(reader^) then
begin
fTokKind := tkSymbl;
case reader^ of
'{': StartCodeFoldBlock(nil, fkBrackets in fFoldKinds);
'}':
begin
EndCodeFoldBlock(fkBrackets in fFoldKinds);
if (reader^ = '}') and (rkAsm in fCurrRange.rangeKinds) then
fCurrRange.rangeKinds -= [rkAsm];
if ((reader+1)^ in stringPostfixes) and not isIdentifier((reader+2)^) then
readerNext;
end;
'(':
begin
if rkAttrib in fCurrRange.rangeKinds then
fCurrRange.attribParenCount += 1;
end;
')':
begin
if rkAttrib in fCurrRange.rangeKinds then
begin
fCurrRange.attribParenCount -= 1;
if fCurrRange.attribParenCount.equals(0) then
begin
fCurrRange.rangeKinds -= [rkAttrib];
fTokKind := tkAttri;
end;
end;
end;
end;
readerNext;
exit;
end;
// operators
if isOperator1(reader^) then
begin
fTokKind := tkSymbl;
while isOperator1(readerNext^) do
if (fTokStop - fTokStart = 4) or (reader^= #10) then
break;
if (fTokStop - fTokStart = 4) then
begin
if isOperator4(fLineBuf[fTokStart..fTokStart+3]) then
exit;
if isOperator3(fLineBuf[fTokStart..fTokStart+2]) then
begin
readerPrev;
exit;
end;
if isOperator2(fLineBuf[fTokStart..fTokStart+1]) then
begin
readerPrev;
readerPrev;
exit;
end;
if isOperator1(fLineBuf[fTokStart]) then
begin
readerPrev;
readerPrev;
readerPrev;
exit;
end;
end;
if (fTokStop - fTokStart = 3) then
begin
if isOperator3(fLineBuf[fTokStart..fTokStart+2]) then
exit;
if isOperator2(fLineBuf[fTokStart..fTokStart+1]) then
begin
readerPrev;
exit;
end;
if isOperator1(fLineBuf[fTokStart]) then
begin
readerPrev;
readerPrev;
exit;
end;
end;
if (fTokStop - fTokStart = 2) then
begin
if isOperator2(fLineBuf[fTokStart..fTokStart+1]) then
exit;
if isOperator1(fLineBuf[fTokStart]) then
begin
readerPrev;
exit;
end;
end;
if (fTokStop - fTokStart = 1) and isOperator1(fLineBuf[fTokStart]) then
exit;
fTokKind := tkError;
exit;
end;
// attributes
if reader^ = '@' then
begin
if isAlpha(readerNext^) then
begin
fTokKind:=tkAttri;
while isAlNum(reader^) or (reader^ = '_') do
begin
if (reader^= #10) or (reader^= '@') then
exit;
readerNext;
end;
exit;
end
else if (reader^ = '(') and (not (rkAttrib in fCurrRange.rangeKinds)) then
begin
fCurrRange.rangeKinds += [rkAttrib];
fTokKind:=tkAttri;
fCurrRange.attribParenCount := 1;
readerNext;
exit;
end
else readerPrev();
end;
// Keywords & identifiers
if isFirstIdentifier(reader^) then
begin
fTokKind := tkIdent;
while(true) do
begin
if isWhite(readerNext^) or isSymbol(reader^) or isOperator1(reader^) or
(reader^ = '@') then
break;
end;
if keywordsMap.match(fLineBuf[FTokStart..fTokStop-1]) then
begin
fTokKind := tkKeywd;
if (fLineBuf[FTokStart..fTokStop-1] = 'asm') then
fCurrRange.rangeKinds += [rkAsm];
end
else if specialKeywordsMap.match(fLineBuf[FTokStart..fTokStop-1]) then
fTokKind := tkSpecK
else if reader^ = '(' then
fTokKind:= tkCall
else if fPhobosStyleType and ('A' <= fLineBuf[FTokStart]) and (fLineBuf[FTokStart] <= 'Z') then
fTokKind:= tkTypes
else if rkAsm in fCurrRange.rangeKinds then
fTokKind:=tkAsmbl;
exit;
end;
if fLineBuf[fTokStop] = #10 then
exit;
readUntilAmong(reader, fTokStop, [#9, #10, ' ']);
fTokKind := tkError;
end;
function TSynD2Syn.GetEol: Boolean;
begin
result := fTokStop > length(fLineBuf);
end;
function TSynD2Syn.GetTokenAttribute: TSynHighlighterAttributes;
begin
result := fAttribLut[fTokKind];
end;
procedure TSynD2Syn.SetRange(value: Pointer);
var
stored: TSynD2SynRange;
begin
inherited SetRange(value);
stored := TSynD2SynRange(CodeFoldRange.RangeType);
if fCurrRange.isAssigned and stored.isAssigned then
fCurrRange.copyFrom(stored);
end;
function TSynD2Syn.GetRange: Pointer;
var
stored: TSynD2SynRange;
begin
stored := TSynD2SynRange(inherited GetRange);
if stored.isNotAssigned then
stored := TSynD2SynRange.Create(nil);
stored.copyFrom(fCurrRange);
CodeFoldRange.RangeType := Pointer(stored);
Result := inherited GetRange;
end;
procedure TSynD2Syn.ResetRange;
begin
if fCurrRange.isNotAssigned then
fCurrRange := TSynD2SynRange.Create(nil)
else
fCurrRange.Clear;
end;
function TSynD2Syn.GetTokenPos: Integer;
begin
result := fTokStart - 1;
end;
function TSynD2Syn.GetToken: string;
begin
result := copy(fLineBuf, FTokStart, fTokStop - FTokStart);
end;
procedure TSynD2Syn.GetTokenEx(out TokenStart: PChar; out TokenLength: integer);
begin
TokenStart := @fLineBuf[FTokStart];
TokenLength := fTokStop - FTokStart;
end;
function TSynD2Syn.GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
begin
result := nil;
end;
function TSynD2Syn.GetTokenKind: integer;
begin
Result := Integer(fTokKind);
end;
end.