]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexEiffel.cxx
1296fb24506c7787775d2776b5c4201dfedbd6da
1 // Scintilla source code edit control
2 /** @file LexEiffel.cxx
5 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
20 #include "Scintilla.h"
23 inline bool isEiffelOperator(unsigned int ch
) {
24 // '.' left out as it is used to make up numbers
25 return ch
== '*' || ch
== '/' || ch
== '\\' || ch
== '-' || ch
== '+' ||
26 ch
== '(' || ch
== ')' || ch
== '=' ||
27 ch
== '{' || ch
== '}' || ch
== '~' ||
28 ch
== '[' || ch
== ']' || ch
== ';' ||
29 ch
== '<' || ch
== '>' || ch
== ',' ||
30 ch
== '.' || ch
== '^' || ch
== '%' || ch
== ':' ||
31 ch
== '!' || ch
== '@' || ch
== '?';
34 static void getRangeLowered(unsigned int start
,
40 while ((i
< end
- start
+ 1) && (i
< len
-1)) {
41 s
[i
] = static_cast<char>(tolower(styler
[start
+ i
]));
47 inline bool IsASpace(unsigned int ch
) {
48 return (ch
== ' ') || ((ch
>= 0x09) && (ch
<= 0x0d));
51 inline bool IsAWordChar(unsigned int ch
) {
52 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
55 inline bool IsAWordStart(unsigned int ch
) {
56 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
59 inline bool IsADigit(unsigned int ch
) {
60 return (ch
>= '0') && (ch
<= '9');
63 // All languages handled so far can treat all characters >= 0x80 as one class
64 // which just continues the current token or starts an identifier if in default.
65 // DBCS treated specially as the second character can be < 0x80 and hence
66 // syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80
67 class xColouriseContext
{
71 xColouriseContext
& operator=(const xColouriseContext
&) {
80 xColouriseContext(unsigned int startPos
, int length
,
81 int initStyle
, Accessor
&styler_
) :
83 lengthDoc(startPos
+ length
),
89 styler
.StartAt(startPos
);
90 styler
.StartSegment(startPos
);
92 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(pos
));
93 if (styler
.IsLeadByte(static_cast<char>(ch
))) {
96 ch
|= static_cast<unsigned char>(styler
.SafeGetCharAt(pos
));
98 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(pos
+1));
99 if (styler
.IsLeadByte(static_cast<char>(chNext
))) {
100 chNext
= chNext
<< 8;
101 chNext
|= static_cast<unsigned char>(styler
.SafeGetCharAt(pos
+2));
105 styler
.ColourTo(currentPos
- 1, state
);
108 return currentPos
<= lengthDoc
;
116 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(currentPos
+1));
117 if (styler
.IsLeadByte(static_cast<char>(chNext
))) {
118 chNext
= chNext
<< 8;
119 chNext
|= static_cast<unsigned char>(styler
.SafeGetCharAt(currentPos
+ 2));
122 void ChangeState(int state_
) {
125 void SetState(int state_
) {
126 styler
.ColourTo(currentPos
- 1, state
);
129 void GetCurrentLowered(char *s
, int len
) {
130 getRangeLowered(styler
.GetStartSegment(), currentPos
- 1, styler
, s
, len
);
134 static void ColouriseEiffelDoc(unsigned int startPos
,
137 WordList
*keywordlists
[],
140 WordList
&keywords
= *keywordlists
[0];
142 xColouriseContext
lc(startPos
, length
, initStyle
, styler
);
144 for (; lc
.More(); lc
.Forward()) {
146 if (lc
.state
== SCE_EIFFEL_STRINGEOL
) {
147 if (lc
.ch
!= '\r' && lc
.ch
!= '\n') {
148 lc
.SetState(SCE_EIFFEL_DEFAULT
);
150 } else if (lc
.state
== SCE_EIFFEL_OPERATOR
) {
151 lc
.SetState(SCE_EIFFEL_DEFAULT
);
152 } else if (lc
.state
== SCE_EIFFEL_WORD
) {
153 if (!IsAWordChar(lc
.ch
)) {
155 lc
.GetCurrentLowered(s
, sizeof(s
));
156 if (!keywords
.InList(s
)) {
157 lc
.ChangeState(SCE_EIFFEL_IDENTIFIER
);
159 lc
.SetState(SCE_EIFFEL_DEFAULT
);
161 } else if (lc
.state
== SCE_EIFFEL_NUMBER
) {
162 if (!IsAWordChar(lc
.ch
)) {
163 lc
.SetState(SCE_EIFFEL_DEFAULT
);
165 } else if (lc
.state
== SCE_EIFFEL_COMMENTLINE
) {
166 if (lc
.ch
== '\r' || lc
.ch
== '\n') {
167 lc
.SetState(SCE_EIFFEL_DEFAULT
);
169 } else if (lc
.state
== SCE_EIFFEL_STRING
) {
172 } else if (lc
.ch
== '\"') {
174 lc
.SetState(SCE_EIFFEL_DEFAULT
);
176 } else if (lc
.state
== SCE_EIFFEL_CHARACTER
) {
177 if (lc
.ch
== '\r' || lc
.ch
== '\n') {
178 lc
.SetState(SCE_EIFFEL_STRINGEOL
);
179 } else if (lc
.ch
== '%') {
181 } else if (lc
.ch
== '\'') {
183 lc
.SetState(SCE_EIFFEL_DEFAULT
);
187 if (lc
.state
== SCE_EIFFEL_DEFAULT
) {
188 if (lc
.ch
== '-' && lc
.chNext
== '-') {
189 lc
.SetState(SCE_EIFFEL_COMMENTLINE
);
190 } else if (lc
.ch
== '\"') {
191 lc
.SetState(SCE_EIFFEL_STRING
);
192 } else if (lc
.ch
== '\'') {
193 lc
.SetState(SCE_EIFFEL_CHARACTER
);
194 } else if (IsADigit(lc
.ch
) || (lc
.ch
== '.')) {
195 lc
.SetState(SCE_EIFFEL_NUMBER
);
196 } else if (IsAWordStart(lc
.ch
)) {
197 lc
.SetState(SCE_EIFFEL_WORD
);
198 } else if (isEiffelOperator(lc
.ch
)) {
199 lc
.SetState(SCE_EIFFEL_OPERATOR
);
206 static bool IsEiffelComment(Accessor
&styler
, int pos
, int len
) {
207 return len
>1 && styler
[pos
]=='-' && styler
[pos
+1]=='-';
210 static void FoldEiffelDocIndent(unsigned int startPos
, int length
, int,
211 WordList
*[], Accessor
&styler
) {
212 int lengthDoc
= startPos
+ length
;
214 // Backtrack to previous line in case need to fix its fold status
215 int lineCurrent
= styler
.GetLine(startPos
);
217 if (lineCurrent
> 0) {
219 startPos
= styler
.LineStart(lineCurrent
);
223 int indentCurrent
= styler
.IndentAmount(lineCurrent
, &spaceFlags
, IsEiffelComment
);
224 char chNext
= styler
[startPos
];
225 for (int i
= startPos
; i
< lengthDoc
; i
++) {
227 chNext
= styler
.SafeGetCharAt(i
+ 1);
229 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n') || (i
== lengthDoc
)) {
230 int lev
= indentCurrent
;
231 int indentNext
= styler
.IndentAmount(lineCurrent
+ 1, &spaceFlags
, IsEiffelComment
);
232 if (!(indentCurrent
& SC_FOLDLEVELWHITEFLAG
)) {
233 // Only non whitespace lines can be headers
234 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext
& SC_FOLDLEVELNUMBERMASK
)) {
235 lev
|= SC_FOLDLEVELHEADERFLAG
;
236 } else if (indentNext
& SC_FOLDLEVELWHITEFLAG
) {
237 // Line after is blank so check the next - maybe should continue further?
239 int indentNext2
= styler
.IndentAmount(lineCurrent
+ 2, &spaceFlags2
, IsEiffelComment
);
240 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext2
& SC_FOLDLEVELNUMBERMASK
)) {
241 lev
|= SC_FOLDLEVELHEADERFLAG
;
245 indentCurrent
= indentNext
;
246 styler
.SetLevel(lineCurrent
, lev
);
252 static void FoldEiffelDocKeyWords(unsigned int startPos
, int length
, int /* initStyle */, WordList
*[],
254 unsigned int lengthDoc
= startPos
+ length
;
255 int visibleChars
= 0;
256 int lineCurrent
= styler
.GetLine(startPos
);
257 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
258 int levelCurrent
= levelPrev
;
259 char chNext
= styler
[startPos
];
261 int styleNext
= styler
.StyleAt(startPos
);
262 // lastDeferred should be determined by looking back to last keyword in case
263 // the "deferred" is on a line before "class"
264 bool lastDeferred
= false;
265 for (unsigned int i
= startPos
; i
< lengthDoc
; i
++) {
267 chNext
= styler
.SafeGetCharAt(i
+ 1);
268 int style
= styleNext
;
269 styleNext
= styler
.StyleAt(i
+ 1);
270 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
271 if ((stylePrev
!= SCE_EIFFEL_WORD
) && (style
== SCE_EIFFEL_WORD
)) {
274 while ((j
< (sizeof(s
) - 1)) && (iswordchar(styler
[i
+ j
]))) {
275 s
[j
] = styler
[i
+ j
];
281 (strcmp(s
, "check") == 0) ||
282 (strcmp(s
, "debug") == 0) ||
283 (strcmp(s
, "deferred") == 0) ||
284 (strcmp(s
, "do") == 0) ||
285 (strcmp(s
, "from") == 0) ||
286 (strcmp(s
, "if") == 0) ||
287 (strcmp(s
, "inspect") == 0) ||
288 (strcmp(s
, "once") == 0)
291 if (!lastDeferred
&& (strcmp(s
, "class") == 0))
293 if (strcmp(s
, "end") == 0)
295 lastDeferred
= strcmp(s
, "deferred") == 0;
300 if (visibleChars
== 0)
301 lev
|= SC_FOLDLEVELWHITEFLAG
;
302 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
303 lev
|= SC_FOLDLEVELHEADERFLAG
;
304 if (lev
!= styler
.LevelAt(lineCurrent
)) {
305 styler
.SetLevel(lineCurrent
, lev
);
308 levelPrev
= levelCurrent
;
311 if (!isspacechar(ch
))
315 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
316 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
317 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
320 LexerModule
lmEiffel(SCLEX_EIFFEL
, ColouriseEiffelDoc
, "eiffel", FoldEiffelDocIndent
);
321 LexerModule
lmEiffelkw(SCLEX_EIFFELKW
, ColouriseEiffelDoc
, "eiffelkw", FoldEiffelDocKeyWords
);