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