]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexEiffel.cxx
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.
16 #include "Scintilla.h"
20 #include "LexAccessor.h"
22 #include "StyleContext.h"
23 #include "CharacterSet.h"
24 #include "LexerModule.h"
27 using namespace Scintilla
;
30 static inline bool isEiffelOperator(unsigned int ch
) {
31 // '.' left out as it is used to make up numbers
32 return ch
== '*' || ch
== '/' || ch
== '\\' || ch
== '-' || ch
== '+' ||
33 ch
== '(' || ch
== ')' || ch
== '=' ||
34 ch
== '{' || ch
== '}' || ch
== '~' ||
35 ch
== '[' || ch
== ']' || ch
== ';' ||
36 ch
== '<' || ch
== '>' || ch
== ',' ||
37 ch
== '.' || ch
== '^' || ch
== '%' || ch
== ':' ||
38 ch
== '!' || ch
== '@' || ch
== '?';
41 static inline bool IsAWordChar(unsigned int ch
) {
42 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
45 static inline bool IsAWordStart(unsigned int ch
) {
46 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
49 static void ColouriseEiffelDoc(unsigned int startPos
,
52 WordList
*keywordlists
[],
55 WordList
&keywords
= *keywordlists
[0];
57 StyleContext
sc(startPos
, length
, initStyle
, styler
);
59 for (; sc
.More(); sc
.Forward()) {
61 if (sc
.state
== SCE_EIFFEL_STRINGEOL
) {
62 if (sc
.ch
!= '\r' && sc
.ch
!= '\n') {
63 sc
.SetState(SCE_EIFFEL_DEFAULT
);
65 } else if (sc
.state
== SCE_EIFFEL_OPERATOR
) {
66 sc
.SetState(SCE_EIFFEL_DEFAULT
);
67 } else if (sc
.state
== SCE_EIFFEL_WORD
) {
68 if (!IsAWordChar(sc
.ch
)) {
70 sc
.GetCurrentLowered(s
, sizeof(s
));
71 if (!keywords
.InList(s
)) {
72 sc
.ChangeState(SCE_EIFFEL_IDENTIFIER
);
74 sc
.SetState(SCE_EIFFEL_DEFAULT
);
76 } else if (sc
.state
== SCE_EIFFEL_NUMBER
) {
77 if (!IsAWordChar(sc
.ch
)) {
78 sc
.SetState(SCE_EIFFEL_DEFAULT
);
80 } else if (sc
.state
== SCE_EIFFEL_COMMENTLINE
) {
81 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
82 sc
.SetState(SCE_EIFFEL_DEFAULT
);
84 } else if (sc
.state
== SCE_EIFFEL_STRING
) {
87 } else if (sc
.ch
== '\"') {
89 sc
.SetState(SCE_EIFFEL_DEFAULT
);
91 } else if (sc
.state
== SCE_EIFFEL_CHARACTER
) {
92 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
93 sc
.SetState(SCE_EIFFEL_STRINGEOL
);
94 } else if (sc
.ch
== '%') {
96 } else if (sc
.ch
== '\'') {
98 sc
.SetState(SCE_EIFFEL_DEFAULT
);
102 if (sc
.state
== SCE_EIFFEL_DEFAULT
) {
103 if (sc
.ch
== '-' && sc
.chNext
== '-') {
104 sc
.SetState(SCE_EIFFEL_COMMENTLINE
);
105 } else if (sc
.ch
== '\"') {
106 sc
.SetState(SCE_EIFFEL_STRING
);
107 } else if (sc
.ch
== '\'') {
108 sc
.SetState(SCE_EIFFEL_CHARACTER
);
109 } else if (IsADigit(sc
.ch
) || (sc
.ch
== '.')) {
110 sc
.SetState(SCE_EIFFEL_NUMBER
);
111 } else if (IsAWordStart(sc
.ch
)) {
112 sc
.SetState(SCE_EIFFEL_WORD
);
113 } else if (isEiffelOperator(sc
.ch
)) {
114 sc
.SetState(SCE_EIFFEL_OPERATOR
);
121 static bool IsEiffelComment(Accessor
&styler
, int pos
, int len
) {
122 return len
>1 && styler
[pos
]=='-' && styler
[pos
+1]=='-';
125 static void FoldEiffelDocIndent(unsigned int startPos
, int length
, int,
126 WordList
*[], Accessor
&styler
) {
127 int lengthDoc
= startPos
+ length
;
129 // Backtrack to previous line in case need to fix its fold status
130 int lineCurrent
= styler
.GetLine(startPos
);
132 if (lineCurrent
> 0) {
134 startPos
= styler
.LineStart(lineCurrent
);
138 int indentCurrent
= styler
.IndentAmount(lineCurrent
, &spaceFlags
, IsEiffelComment
);
139 char chNext
= styler
[startPos
];
140 for (int i
= startPos
; i
< lengthDoc
; i
++) {
142 chNext
= styler
.SafeGetCharAt(i
+ 1);
144 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n') || (i
== lengthDoc
)) {
145 int lev
= indentCurrent
;
146 int indentNext
= styler
.IndentAmount(lineCurrent
+ 1, &spaceFlags
, IsEiffelComment
);
147 if (!(indentCurrent
& SC_FOLDLEVELWHITEFLAG
)) {
148 // Only non whitespace lines can be headers
149 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext
& SC_FOLDLEVELNUMBERMASK
)) {
150 lev
|= SC_FOLDLEVELHEADERFLAG
;
151 } else if (indentNext
& SC_FOLDLEVELWHITEFLAG
) {
152 // Line after is blank so check the next - maybe should continue further?
154 int indentNext2
= styler
.IndentAmount(lineCurrent
+ 2, &spaceFlags2
, IsEiffelComment
);
155 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext2
& SC_FOLDLEVELNUMBERMASK
)) {
156 lev
|= SC_FOLDLEVELHEADERFLAG
;
160 indentCurrent
= indentNext
;
161 styler
.SetLevel(lineCurrent
, lev
);
167 static void FoldEiffelDocKeyWords(unsigned int startPos
, int length
, int /* initStyle */, WordList
*[],
169 unsigned int lengthDoc
= startPos
+ length
;
170 int visibleChars
= 0;
171 int lineCurrent
= styler
.GetLine(startPos
);
172 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
173 int levelCurrent
= levelPrev
;
174 char chNext
= styler
[startPos
];
176 int styleNext
= styler
.StyleAt(startPos
);
177 // lastDeferred should be determined by looking back to last keyword in case
178 // the "deferred" is on a line before "class"
179 bool lastDeferred
= false;
180 for (unsigned int i
= startPos
; i
< lengthDoc
; i
++) {
182 chNext
= styler
.SafeGetCharAt(i
+ 1);
183 int style
= styleNext
;
184 styleNext
= styler
.StyleAt(i
+ 1);
185 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
186 if ((stylePrev
!= SCE_EIFFEL_WORD
) && (style
== SCE_EIFFEL_WORD
)) {
189 while ((j
< (sizeof(s
) - 1)) && (iswordchar(styler
[i
+ j
]))) {
190 s
[j
] = styler
[i
+ j
];
196 (strcmp(s
, "check") == 0) ||
197 (strcmp(s
, "debug") == 0) ||
198 (strcmp(s
, "deferred") == 0) ||
199 (strcmp(s
, "do") == 0) ||
200 (strcmp(s
, "from") == 0) ||
201 (strcmp(s
, "if") == 0) ||
202 (strcmp(s
, "inspect") == 0) ||
203 (strcmp(s
, "once") == 0)
206 if (!lastDeferred
&& (strcmp(s
, "class") == 0))
208 if (strcmp(s
, "end") == 0)
210 lastDeferred
= strcmp(s
, "deferred") == 0;
215 if (visibleChars
== 0)
216 lev
|= SC_FOLDLEVELWHITEFLAG
;
217 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
218 lev
|= SC_FOLDLEVELHEADERFLAG
;
219 if (lev
!= styler
.LevelAt(lineCurrent
)) {
220 styler
.SetLevel(lineCurrent
, lev
);
223 levelPrev
= levelCurrent
;
226 if (!isspacechar(ch
))
230 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
231 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
232 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
235 static const char * const eiffelWordListDesc
[] = {
240 LexerModule
lmEiffel(SCLEX_EIFFEL
, ColouriseEiffelDoc
, "eiffel", FoldEiffelDocIndent
, eiffelWordListDesc
);
241 LexerModule
lmEiffelkw(SCLEX_EIFFELKW
, ColouriseEiffelDoc
, "eiffelkw", FoldEiffelDocKeyWords
, eiffelWordListDesc
);