]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexEiffel.cxx
e9e154cd5f64b8eb8051aa11c7ccbf8ad08a0cda
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.
18 #include "StyleContext.h"
20 #include "Scintilla.h"
23 static 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 inline bool IsAWordChar(unsigned int ch
) {
35 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
38 static inline bool IsAWordStart(unsigned int ch
) {
39 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
42 static void ColouriseEiffelDoc(unsigned int startPos
,
45 WordList
*keywordlists
[],
48 WordList
&keywords
= *keywordlists
[0];
50 StyleContext
sc(startPos
, length
, initStyle
, styler
);
52 for (; sc
.More(); sc
.Forward()) {
54 if (sc
.state
== SCE_EIFFEL_STRINGEOL
) {
55 if (sc
.ch
!= '\r' && sc
.ch
!= '\n') {
56 sc
.SetState(SCE_EIFFEL_DEFAULT
);
58 } else if (sc
.state
== SCE_EIFFEL_OPERATOR
) {
59 sc
.SetState(SCE_EIFFEL_DEFAULT
);
60 } else if (sc
.state
== SCE_EIFFEL_WORD
) {
61 if (!IsAWordChar(sc
.ch
)) {
63 sc
.GetCurrentLowered(s
, sizeof(s
));
64 if (!keywords
.InList(s
)) {
65 sc
.ChangeState(SCE_EIFFEL_IDENTIFIER
);
67 sc
.SetState(SCE_EIFFEL_DEFAULT
);
69 } else if (sc
.state
== SCE_EIFFEL_NUMBER
) {
70 if (!IsAWordChar(sc
.ch
)) {
71 sc
.SetState(SCE_EIFFEL_DEFAULT
);
73 } else if (sc
.state
== SCE_EIFFEL_COMMENTLINE
) {
74 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
75 sc
.SetState(SCE_EIFFEL_DEFAULT
);
77 } else if (sc
.state
== SCE_EIFFEL_STRING
) {
80 } else if (sc
.ch
== '\"') {
82 sc
.SetState(SCE_EIFFEL_DEFAULT
);
84 } else if (sc
.state
== SCE_EIFFEL_CHARACTER
) {
85 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
86 sc
.SetState(SCE_EIFFEL_STRINGEOL
);
87 } else if (sc
.ch
== '%') {
89 } else if (sc
.ch
== '\'') {
91 sc
.SetState(SCE_EIFFEL_DEFAULT
);
95 if (sc
.state
== SCE_EIFFEL_DEFAULT
) {
96 if (sc
.ch
== '-' && sc
.chNext
== '-') {
97 sc
.SetState(SCE_EIFFEL_COMMENTLINE
);
98 } else if (sc
.ch
== '\"') {
99 sc
.SetState(SCE_EIFFEL_STRING
);
100 } else if (sc
.ch
== '\'') {
101 sc
.SetState(SCE_EIFFEL_CHARACTER
);
102 } else if (IsADigit(sc
.ch
) || (sc
.ch
== '.')) {
103 sc
.SetState(SCE_EIFFEL_NUMBER
);
104 } else if (IsAWordStart(sc
.ch
)) {
105 sc
.SetState(SCE_EIFFEL_WORD
);
106 } else if (isEiffelOperator(sc
.ch
)) {
107 sc
.SetState(SCE_EIFFEL_OPERATOR
);
114 static bool IsEiffelComment(Accessor
&styler
, int pos
, int len
) {
115 return len
>1 && styler
[pos
]=='-' && styler
[pos
+1]=='-';
118 static void FoldEiffelDocIndent(unsigned int startPos
, int length
, int,
119 WordList
*[], Accessor
&styler
) {
120 int lengthDoc
= startPos
+ length
;
122 // Backtrack to previous line in case need to fix its fold status
123 int lineCurrent
= styler
.GetLine(startPos
);
125 if (lineCurrent
> 0) {
127 startPos
= styler
.LineStart(lineCurrent
);
131 int indentCurrent
= styler
.IndentAmount(lineCurrent
, &spaceFlags
, IsEiffelComment
);
132 char chNext
= styler
[startPos
];
133 for (int i
= startPos
; i
< lengthDoc
; i
++) {
135 chNext
= styler
.SafeGetCharAt(i
+ 1);
137 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n') || (i
== lengthDoc
)) {
138 int lev
= indentCurrent
;
139 int indentNext
= styler
.IndentAmount(lineCurrent
+ 1, &spaceFlags
, IsEiffelComment
);
140 if (!(indentCurrent
& SC_FOLDLEVELWHITEFLAG
)) {
141 // Only non whitespace lines can be headers
142 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext
& SC_FOLDLEVELNUMBERMASK
)) {
143 lev
|= SC_FOLDLEVELHEADERFLAG
;
144 } else if (indentNext
& SC_FOLDLEVELWHITEFLAG
) {
145 // Line after is blank so check the next - maybe should continue further?
147 int indentNext2
= styler
.IndentAmount(lineCurrent
+ 2, &spaceFlags2
, IsEiffelComment
);
148 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext2
& SC_FOLDLEVELNUMBERMASK
)) {
149 lev
|= SC_FOLDLEVELHEADERFLAG
;
153 indentCurrent
= indentNext
;
154 styler
.SetLevel(lineCurrent
, lev
);
160 static void FoldEiffelDocKeyWords(unsigned int startPos
, int length
, int /* initStyle */, WordList
*[],
162 unsigned int lengthDoc
= startPos
+ length
;
163 int visibleChars
= 0;
164 int lineCurrent
= styler
.GetLine(startPos
);
165 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
166 int levelCurrent
= levelPrev
;
167 char chNext
= styler
[startPos
];
169 int styleNext
= styler
.StyleAt(startPos
);
170 // lastDeferred should be determined by looking back to last keyword in case
171 // the "deferred" is on a line before "class"
172 bool lastDeferred
= false;
173 for (unsigned int i
= startPos
; i
< lengthDoc
; i
++) {
175 chNext
= styler
.SafeGetCharAt(i
+ 1);
176 int style
= styleNext
;
177 styleNext
= styler
.StyleAt(i
+ 1);
178 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
179 if ((stylePrev
!= SCE_EIFFEL_WORD
) && (style
== SCE_EIFFEL_WORD
)) {
182 while ((j
< (sizeof(s
) - 1)) && (iswordchar(styler
[i
+ j
]))) {
183 s
[j
] = styler
[i
+ j
];
189 (strcmp(s
, "check") == 0) ||
190 (strcmp(s
, "debug") == 0) ||
191 (strcmp(s
, "deferred") == 0) ||
192 (strcmp(s
, "do") == 0) ||
193 (strcmp(s
, "from") == 0) ||
194 (strcmp(s
, "if") == 0) ||
195 (strcmp(s
, "inspect") == 0) ||
196 (strcmp(s
, "once") == 0)
199 if (!lastDeferred
&& (strcmp(s
, "class") == 0))
201 if (strcmp(s
, "end") == 0)
203 lastDeferred
= strcmp(s
, "deferred") == 0;
208 if (visibleChars
== 0)
209 lev
|= SC_FOLDLEVELWHITEFLAG
;
210 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
211 lev
|= SC_FOLDLEVELHEADERFLAG
;
212 if (lev
!= styler
.LevelAt(lineCurrent
)) {
213 styler
.SetLevel(lineCurrent
, lev
);
216 levelPrev
= levelCurrent
;
219 if (!isspacechar(ch
))
223 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
224 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
225 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
228 static const char * const eiffelWordListDesc
[] = {
233 LexerModule
lmEiffel(SCLEX_EIFFEL
, ColouriseEiffelDoc
, "eiffel", FoldEiffelDocIndent
, eiffelWordListDesc
);
234 LexerModule
lmEiffelkw(SCLEX_EIFFELKW
, ColouriseEiffelDoc
, "eiffelkw", FoldEiffelDocKeyWords
, eiffelWordListDesc
);