1 // SciTE - Scintilla based Text Editor
2 // LexCPP.cxx - lexer for C++, C, Java, and Javascript
3 // Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
4 // The License.txt file describes the conditions under which this software may be distributed.
17 #include "Scintilla.h"
20 static bool classifyWordCpp(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
22 for (unsigned int i
= 0; i
< end
- start
+ 1 && i
< 30; i
++) {
23 s
[i
] = styler
[start
+ i
];
26 bool wordIsUUID
= false;
27 char chAttr
= SCE_C_IDENTIFIER
;
28 if (isdigit(s
[0]) || (s
[0] == '.'))
29 chAttr
= SCE_C_NUMBER
;
31 if (keywords
.InList(s
)) {
33 wordIsUUID
= strcmp(s
, "uuid") == 0;
36 styler
.ColourTo(end
, chAttr
);
40 static void ColouriseCppDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
43 WordList
&keywords
= *keywordlists
[0];
45 styler
.StartAt(startPos
);
47 bool fold
= styler
.GetPropertyInt("fold");
48 bool stylingWithinPreprocessor
= styler
.GetPropertyInt("styling.within.preprocessor");
49 int lineCurrent
= styler
.GetLine(startPos
);
50 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
51 int levelCurrent
= levelPrev
;
53 int state
= initStyle
;
54 if (state
== SCE_C_STRINGEOL
) // Does not leak onto next line
55 state
= SCE_C_DEFAULT
;
57 char chNext
= styler
[startPos
];
58 unsigned int lengthDoc
= startPos
+ length
;
60 styler
.StartSegment(startPos
);
61 bool lastWordWasUUID
= false;
62 for (unsigned int i
= startPos
; i
< lengthDoc
; i
++) {
64 chNext
= styler
.SafeGetCharAt(i
+ 1);
66 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n')) {
67 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
68 // Avoid triggering two times on Dos/Win
70 if (state
== SCE_C_STRINGEOL
) {
71 styler
.ColourTo(i
, state
);
72 state
= SCE_C_DEFAULT
;
76 if (visibleChars
== 0)
77 lev
|= SC_FOLDLEVELWHITEFLAG
;
78 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
79 lev
|= SC_FOLDLEVELHEADERFLAG
;
80 styler
.SetLevel(lineCurrent
, lev
);
82 levelPrev
= levelCurrent
;
89 if (styler
.IsLeadByte(ch
)) {
90 chNext
= styler
.SafeGetCharAt(i
+ 2);
96 if (state
== SCE_C_DEFAULT
) {
97 if (ch
== '@' && chNext
== '\"') {
98 styler
.ColourTo(i
-1, state
);
99 state
= SCE_C_VERBATIM
;
102 chNext
= styler
.SafeGetCharAt(i
+ 1);
103 } else if (iswordstart(ch
) || (ch
== '@')) {
104 styler
.ColourTo(i
-1, state
);
105 if (lastWordWasUUID
) {
107 lastWordWasUUID
= false;
109 state
= SCE_C_IDENTIFIER
;
111 } else if (ch
== '/' && chNext
== '*') {
112 styler
.ColourTo(i
-1, state
);
113 if (styler
.SafeGetCharAt(i
+ 2) == '*')
114 state
= SCE_C_COMMENTDOC
;
116 state
= SCE_C_COMMENT
;
117 } else if (ch
== '/' && chNext
== '/') {
118 styler
.ColourTo(i
-1, state
);
119 state
= SCE_C_COMMENTLINE
;
120 } else if (ch
== '\"') {
121 styler
.ColourTo(i
-1, state
);
122 state
= SCE_C_STRING
;
123 } else if (ch
== '\'') {
124 styler
.ColourTo(i
-1, state
);
125 state
= SCE_C_CHARACTER
;
126 } else if (ch
== '#' && visibleChars
== 1) {
127 // Preprocessor commands are alone on their line
128 styler
.ColourTo(i
-1, state
);
129 state
= SCE_C_PREPROCESSOR
;
130 // Skip whitespace between # and preprocessor word
134 chNext
= styler
.SafeGetCharAt(i
+ 1);
135 } while (isspace(ch
) && (i
< lengthDoc
));
136 } else if (isoperator(ch
)) {
137 styler
.ColourTo(i
-1, state
);
138 styler
.ColourTo(i
, SCE_C_OPERATOR
);
139 if ((ch
== '{') || (ch
== '}')) {
140 levelCurrent
+= (ch
== '{') ? 1 : -1;
143 } else if (state
== SCE_C_IDENTIFIER
) {
144 if (!iswordchar(ch
)) {
145 lastWordWasUUID
= classifyWordCpp(styler
.GetStartSegment(), i
- 1, keywords
, styler
);
146 state
= SCE_C_DEFAULT
;
147 if (ch
== '/' && chNext
== '*') {
148 if (styler
.SafeGetCharAt(i
+ 2) == '*')
149 state
= SCE_C_COMMENTDOC
;
151 state
= SCE_C_COMMENT
;
152 } else if (ch
== '/' && chNext
== '/') {
153 state
= SCE_C_COMMENTLINE
;
154 } else if (ch
== '\"') {
155 state
= SCE_C_STRING
;
156 } else if (ch
== '\'') {
157 state
= SCE_C_CHARACTER
;
158 } else if (isoperator(ch
)) {
159 styler
.ColourTo(i
, SCE_C_OPERATOR
);
160 if ((ch
== '{') || (ch
== '}')) {
161 levelCurrent
+= (ch
== '{') ? 1 : -1;
166 if (state
== SCE_C_PREPROCESSOR
) {
167 if (stylingWithinPreprocessor
) {
169 styler
.ColourTo(i
-1, state
);
170 state
= SCE_C_DEFAULT
;
173 if ((ch
== '\r' || ch
== '\n') && !(chPrev
== '\\' || chPrev
== '\r')) {
174 styler
.ColourTo(i
-1, state
);
175 state
= SCE_C_DEFAULT
;
178 } else if (state
== SCE_C_COMMENT
) {
179 if (ch
== '/' && chPrev
== '*') {
180 if (((i
> styler
.GetStartSegment() + 2) || (
181 (initStyle
== SCE_C_COMMENT
) &&
182 (styler
.GetStartSegment() == static_cast<unsigned int>(startPos
))))) {
183 styler
.ColourTo(i
, state
);
184 state
= SCE_C_DEFAULT
;
187 } else if (state
== SCE_C_COMMENTDOC
) {
188 if (ch
== '/' && chPrev
== '*') {
189 if (((i
> styler
.GetStartSegment() + 2) || (
190 (initStyle
== SCE_C_COMMENTDOC
) &&
191 (styler
.GetStartSegment() == static_cast<unsigned int>(startPos
))))) {
192 styler
.ColourTo(i
, state
);
193 state
= SCE_C_DEFAULT
;
196 } else if (state
== SCE_C_COMMENTLINE
) {
197 if (ch
== '\r' || ch
== '\n') {
198 styler
.ColourTo(i
-1, state
);
199 state
= SCE_C_DEFAULT
;
201 } else if (state
== SCE_C_STRING
) {
203 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
206 chNext
= styler
.SafeGetCharAt(i
+ 1);
208 } else if (ch
== '\"') {
209 styler
.ColourTo(i
, state
);
210 state
= SCE_C_DEFAULT
;
211 } else if (chNext
== '\r' || chNext
== '\n') {
212 styler
.ColourTo(i
-1, SCE_C_STRINGEOL
);
213 state
= SCE_C_STRINGEOL
;
215 } else if (state
== SCE_C_CHARACTER
) {
216 if ((ch
== '\r' || ch
== '\n') && (chPrev
!= '\\')) {
217 styler
.ColourTo(i
-1, SCE_C_STRINGEOL
);
218 state
= SCE_C_STRINGEOL
;
219 } else if (ch
== '\\') {
220 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
223 chNext
= styler
.SafeGetCharAt(i
+ 1);
225 } else if (ch
== '\'') {
226 styler
.ColourTo(i
, state
);
227 state
= SCE_C_DEFAULT
;
229 } else if (state
== SCE_C_VERBATIM
) {
231 if (chNext
== '\"') {
234 chNext
= styler
.SafeGetCharAt(i
+ 1);
236 styler
.ColourTo(i
, state
);
237 state
= SCE_C_DEFAULT
;
240 } else if (state
== SCE_C_UUID
) {
241 if (ch
== '\r' || ch
== '\n' || ch
== ')') {
242 styler
.ColourTo(i
-1, state
);
244 styler
.ColourTo(i
, SCE_C_OPERATOR
);
245 state
= SCE_C_DEFAULT
;
251 styler
.ColourTo(lengthDoc
- 1, state
);
253 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
255 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
256 //styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
257 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
262 LexerModule
lmCPP(SCLEX_CPP
, ColouriseCppDoc
);