diff --git a/lazproj/dexed.lpi b/lazproj/dexed.lpi index 31cf1194..31006aed 100644 --- a/lazproj/dexed.lpi +++ b/lazproj/dexed.lpi @@ -1,13 +1,11 @@ - + - - - + <ResourceType Value="res"/> <UseXPManifest Value="True"/> @@ -551,7 +549,7 @@ <PackageName Value="LCL"/> </Item8> </RequiredPackages> - <Units Count="62"> + <Units Count="63"> <Unit0> <Filename Value="dexed.lpr"/> <IsPartOfProject Value="True"/> @@ -876,6 +874,10 @@ <Filename Value="..\src\u_synmultiguttermarks.pas"/> <IsPartOfProject Value="True"/> </Unit61> + <Unit62> + <Filename Value="..\src\u_sxsyn.pas"/> + <IsPartOfProject Value="True"/> + </Unit62> </Units> </ProjectOptions> <CompilerOptions> diff --git a/src/u_common.pas b/src/u_common.pas index 8bb6d613..18c44fb7 100644 --- a/src/u_common.pas +++ b/src/u_common.pas @@ -303,6 +303,11 @@ type *) function hasCppSyntax(const ext: string): boolean; + (** + * Returns true if ext matches a file extension whose type is highlightable (C/C++) + *) + function hasSxSyntax(const ext: string): boolean; + (** * Returns true if ext matches a file extension whose type can be passed as source. *) @@ -1349,6 +1354,14 @@ begin end; end; +function hasSxSyntax(const ext: string): boolean; +begin + result := false; + case ext of + '.sx', '.sar': result := true; + end; +end; + function isDlangCompilable(const ext: string): boolean; begin result := false; diff --git a/src/u_editoroptions.pas b/src/u_editoroptions.pas index 22fd8625..96693465 100644 --- a/src/u_editoroptions.pas +++ b/src/u_editoroptions.pas @@ -699,6 +699,16 @@ begin anEditor.CppHighlighter.SymbolAttri := anEditor.D2Highlighter.symbols; anEditor.CppHighlighter.NumberAttri := anEditor.D2Highlighter.numbers; + anEditor.SxHighlighter.attributes := anEditor.D2Highlighter.attributes; + anEditor.SxHighlighter.comments := anEditor.D2Highlighter.comments; + anEditor.SxHighlighter.identifiers := anEditor.D2Highlighter.identifiers; + anEditor.SxHighlighter.keywords := anEditor.D2Highlighter.keywords; + anEditor.SxHighlighter.whites := anEditor.D2Highlighter.whites; + anEditor.SxHighlighter.strings := anEditor.D2Highlighter.strings; + anEditor.SxHighlighter.symbols := anEditor.D2Highlighter.symbols; + anEditor.SxHighlighter.numbers := anEditor.D2Highlighter.numbers; + anEditor.SxHighlighter.errors := anEditor.D2Highlighter.errors; + anEditor.completionMenu.TheForm.Font.Assign(font); anEditor.autoCloseCurlyBrace := fAutoCloseCurlyBrace; anEditor.autoClosedPairs := fAutoClosedPairs; diff --git a/src/u_sxsyn.pas b/src/u_sxsyn.pas new file mode 100644 index 00000000..3fdea3e3 --- /dev/null +++ b/src/u_sxsyn.pas @@ -0,0 +1,828 @@ +unit u_sxsyn; + +{$I u_defines.inc} + +interface + +uses + Classes, SysUtils, Graphics, + SynEditHighlighter, SynEditHighlighterFoldBase, SynEditTypes, + u_common; + +type + + KeywordMatch = record + private + + { + rendered on 2021-Oct-31 06:16:53.798781 by IsItThere. + - PRNG seed: 6574 + - map length: 128 + - case sensitive: true + } + + const fWords: array [0..127] of string = + ('', '', 'alias', 'this', 'f32', '', 's32', 's8', 'throw', 'f64', 'switch', 's64', '', '', '', '', '', '', 'finally', '', '', '', 'if', '', '', '', '', '', '', '', '', '', '', '', '', '', 'protection', 's16', '', '', 'goto', 'usize', '', '', 'in', '', 'static', '', 'try', '', '', '', 'enum', 'do', '', '', '', 'super', 'const', 'union', '', '', 'else', '', 'version', '', '', '', '', 'u32', 'u8', 'echo', '', 'true', 'u64', 'asm', '', 'struct', '', 'auto', 'bool', '', '', '', '', '', 'false', 'null', 'class', '', '', 'overload', '', '', '', '', 'label', '', 'assert', 'continue', 'u16', 'foreach', 'break', '', '', '', 'ssize', '', '', '', '', 'unit', 'while', '', 'var', '', 'with', 'template', '', 'import', 'on', '', '', 'function', '', 'return', '', ''); + + const fFilled: array [0..127] of boolean = + (false, false, true, true, true, false, true, true, true, true, true, true, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, true, true, false, false, true, false, true, false, true, false, false, false, true, true, false, false, false, true, true, true, false, false, true, false, true, false, false, false, false, true, true, true, false, true, true, true, false, true, false, true, true, false, false, false, false, false, true, true, true, false, false, true, false, false, false, false, true, false, true, true, true, true, true, false, false, false, true, false, false, false, false, true, true, false, true, false, true, true, false, true, true, false, false, true, false, true, false, false); + + const fCoefficients: array [0..255] of Byte = + (251, 141, 241, 229, 153, 224, 69, 154, 183, 60, 181, 128, 168, 190, 25, 39, 142, 116, 172, 48, 49, 203, 195, 46, 229, 38, 232, 88, 114, 147, 97, 185, 242, 43, 34, 75, 89, 228, 21, 156, 254, 129, 186, 74, 224, 78, 146, 25, 49, 118, 232, 70, 92, 34, 215, 44, 47, 48, 153, 28, 19, 111, 146, 97, 159, 224, 143, 72, 212, 194, 30, 104, 134, 217, 123, 30, 68, 206, 208, 50, 96, 3, 30, 30, 90, 245, 234, 93, 191, 97, 112, 45, 103, 11, 225, 255, 132, 128, 78, 62, 41, 62, 214, 100, 191, 64, 95, 146, 234, 243, 236, 12, 68, 60, 72, 216, 44, 23, 42, 201, 206, 188, 188, 190, 114, 193, 20, 143, 119, 31, 235, 96, 72, 92, 146, 146, 227, 33, 253, 76, 142, 189, 58, 38, 203, 68, 19, 35, 82, 49, 150, 78, 157, 199, 33, 210, 223, 133, 237, 56, 89, 123, 20, 177, 68, 205, 21, 128, 142, 35, 222, 180, 138, 141, 10, 160, 212, 166, 255, 166, 75, 212, 216, 239, 76, 119, 45, 62, 130, 21, 116, 119, 253, 50, 241, 160, 208, 225, 244, 55, 57, 238, 239, 107, 190, 143, 165, 125, 217, 80, 18, 244, 72, 210, 28, 77, 138, 40, 239, 124, 75, 87, 92, 121, 107, 222, 0, 23, 215, 213, 133, 144, 208, 216, 191, 170, 75, 182, 75, 230, 218, 136, 44, 134, 191, 183, 126, 108, 58, 29, 52, 163, 111, 131, 198, 230); + + class function hash(const w: string): Word; static; + public + class function contains(const w: string): boolean; static; + end; + + TTokenKind = (tkNone, tkError, tkCommt, tkIdent, tkKeywd, tkStrng, tkBlank, tkSymbl, tkNumbr, tkAttri); + + TRangeKind = (rkNone, rkString1, rkString2, rkBlockCom1, rkAttrib); + + TSynSxSynRange = class (TSynCustomHighlighterRange) + private + attribParenCount : Integer; + rangeKind : TRangeKind; + public + procedure Assign(source: TSynCustomHighlighterRange); override; + function Compare(range: TSynCustomHighlighterRange): integer; override; + procedure Clear; override; + procedure copyFrom(source: TSynSxSynRange); + end; + + TSynSxSyn = class (TSynCustomFoldHighlighter) + private + fWhiteAttrib: TSynHighlighterAttributes; + fNumbrAttrib: TSynHighlighterAttributes; + fSymblAttrib: TSynHighlighterAttributes; + fIdentAttrib: TSynHighlighterAttributes; + fCommtAttrib: TSynHighlighterAttributes; + fStrngAttrib: TSynHighlighterAttributes; + fKeywdAttrib: TSynHighlighterAttributes; + fAttriAttrib: TSynHighlighterAttributes; + fErrorAttrib: TSynHighlighterAttributes; + + fLineBuf: string; + fTokStart, fTokStop: Integer; + fTokKind: TTokenKind; + fCurrRange: TSynSxSynRange; + fLineNum: integer; + + fAttribLut: array[TTokenKind] of TSynHighlighterAttributes; + + 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 setAttriAttrib(value: TSynHighlighterAttributes); + procedure setErrorAttrib(value: TSynHighlighterAttributes); + + function safeLookupChar(): PChar; + function canLookup2Char(): boolean; + procedure lexOpAndOpEqual(); + procedure lexOpAndOpOpAndOpEqual(const op: char); + procedure lexOpAndOpOpAndOpEqualAndOpOpEqual(const op: char); + procedure lexAssEquOrLambda(); + procedure lexHexLiteral(); + procedure lexBinLiteral(); + procedure lexIntLiteral(); + procedure lexFloatingLiteralFractionalPart(); + procedure lexExponent(); + procedure lexStringLiteral(); + procedure lexRawStringLiteral(); + procedure lexLineComment(); + procedure lexStarComment(); + procedure lexIdentifier(); + + protected + function GetRangeClass: TSynCustomHighlighterRangeClass; override; + function GetIdentChars: TSynIdentChars; override; + + public + + constructor create(aOwner: TComponent); override; + destructor destroy; 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; + + 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 attributes: TSynHighlighterAttributes read fAttriAttrib write setAttriAttrib stored true; + property errors: TSynHighlighterAttributes read fErrorAttrib write setErrorAttrib stored true; + + end; + +implementation + +{$PUSH}{$R-}{$COPERATORS ON} +class function KeywordMatch.hash(const w: string): Word; +var + i: integer; +begin + Result := 0; + for i := 1 to length(w) do + Result += fCoefficients[Byte(w[i])]; + Result := Result mod 128; +end; + +class function KeywordMatch.contains(const w: string): boolean; +var + h: Word; +begin + result := false; + h := hash(w); + if fFilled[h] then + result := fWords[h] = w; +end; +{$POP} + +procedure TSynSxSynRange.Assign(source: TSynCustomHighlighterRange); +var + rng: TSynSxSynRange; +begin + inherited; + if source is TSynSxSynRange then + begin + rng := TSynSxSynRange(source); + rangeKind := rng.rangeKind; + end; +end; + +function TSynSxSynRange.Compare(range: TSynCustomHighlighterRange): integer; +begin + result := inherited Compare(range); + assert(range <> nil); + if not result.equals(0) then + exit; + if range is TSynSxSynRange then + result := integer(rangeKind = TSynSxSynRange(range).rangeKind); +end; + +procedure TSynSxSynRange.Clear; +begin + rangeKind := TRangeKind.rkNone; +end; + +procedure TSynSxSynRange.copyFrom(source: TSynSxSynRange); +begin + if source.isAssigned then + rangeKind := source.rangeKind; +end; + +constructor TSynSxSyn.create(aOwner: TComponent); +begin + inherited create(aOwner); + + DefaultFilter:= 'STYX source|*.sx|STYX archive|*.sar'; + + 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'); + fAttriAttrib := TSynHighlighterAttributes.Create('Attri','Attri'); + fErrorAttrib := TSynHighlighterAttributes.Create('Error','Error'); + + AddAttribute(fWhiteAttrib); + AddAttribute(fNumbrAttrib); + AddAttribute(fSymblAttrib); + AddAttribute(fIdentAttrib); + AddAttribute(fCommtAttrib); + AddAttribute(fStrngAttrib); + AddAttribute(fKeywdAttrib); + AddAttribute(fAttriAttrib); + AddAttribute(fErrorAttrib); + + 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.tkAttri] := fAttriAttrib; + fAttribLut[TTokenKind.tkError] := fErrorAttrib; + +end; + +destructor TSynSxSyn.destroy; +begin + fCurrRange.Free; + inherited; +end; + +function TSynSxSyn.GetRangeClass: TSynCustomHighlighterRangeClass; +begin + result := TSynSxSynRange; +end; + +function TSynSxSyn.GetIdentChars: TSynIdentChars; +begin + result := ['_', 'A'..'Z', 'a'..'z', '0'..'9']; +end; + +procedure TSynSxSyn.setWhiteAttrib(value: TSynHighlighterAttributes); +begin + fWhiteAttrib.Assign(value); +end; + +procedure TSynSxSyn.setNumbrAttrib(value: TSynHighlighterAttributes); +begin + fNumbrAttrib.Assign(value); +end; + +procedure TSynSxSyn.setSymblAttrib(value: TSynHighlighterAttributes); +begin + fSymblAttrib.Assign(value); +end; + +procedure TSynSxSyn.setIdentAttrib(value: TSynHighlighterAttributes); +begin + fIdentAttrib.Assign(value); +end; + +procedure TSynSxSyn.setCommtAttrib(value: TSynHighlighterAttributes); +begin + fCommtAttrib.Assign(value); +end; + +procedure TSynSxSyn.setStrngAttrib(value: TSynHighlighterAttributes); +begin + fStrngAttrib.Assign(value); +end; + +procedure TSynSxSyn.setKeywdAttrib(value: TSynHighlighterAttributes); +begin + fKeywdAttrib.Assign(value); +end; + +procedure TSynSxSyn.setAttriAttrib(value: TSynHighlighterAttributes); +begin + fAttriAttrib.Assign(value); +end; + +procedure TSynSxSyn.setErrorAttrib(value: TSynHighlighterAttributes); +begin + fErrorAttrib.Assign(value); +end; + +function TSynSxSyn.GetTokenAttribute: TSynHighlighterAttributes; +begin + result := fAttribLut[fTokKind]; +end; + +procedure TSynSxSyn.SetRange(value: Pointer); +var + stored: TSynSxSynRange; +begin + inherited SetRange(value); + stored := TSynSxSynRange(CodeFoldRange.RangeType); + if fCurrRange.isAssigned and stored.isAssigned then + fCurrRange.copyFrom(stored); +end; + +function TSynSxSyn.GetRange: Pointer; +var + stored: TSynSxSynRange; +begin + stored := TSynSxSynRange(inherited GetRange); + if stored.isNotAssigned then + stored := TSynSxSynRange.Create(nil); + stored.copyFrom(fCurrRange); + + CodeFoldRange.RangeType := Pointer(stored); + Result := inherited GetRange; +end; + +procedure TSynSxSyn.ResetRange; +begin + if fCurrRange.isNotAssigned then + fCurrRange := TSynSxSynRange.Create(nil) + else + fCurrRange.Clear; +end; + +procedure TSynSxSyn.setLine(const NewValue: string; LineNumber: Integer); +begin + inherited; + fLineBuf := NewValue; + fLineNum := LineNumber; + fTokStop := 1; + next; +end; + +function TSynSxSyn.GetEol: Boolean; +begin + result := fTokKind = tkNone; +end; + +function TSynSxSyn.GetTokenPos: Integer; +begin + result := fTokStart - 1; +end; + +function TSynSxSyn.GetToken: string; +begin + result := copy(fLineBuf, FTokStart, fTokStop - FTokStart); +end; + +procedure TSynSxSyn.GetTokenEx(out TokenStart: PChar; out TokenLength: integer); +begin + TokenStart := @fLineBuf[FTokStart]; + TokenLength := fTokStop - FTokStart; +end; + +function TSynSxSyn.GetDefaultAttribute(Index: integer): TSynHighlighterAttributes; +begin + result := nil; +end; + +function TSynSxSyn.GetTokenKind: integer; +begin + Result := Integer(fTokKind); +end; + +function TSynSxSyn.safeLookupChar: PChar; +begin + if fTokStop >= length(fLineBuf) then + result := nil + else result := @fLineBuf[fTokStop + 1]; +end; + +function TSynSxSyn.canLookup2Char(): boolean; +begin + result := fTokStop + 2 <= length(fLineBuf); +end; + +procedure TSynSxSyn.lexOpAndOpEqual(); +var + nextPChar: PChar; + nextChar: char; +begin + fTokKind := TTokenKind.tkSymbl; + nextPChar := safeLookupChar(); + if nextPChar <> nil then + begin + nextChar := nextPChar^; + if nextChar = '=' then + fTokStop += 1; + end; + fTokStop += 1; +end; + +procedure TSynSxSyn.lexOpAndOpOpAndOpEqual(const op: char); +var + nextPChar: PChar; + nextChar: char; +begin + fTokKind := TTokenKind.tkSymbl; + nextPChar := safeLookupChar(); + if nextPChar <> nil then + begin + nextChar := fLineBuf[fTokStop]; + if (nextChar = op) or (nextChar = '=') then + fTokStop += 1; + end; + fTokStop += 1; +end; + +procedure TSynSxSyn.lexOpAndOpOpAndOpEqualAndOpOpEqual(const op: char); +var + nextPChar: PChar; + nextChar: char; + can2: boolean; +begin + fTokKind := TTokenKind.tkSymbl; + can2 := canLookup2Char(); + nextPChar := safeLookupChar(); + // <<= + if can2 and (fLineBuf[fTokStop + 1] = op) and (fLineBuf[fTokStop+2] = '=') then + fTokStop += 2 + else if nextPChar <> nil then + begin + nextChar := nextPChar^; + // << or <= + if (nextChar = op) or (nextChar = '=') then + fTokStop += 1; + end; + fTokStop += 1; +end; + +procedure TSynSxSyn.lexAssEquOrLambda(); +var + nextPChar: PChar; + nextChar: char; +begin + fTokKind := TTokenKind.tkSymbl; + nextPChar := safeLookupChar(); + if nextPChar <> nil then + begin + nextChar := fLineBuf[fTokStop]; + if (nextChar = '=') or (nextChar = '>') then + fTokStop += 1; + end; + fTokStop += 1; +end; + +procedure TSynSxSyn.lexIntLiteral(); +var + nextPChar: PChar; + nextChar: char; +begin + fTokKind:=TTokenKind.tkNumbr; + while fTokStop <= fLineBuf.length do + begin + case fLineBuf[fTokStop] of + '0'..'9', '_': + begin + fTokStop += 1; + continue; + end; + '.': + begin + nextPChar := safeLookupChar(); + if nextPChar <> nil then + begin + nextChar := nextPChar^; + if nextChar in ['0' .. '9'] then + begin + fTokStop += 1; + lexFloatingLiteralFractionalPart(); + exit; + end; + end; + break; + end; + end; + break; + end; +end; + +procedure TSynSxSyn.lexFloatingLiteralFractionalPart(); +begin + fTokKind:=TTokenKind.tkNumbr; + while fTokStop <= fLineBuf.length do + begin + case fLineBuf[fTokStop] of + '0'..'9', '_': fTokStop += 1; + 'e', 'E': + begin + lexExponent(); + exit; + end + else break; + end; + end; +end; + +procedure TSynSxSyn.lexExponent(); +begin + fTokStop += 1; + if fTokStop > fLineBuf.length then + begin + fTokKind:=TTokenKind.tkError; + exit; + end; + if fLineBuf[fTokStop] in ['+', '-'] then + fTokStop += 1; + if fTokStop > fLineBuf.length then + begin + fTokKind:=TTokenKind.tkError; + exit; + end; + while fTokStop <= fLineBuf.length do + begin + if fLineBuf[fTokStop] in ['0' .. '9'] then + begin + fTokStop += 1; + continue; + end else + break; + end; +end; + +procedure TSynSxSyn.lexHexLiteral(); +begin + fTokStop += 2; + fTokKind:=TTokenKind.tkNumbr; + while fTokStop <= fLineBuf.length do + begin + case fLineBuf[fTokStop] of + '0'..'9', 'a'..'f', 'A'..'F', '_': + begin + fTokStop += 1; + continue; + end + else while (fTokStop <= fLineBuf.length) and + (fLineBuf[fTokStop] in ['g' .. 'z', 'G' .. 'Z']) do + begin + fTokKind := TTokenKind.tkError; + fTokStop += 1; + end; + end; + break; + end; +end; + +procedure TSynSxSyn.lexBinLiteral(); +begin + fTokStop += 2; + fTokKind:=TTokenKind.tkNumbr; + while fTokStop <= fLineBuf.length do + begin + case fLineBuf[fTokStop] of + '0', '1', '_': + begin + fTokStop += 1; + continue; + end; + else while (fTokStop <= fLineBuf.length) and + (fLineBuf[fTokStop] in ['2' .. '9', 'a' .. 'z', 'A' .. 'Z']) do + begin + fTokKind := TTokenKind.tkError; + fTokStop += 1; + end; + end; + break; + end; +end; + +procedure TSynSxSyn.lexStringLiteral(); +var + firstLine: Boolean; + terminate: Boolean = false; +begin + fTokKind := TTokenKind.tkStrng; + firstLine := fCurrRange.rangeKind = TRangeKind.rkNone; + if firstLine then + fTokStop += 1; + while fTokStop <= fLineBuf.length do + begin + case fLineBuf[fTokStop] of + '\' : fTokStop += 2; + '"' : + begin + fTokStop += 1; + terminate := true; + break; + end + else fTokStop += 1; + end; + end; + if firstLine and not terminate then + fCurrRange.rangeKind:= TRangeKind.rkString1 + else if (fCurrRange.rangeKind = TRangeKind.rkString1) and terminate then + fCurrRange.rangeKind:= TRangeKind.rkNone; +end; + +procedure TSynSxSyn.lexRawStringLiteral(); +var + firstLine: Boolean; + terminate: Boolean = false; +begin + fTokKind := TTokenKind.tkStrng; + firstLine := fCurrRange.rangeKind = TRangeKind.rkNone; + if firstLine then + fTokStop += 1; + while fTokStop <= fLineBuf.length do + begin + if fLineBuf[fTokStop] = '`' then + begin + fTokStop += 1; + terminate := true; + break; + end + else fTokStop += 1; + end; + if firstLine and not terminate then + fCurrRange.rangeKind:= TRangeKind.rkString2 + else if (fCurrRange.rangeKind = TRangeKind.rkString2) and terminate then + fCurrRange.rangeKind:= TRangeKind.rkNone; +end; + +procedure TSynSxSyn.lexLineComment(); +begin + fTokKind := TTokenKind.tkCommt; + fTokStop := fLineBuf.length + 1; +end; + +procedure TSynSxSyn.lexStarComment(); +var + firstLine: Boolean; + terminate: Boolean = false; +begin + fTokKind := TTokenKind.tkCommt; + firstLine := fCurrRange.rangeKind = TRangeKind.rkNone; + while fTokStop <= fLineBuf.length do + begin + if fLineBuf[fTokStop] = '*' then + begin + fTokStop += 1; + if (fTokStop <= fLineBuf.length) and (fLineBuf[fTokStop] = '/') then + begin + fTokStop += 1; + terminate := true; + break; + end; + end + else fTokStop += 1; + end; + if firstLine and not terminate then + fCurrRange.rangeKind := TRangeKind.rkBlockCom1 + else if (fCurrRange.rangeKind = TRangeKind.rkBlockCom1) and terminate then + fCurrRange.rangeKind := TRangeKind.rkNone; +end; + +procedure TSynSxSyn.lexIdentifier(); +var + dollar: boolean; + oneChr: boolean = false; +begin + fTokKind := TTokenKind.tkIdent; + dollar := fLineBuf[fTokStop] = '$'; + if dollar then + fTokStop += 1; + while fTokStop <= fLineBuf.length do + begin + case fLineBuf[fTokStop] of + '_', 'a'..'z', 'A'..'Z': + begin + oneChr := true; + fTokStop += 1; + continue; + end; + '0' .. '9': + begin + if oneChr then + begin + fTokStop += 1; + continue; + end + else break; // e.g $0 + end + else break; + end; + end; + if dollar and not oneChr then + fTokKind := TTokenKind.tkError + else + begin + if KeywordMatch.contains(GetToken()) then + fTokKind := TTokenKind.tkKeywd; + end; +end; + +procedure TSynSxSyn.next; +var + llen: integer; + nextPChar: PChar; + nextChar: char; +begin + fTokKind := tkNone; + fTokStart := fTokStop; + llen := length(fLineBuf); + // EOL + if fTokStop > llen then + exit; + if fCurrRange.isNotAssigned then + fCurrRange := TSynSxSynRange.Create(nil); + + if (fLineBuf.length > 1) then + begin + // she bang + if (fLineNum = 0) and (fLineBuf[1..2] = '#!') then + begin + lexLineComment(); + exit; + end + // "ยง" of SAR + else if (fTokStart = 1) and (fLineBuf[1..2] = #194#167) then + begin + lexLineComment(); + exit; + end; + end; + + case fCurrRange.rangeKind of + TRangeKind.rkString1: begin lexStringLiteral(); exit; end; + TRangeKind.rkString2: begin lexRawStringLiteral(); exit; end; + TRangeKind.rkBlockCom1: begin lexStarComment(); exit; end; + end; + + case fLineBuf[fTokStop] of + #0 .. #10, #13, #32: + begin + fTokStop += 1; + fTokKind := TTokenKind.tkBlank; + exit; + end; + // `//comment` `/*comment` `/=` `/` + '/': + begin + fTokKind := TTokenKind.tkSymbl; + fTokStop += 1; + if (fTokStop <= llen) then + case fLineBuf[fTokStop] of + '/' : lexLineComment(); + '*' : begin fTokStop += 1; lexStarComment(); end; + '=' : fTokStop += 1; + end; + end; + // `_ident` `$kwIdent` + 'a'..'z', 'A'..'Z', '_', '$': lexIdentifier(); + // `0x...` `0b...` `012...` `0.12...` `012...` + '0': + begin + nextPChar := safeLookupChar(); + if nextPChar <> nil then + begin + nextChar := nextPChar^; + if (nextChar = 'x') or (nextChar = 'X') then + lexHexLiteral() + else if (nextChar = 'b') or (nextChar = 'B') then + lexBinLiteral() + else lexIntLiteral(); + end + else lexIntLiteral(); + end; + // number + '1' .. '9' : lexIntLiteral(); + // "string" + '"': lexStringLiteral(); + // `string` + '`': lexRawStringLiteral(); + // `-` `-=` `--` + '-': lexOpAndOpOpAndOpEqual('-'); + // `&` `&=` `&&` + '&': lexOpAndOpOpAndOpEqual('&'); + // `|` `|=` `||` + '|': lexOpAndOpOpAndOpEqual('|'); + // `+` `+=` `++` + '+': lexOpAndOpOpAndOpEqual('+'); + // `*` `*=` `%` `%=` `^` `^=` `~` `~=` `!` `!=` + '*', '%', '^', '!', '~': lexOpAndOpEqual(); + // `<` `<<` `<=` `<<=` `>` `>>` `>=` `>>=` + '<': lexOpAndOpOpAndOpEqualAndOpOpEqual('<'); + '>': lexOpAndOpOpAndOpEqualAndOpOpEqual('>'); + // `=`, `==`, `=>` + '=': lexAssEquOrLambda(); + '.', '(', ')', ',', ':' , '[', ']', '?', ';' : + begin + fTokKind := TTokenKind.tkSymbl; + fTokStop += 1; + end; + '@': + begin + fTokKind := TTokenKind.tkError; + fTokStop += 1; + if fTokStop <= llen then + begin + lexIdentifier(); + fTokKind := TTokenKind.tkAttri; + end; + end; + '{': + begin + fTokKind := TTokenKind.tkSymbl; + fTokStop += 1; + StartCodeFoldBlock(); + end; + '}': + begin + fTokKind := TTokenKind.tkSymbl; + fTokStop += 1; + EndCodeFoldBlock(); + end + else begin + fTokStop += 1; + fTokKind := TTokenKind.tkError; + exit; + end; + end; +end; + +end. + diff --git a/src/u_synmemo.pas b/src/u_synmemo.pas index d6da536f..9d136a90 100644 --- a/src/u_synmemo.pas +++ b/src/u_synmemo.pas @@ -13,7 +13,7 @@ uses SynGutterBase, LCLVersion, //SynEditMarkupFoldColoring, Clipbrd, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls, - u_common, u_writableComponent, u_d2syn, u_txtsyn, u_dialogs, + u_common, u_writableComponent, u_d2syn, u_txtsyn, u_dialogs, u_sxsyn, u_sharedres, u_dlang, u_stringrange, u_dbgitf, u_observer, u_diff, u_processes, u_synmultiguttermarks; @@ -222,6 +222,7 @@ type fD2Highlighter: TSynD2Syn; fTxtHighlighter: TSynTxtSyn; fCppHighlighter: TSynCppSyn; + fSxHighlighter: TSynSxSyn; fImages: TImageList; fMatchSelectionOpts: TSynSearchOptions; fMatchIdentOpts: TSynSearchOptions; @@ -402,6 +403,7 @@ type property D2Highlighter: TSynD2Syn read fD2Highlighter; property TxtHighlighter: TSynTxtSyn read fTxtHighlighter; property CppHighlighter: TSynCppSyn read fCppHighlighter; + property SxHighlighter: TSynSxSyn read fSxHighlighter; property defaultFontSize: Integer read fDefaultFontSize write setDefaultFontSize; property ddocDelay: Integer read fDDocDelay write setDDocDelay; property autoDotDelay: Integer read fAutoDotDelay write setAutoDotDelay; @@ -1162,6 +1164,7 @@ begin fD2Highlighter := TSynD2Syn.create(self); fTxtHighlighter := TSynTxtSyn.Create(self); fCppHighlighter := TSynCppSyn.Create(self); + fSxHighlighter := TSynSxSyn.Create(self); Highlighter := fD2Highlighter; fTempFileName := GetTempDir(false) + 'temp_' + uniqueObjStr(self) + '.d'; @@ -3350,14 +3353,18 @@ procedure TDexedMemo.loadFromFile(const fname: string); var e: string; c: boolean; + s: boolean; begin e := fname.extractFileExt; fIsDsource := hasDlangSyntax(e); c := hasCppSyntax(e); + s := hasSxSyntax(e); if not fIsDsource then begin if c then Highlighter := CppHighlighter + else if s then + Highlighter := SxHighlighter else Highlighter := TxtSyn; end; @@ -3399,6 +3406,8 @@ begin begin if hasCppSyntax(ext) then Highlighter := CppHighlighter + else if hasSxSyntax(ext) then + Highlighter := SxHighlighter else Highlighter := TxtHighlighter; end;