]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexSpecman.cxx
Compilation fix for wxMSW with wxUSE_MSGBOX_HOOK==0.
[wxWidgets.git] / src / stc / scintilla / lexers / LexSpecman.cxx
1 // Scintilla source code edit control
2 /** @file LexSpecman.cxx
3 ** Lexer for Specman E language.
4 ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson
5 **/
6 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <assert.h>
15
16 #include "ILexer.h"
17 #include "Scintilla.h"
18 #include "SciLexer.h"
19
20 #include "WordList.h"
21 #include "LexAccessor.h"
22 #include "Accessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
26
27 #ifdef SCI_NAMESPACE
28 using namespace Scintilla;
29 #endif
30
31 static inline bool IsAWordChar(const int ch) {
32 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
33 }
34
35 static inline bool IsANumberChar(const int ch) {
36 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '\'');
37 }
38
39 static inline bool IsAWordStart(const int ch) {
40 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '`');
41 }
42
43 static void ColouriseSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
44 Accessor &styler, bool caseSensitive) {
45
46 WordList &keywords = *keywordlists[0];
47 WordList &keywords2 = *keywordlists[1];
48 WordList &keywords3 = *keywordlists[2];
49 WordList &keywords4 = *keywordlists[3];
50
51 // Do not leak onto next line
52 if (initStyle == SCE_SN_STRINGEOL)
53 initStyle = SCE_SN_CODE;
54
55 int visibleChars = 0;
56
57 StyleContext sc(startPos, length, initStyle, styler);
58
59 for (; sc.More(); sc.Forward()) {
60
61 if (sc.atLineStart && (sc.state == SCE_SN_STRING)) {
62 // Prevent SCE_SN_STRINGEOL from leaking back to previous line
63 sc.SetState(SCE_SN_STRING);
64 }
65
66 // Handle line continuation generically.
67 if (sc.ch == '\\') {
68 if (sc.chNext == '\n' || sc.chNext == '\r') {
69 sc.Forward();
70 if (sc.ch == '\r' && sc.chNext == '\n') {
71 sc.Forward();
72 }
73 continue;
74 }
75 }
76
77 // Determine if the current state should terminate.
78 if (sc.state == SCE_SN_OPERATOR) {
79 sc.SetState(SCE_SN_CODE);
80 } else if (sc.state == SCE_SN_NUMBER) {
81 if (!IsANumberChar(sc.ch)) {
82 sc.SetState(SCE_SN_CODE);
83 }
84 } else if (sc.state == SCE_SN_IDENTIFIER) {
85 if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
86 char s[100];
87 if (caseSensitive) {
88 sc.GetCurrent(s, sizeof(s));
89 } else {
90 sc.GetCurrentLowered(s, sizeof(s));
91 }
92 if (keywords.InList(s)) {
93 sc.ChangeState(SCE_SN_WORD);
94 } else if (keywords2.InList(s)) {
95 sc.ChangeState(SCE_SN_WORD2);
96 } else if (keywords3.InList(s)) {
97 sc.ChangeState(SCE_SN_WORD3);
98 } else if (keywords4.InList(s)) {
99 sc.ChangeState(SCE_SN_USER);
100 }
101 sc.SetState(SCE_SN_CODE);
102 }
103 } else if (sc.state == SCE_SN_PREPROCESSOR) {
104 if (IsASpace(sc.ch)) {
105 sc.SetState(SCE_SN_CODE);
106 }
107 } else if (sc.state == SCE_SN_DEFAULT) {
108 if (sc.Match('<', '\'')) {
109 sc.Forward();
110 sc.ForwardSetState(SCE_SN_CODE);
111 }
112 } else if (sc.state == SCE_SN_COMMENTLINE || sc.state == SCE_SN_COMMENTLINEBANG) {
113 if (sc.atLineEnd) {
114 sc.SetState(SCE_SN_CODE);
115 visibleChars = 0;
116 }
117 } else if (sc.state == SCE_SN_STRING) {
118 if (sc.ch == '\\') {
119 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
120 sc.Forward();
121 }
122 } else if (sc.ch == '\"') {
123 sc.ForwardSetState(SCE_SN_CODE);
124 } else if (sc.atLineEnd) {
125 sc.ChangeState(SCE_SN_STRINGEOL);
126 sc.ForwardSetState(SCE_SN_CODE);
127 visibleChars = 0;
128 }
129 } else if (sc.state == SCE_SN_SIGNAL) {
130 if (sc.atLineEnd) {
131 sc.ChangeState(SCE_SN_STRINGEOL);
132 sc.ForwardSetState(SCE_SN_CODE);
133 visibleChars = 0;
134 } else if (sc.ch == '\\') {
135 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
136 sc.Forward();
137 }
138 } else if (sc.ch == '\'') {
139 sc.ForwardSetState(SCE_SN_CODE);
140 }
141 } else if (sc.state == SCE_SN_REGEXTAG) {
142 if (!IsADigit(sc.ch)) {
143 sc.SetState(SCE_SN_CODE);
144 }
145 }
146
147 // Determine if a new state should be entered.
148 if (sc.state == SCE_SN_CODE) {
149 if (sc.ch == '$' && IsADigit(sc.chNext)) {
150 sc.SetState(SCE_SN_REGEXTAG);
151 sc.Forward();
152 } else if (IsADigit(sc.ch)) {
153 sc.SetState(SCE_SN_NUMBER);
154 } else if (IsAWordStart(sc.ch)) {
155 sc.SetState(SCE_SN_IDENTIFIER);
156 } else if (sc.Match('\'', '>')) {
157 sc.SetState(SCE_SN_DEFAULT);
158 sc.Forward(); // Eat the * so it isn't used for the end of the comment
159 } else if (sc.Match('/', '/')) {
160 if (sc.Match("//!")) // Nice to have a different comment style
161 sc.SetState(SCE_SN_COMMENTLINEBANG);
162 else
163 sc.SetState(SCE_SN_COMMENTLINE);
164 } else if (sc.Match('-', '-')) {
165 if (sc.Match("--!")) // Nice to have a different comment style
166 sc.SetState(SCE_SN_COMMENTLINEBANG);
167 else
168 sc.SetState(SCE_SN_COMMENTLINE);
169 } else if (sc.ch == '\"') {
170 sc.SetState(SCE_SN_STRING);
171 } else if (sc.ch == '\'') {
172 sc.SetState(SCE_SN_SIGNAL);
173 } else if (sc.ch == '#' && visibleChars == 0) {
174 // Preprocessor commands are alone on their line
175 sc.SetState(SCE_SN_PREPROCESSOR);
176 // Skip whitespace between # and preprocessor word
177 do {
178 sc.Forward();
179 } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
180 if (sc.atLineEnd) {
181 sc.SetState(SCE_SN_CODE);
182 }
183 } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@') {
184 sc.SetState(SCE_SN_OPERATOR);
185 }
186 }
187
188 if (sc.atLineEnd) {
189 // Reset states to begining of colourise so no surprises
190 // if different sets of lines lexed.
191 visibleChars = 0;
192 }
193 if (!IsASpace(sc.ch)) {
194 visibleChars++;
195 }
196 }
197 sc.Complete();
198 }
199
200 // Store both the current line's fold level and the next lines in the
201 // level store to make it easy to pick up with each increment
202 // and to make it possible to fiddle the current level for "} else {".
203 static void FoldNoBoxSpecmanDoc(unsigned int startPos, int length, int,
204 Accessor &styler) {
205 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
206 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
207 bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
208 unsigned int endPos = startPos + length;
209 int visibleChars = 0;
210 int lineCurrent = styler.GetLine(startPos);
211 int levelCurrent = SC_FOLDLEVELBASE;
212 if (lineCurrent > 0)
213 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
214 int levelMinCurrent = levelCurrent;
215 int levelNext = levelCurrent;
216 char chNext = styler[startPos];
217 int styleNext = styler.StyleAt(startPos);
218 int style;
219 for (unsigned int i = startPos; i < endPos; i++) {
220 char ch = chNext;
221 chNext = styler.SafeGetCharAt(i + 1);
222 //int stylePrev = style;
223 style = styleNext;
224 styleNext = styler.StyleAt(i + 1);
225 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
226 if (foldComment && (style == SCE_SN_COMMENTLINE)) {
227 if (((ch == '/') && (chNext == '/')) ||
228 ((ch == '-') && (chNext == '-'))) {
229 char chNext2 = styler.SafeGetCharAt(i + 2);
230 if (chNext2 == '{') {
231 levelNext++;
232 } else if (chNext2 == '}') {
233 levelNext--;
234 }
235 }
236 }
237 if (style == SCE_SN_OPERATOR) {
238 if (ch == '{') {
239 // Measure the minimum before a '{' to allow
240 // folding on "} else {"
241 if (levelMinCurrent > levelNext) {
242 levelMinCurrent = levelNext;
243 }
244 levelNext++;
245 } else if (ch == '}') {
246 levelNext--;
247 }
248 }
249 if (atEOL) {
250 int levelUse = levelCurrent;
251 if (foldAtElse) {
252 levelUse = levelMinCurrent;
253 }
254 int lev = levelUse | levelNext << 16;
255 if (visibleChars == 0 && foldCompact)
256 lev |= SC_FOLDLEVELWHITEFLAG;
257 if (levelUse < levelNext)
258 lev |= SC_FOLDLEVELHEADERFLAG;
259 if (lev != styler.LevelAt(lineCurrent)) {
260 styler.SetLevel(lineCurrent, lev);
261 }
262 lineCurrent++;
263 levelCurrent = levelNext;
264 levelMinCurrent = levelCurrent;
265 visibleChars = 0;
266 }
267 if (!isspacechar(ch))
268 visibleChars++;
269 }
270 }
271
272 static void FoldSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *[],
273 Accessor &styler) {
274 FoldNoBoxSpecmanDoc(startPos, length, initStyle, styler);
275 }
276
277 static const char * const specmanWordLists[] = {
278 "Primary keywords and identifiers",
279 "Secondary keywords and identifiers",
280 "Sequence keywords and identifiers",
281 "User defined keywords and identifiers",
282 "Unused",
283 0,
284 };
285
286 static void ColouriseSpecmanDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
287 Accessor &styler) {
288 ColouriseSpecmanDoc(startPos, length, initStyle, keywordlists, styler, true);
289 }
290
291
292 LexerModule lmSpecman(SCLEX_SPECMAN, ColouriseSpecmanDocSensitive, "specman", FoldSpecmanDoc, specmanWordLists);