1 // Scintilla source code edit control
4 ** Based on LexPascal.cxx
5 ** Written by Laurent le Tynevez
6 ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
7 ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
8 ** Updated by Rod Falck, Aug 2006 Converted to TACL
19 #include "Scintilla.h"
23 #include "LexAccessor.h"
25 #include "StyleContext.h"
26 #include "CharacterSet.h"
27 #include "LexerModule.h"
30 using namespace Scintilla
;
33 inline bool isTACLoperator(char ch
)
35 return ch
== '\'' || isoperator(ch
);
38 inline bool isTACLwordchar(char ch
)
40 return ch
== '#' || ch
== '^' || ch
== '|' || ch
== '_' || iswordchar(ch
);
43 inline bool isTACLwordstart(char ch
)
45 return ch
== '#' || ch
== '|' || ch
== '_' || iswordstart(ch
);
48 static void getRange(unsigned int start
,
54 while ((i
< end
- start
+ 1) && (i
< len
-1)) {
55 s
[i
] = static_cast<char>(tolower(styler
[start
+ i
]));
61 static bool IsStreamCommentStyle(int style
) {
62 return style
== SCE_C_COMMENT
||
63 style
== SCE_C_COMMENTDOC
||
64 style
== SCE_C_COMMENTDOCKEYWORD
||
65 style
== SCE_C_COMMENTDOCKEYWORDERROR
;
68 static void ColourTo(Accessor
&styler
, unsigned int end
, unsigned int attr
, bool bInAsm
) {
69 if ((bInAsm
) && (attr
== SCE_C_OPERATOR
|| attr
== SCE_C_NUMBER
|| attr
== SCE_C_DEFAULT
|| attr
== SCE_C_WORD
|| attr
== SCE_C_IDENTIFIER
)) {
70 styler
.ColourTo(end
, SCE_C_REGEX
);
72 styler
.ColourTo(end
, attr
);
75 // returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm"
76 static int classifyWordTACL(unsigned int start
, unsigned int end
, /*WordList &keywords*/WordList
*keywordlists
[], Accessor
&styler
, bool bInAsm
) {
79 WordList
& keywords
= *keywordlists
[0];
80 WordList
& builtins
= *keywordlists
[1];
81 WordList
& commands
= *keywordlists
[2];
84 getRange(start
, end
, styler
, s
, sizeof(s
));
86 char chAttr
= SCE_C_IDENTIFIER
;
87 if (isdigit(s
[0]) || (s
[0] == '.')) {
88 chAttr
= SCE_C_NUMBER
;
91 if (s
[0] == '#' || keywords
.InList(s
)) {
94 if (strcmp(s
, "asm") == 0) {
97 else if (strcmp(s
, "end") == 0) {
101 else if (s
[0] == '|' || builtins
.InList(s
)) {
102 chAttr
= SCE_C_WORD2
;
104 else if (commands
.InList(s
)) {
107 else if (strcmp(s
, "comment") == 0) {
108 chAttr
= SCE_C_COMMENTLINE
;
112 ColourTo(styler
, end
, chAttr
, (bInAsm
&& ret
!= -1));
116 static int classifyFoldPointTACL(const char* s
) {
120 else if (s
[0] == ']')
125 static void ColouriseTACLDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
128 styler
.StartAt(startPos
);
130 int state
= initStyle
;
131 if (state
== SCE_C_CHARACTER
) // Does not leak onto next line
132 state
= SCE_C_DEFAULT
;
134 char chNext
= styler
[startPos
];
135 unsigned int lengthDoc
= startPos
+ length
;
137 bool bInClassDefinition
;
139 int currentLine
= styler
.GetLine(startPos
);
140 if (currentLine
> 0) {
141 styler
.SetLineState(currentLine
, styler
.GetLineState(currentLine
-1));
142 bInClassDefinition
= (styler
.GetLineState(currentLine
) == 1);
144 styler
.SetLineState(currentLine
, 0);
145 bInClassDefinition
= false;
148 bool bInAsm
= (state
== SCE_C_REGEX
);
150 state
= SCE_C_DEFAULT
;
152 styler
.StartSegment(startPos
);
153 int visibleChars
= 0;
155 for (i
= startPos
; i
< lengthDoc
; i
++) {
158 chNext
= styler
.SafeGetCharAt(i
+ 1);
160 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n')) {
161 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
162 // Avoid triggering two times on Dos/Win
164 if (state
== SCE_C_CHARACTER
) {
165 ColourTo(styler
, i
, state
, bInAsm
);
166 state
= SCE_C_DEFAULT
;
170 styler
.SetLineState(currentLine
, (bInClassDefinition
? 1 : 0));
173 if (styler
.IsLeadByte(ch
)) {
174 chNext
= styler
.SafeGetCharAt(i
+ 2);
180 if (state
== SCE_C_DEFAULT
) {
181 if (isTACLwordstart(ch
)) {
182 ColourTo(styler
, i
-1, state
, bInAsm
);
183 state
= SCE_C_IDENTIFIER
;
184 } else if (ch
== '{') {
185 ColourTo(styler
, i
-1, state
, bInAsm
);
186 state
= SCE_C_COMMENT
;
187 } else if (ch
== '{' && chNext
== '*') {
188 ColourTo(styler
, i
-1, state
, bInAsm
);
189 state
= SCE_C_COMMENTDOC
;
190 } else if (ch
== '=' && chNext
== '=') {
191 ColourTo(styler
, i
-1, state
, bInAsm
);
192 state
= SCE_C_COMMENTLINE
;
193 } else if (ch
== '"') {
194 ColourTo(styler
, i
-1, state
, bInAsm
);
195 state
= SCE_C_STRING
;
196 } else if (ch
== '?' && visibleChars
== 0) {
197 ColourTo(styler
, i
-1, state
, bInAsm
);
198 state
= SCE_C_PREPROCESSOR
;
199 } else if (isTACLoperator(ch
)) {
200 ColourTo(styler
, i
-1, state
, bInAsm
);
201 ColourTo(styler
, i
, SCE_C_OPERATOR
, bInAsm
);
203 } else if (state
== SCE_C_IDENTIFIER
) {
204 if (!isTACLwordchar(ch
)) {
205 int lStateChange
= classifyWordTACL(styler
.GetStartSegment(), i
- 1, keywordlists
, styler
, bInAsm
);
207 if(lStateChange
== 1) {
208 styler
.SetLineState(currentLine
, 1);
209 bInClassDefinition
= true;
210 } else if(lStateChange
== 2) {
212 } else if(lStateChange
== -1) {
213 styler
.SetLineState(currentLine
, 0);
214 bInClassDefinition
= false;
218 if (lStateChange
== 3) {
219 state
= SCE_C_COMMENTLINE
;
222 state
= SCE_C_DEFAULT
;
223 chNext
= styler
.SafeGetCharAt(i
+ 1);
225 state
= SCE_C_COMMENT
;
226 } else if (ch
== '{' && chNext
== '*') {
227 ColourTo(styler
, i
-1, state
, bInAsm
);
228 state
= SCE_C_COMMENTDOC
;
229 } else if (ch
== '=' && chNext
== '=') {
230 state
= SCE_C_COMMENTLINE
;
231 } else if (ch
== '"') {
232 state
= SCE_C_STRING
;
233 } else if (isTACLoperator(ch
)) {
234 ColourTo(styler
, i
, SCE_C_OPERATOR
, bInAsm
);
239 if (state
== SCE_C_PREPROCESSOR
) {
240 if ((ch
== '\r' || ch
== '\n') && !(chPrev
== '\\' || chPrev
== '\r')) {
241 ColourTo(styler
, i
-1, state
, bInAsm
);
242 state
= SCE_C_DEFAULT
;
244 } else if (state
== SCE_C_COMMENT
) {
245 if (ch
== '}' || (ch
== '\r' || ch
== '\n') ) {
246 ColourTo(styler
, i
, state
, bInAsm
);
247 state
= SCE_C_DEFAULT
;
249 } else if (state
== SCE_C_COMMENTDOC
) {
250 if (ch
== '}' || (ch
== '\r' || ch
== '\n')) {
251 if (((i
> styler
.GetStartSegment() + 2) || (
252 (initStyle
== SCE_C_COMMENTDOC
) &&
253 (styler
.GetStartSegment() == static_cast<unsigned int>(startPos
))))) {
254 ColourTo(styler
, i
, state
, bInAsm
);
255 state
= SCE_C_DEFAULT
;
258 } else if (state
== SCE_C_COMMENTLINE
) {
259 if (ch
== '\r' || ch
== '\n') {
260 ColourTo(styler
, i
-1, state
, bInAsm
);
261 state
= SCE_C_DEFAULT
;
263 } else if (state
== SCE_C_STRING
) {
264 if (ch
== '"' || ch
== '\r' || ch
== '\n') {
265 ColourTo(styler
, i
, state
, bInAsm
);
266 state
= SCE_C_DEFAULT
;
270 if (!isspacechar(ch
))
275 // Process to end of document
276 if (state
== SCE_C_IDENTIFIER
) {
277 classifyWordTACL(styler
.GetStartSegment(), i
- 1, keywordlists
, styler
, bInAsm
);
280 ColourTo(styler
, lengthDoc
- 1, state
, bInAsm
);
283 static void FoldTACLDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*[],
285 bool foldComment
= styler
.GetPropertyInt("fold.comment") != 0;
286 bool foldPreprocessor
= styler
.GetPropertyInt("fold.preprocessor") != 0;
287 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
288 unsigned int endPos
= startPos
+ length
;
289 int visibleChars
= 0;
290 int lineCurrent
= styler
.GetLine(startPos
);
291 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
292 int levelCurrent
= levelPrev
;
293 char chNext
= styler
[startPos
];
294 int styleNext
= styler
.StyleAt(startPos
);
295 int style
= initStyle
;
296 bool section
= false;
300 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
302 chNext
= styler
.SafeGetCharAt(i
+ 1);
303 int stylePrev
= style
;
305 styleNext
= styler
.StyleAt(i
+ 1);
306 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
308 if (stylePrev
== SCE_C_DEFAULT
&& (style
== SCE_C_WORD
|| style
== SCE_C_PREPROCESSOR
))
310 // Store last word start point.
314 if (stylePrev
== SCE_C_WORD
|| stylePrev
== SCE_C_PREPROCESSOR
) {
315 if(isTACLwordchar(ch
) && !isTACLwordchar(chNext
)) {
317 getRange(lastStart
, i
, styler
, s
, sizeof(s
));
318 if (stylePrev
== SCE_C_PREPROCESSOR
&& strcmp(s
, "?section") == 0)
324 else if (stylePrev
== SCE_C_WORD
)
325 levelCurrent
+= classifyFoldPointTACL(s
);
329 if (style
== SCE_C_OPERATOR
) {
332 } else if (ch
== ']') {
336 if (foldComment
&& (style
== SCE_C_COMMENTLINE
)) {
337 if ((ch
== '/') && (chNext
== '/')) {
338 char chNext2
= styler
.SafeGetCharAt(i
+ 2);
339 if (chNext2
== '{') {
341 } else if (chNext2
== '}') {
347 if (foldPreprocessor
&& (style
== SCE_C_PREPROCESSOR
)) {
348 if (ch
== '{' && chNext
== '$') {
349 unsigned int j
=i
+2; // skip {$
350 while ((j
<endPos
) && IsASpaceOrTab(styler
.SafeGetCharAt(j
))) {
353 if (styler
.Match(j
, "region") || styler
.Match(j
, "if")) {
355 } else if (styler
.Match(j
, "end")) {
361 if (foldComment
&& IsStreamCommentStyle(style
)) {
362 if (!IsStreamCommentStyle(stylePrev
)) {
364 } else if (!IsStreamCommentStyle(styleNext
) && !atEOL
) {
365 // Comments don't end at end of line and the next character may be unstyled.
370 int lev
= levelPrev
| SC_FOLDLEVELBASE
;
371 if (visibleChars
== 0 && foldCompact
)
372 lev
|= SC_FOLDLEVELWHITEFLAG
;
373 if ((levelCurrent
> levelPrev
|| section
) && (visibleChars
> 0))
374 lev
|= SC_FOLDLEVELHEADERFLAG
;
375 if (lev
!= styler
.LevelAt(lineCurrent
)) {
376 styler
.SetLevel(lineCurrent
, lev
);
379 levelPrev
= levelCurrent
;
384 if (!isspacechar(ch
))
388 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
389 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
390 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
393 static const char * const TACLWordListDesc
[] = {
400 LexerModule
lmTACL(SCLEX_TACL
, ColouriseTACLDoc
, "TACL", FoldTACLDoc
, TACLWordListDesc
);