]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexBasic.cxx
4a1843aa0d05805a9fa203707549ff5a710cdbce
1 // Scintilla source code edit control
3 ** Lexer for BlitzBasic and PureBasic.
5 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
8 // This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics
9 // and derivatives. Once they diverge enough, might want to split it into multiple
10 // lexers for more code clearity.
12 // Mail me (elias <at> users <dot> sf <dot> net) for any bugs.
14 // Folding only works for simple things like functions or types.
16 // You may want to have a look at my ctags lexer as well, if you additionally to coloring
17 // and folding need to extract things like label tags in your editor.
29 #include "StyleContext.h"
31 #include "Scintilla.h"
42 static int character_classification
[128] =
44 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 2,
47 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2,
48 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4,
49 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4,
50 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4,
51 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0
54 static bool IsSpace(int c
) {
55 return c
< 128 && (character_classification
[c
] & 1);
58 static bool IsOperator(int c
) {
59 return c
< 128 && (character_classification
[c
] & 2);
62 static bool IsIdentifier(int c
) {
63 return c
< 128 && (character_classification
[c
] & 4);
66 static bool IsDigit(int c
) {
67 return c
< 128 && (character_classification
[c
] & 8);
70 static bool IsHexDigit(int c
) {
71 return c
< 128 && (character_classification
[c
] & 16);
74 static bool IsBinDigit(int c
) {
75 return c
< 128 && (character_classification
[c
] & 32);
78 static int LowerCase(int c
)
80 if (c
>= 'A' && c
<= 'Z')
85 static void ColouriseBasicDoc(unsigned int startPos
, int length
, int initStyle
,
86 WordList
*keywordlists
[], Accessor
&styler
, char comment_char
) {
87 bool wasfirst
= true, isfirst
= true; // true if first token in a line
88 styler
.StartAt(startPos
);
90 StyleContext
sc(startPos
, length
, initStyle
, styler
);
92 // Can't use sc.More() here else we miss the last character
93 for (; ; sc
.Forward()) {
94 if (sc
.state
== SCE_B_IDENTIFIER
) {
95 if (!IsIdentifier(sc
.ch
)) {
97 if (wasfirst
&& sc
.Match(':')) {
98 sc
.ChangeState(SCE_B_LABEL
);
99 sc
.ForwardSetState(SCE_B_DEFAULT
);
108 sc
.GetCurrentLowered(s
, sizeof(s
));
109 for (int i
= 0; i
< 4; i
++) {
110 if (keywordlists
[i
]->InList(s
)) {
111 sc
.ChangeState(kstates
[i
]);
114 // Types, must set them as operator else they will be
115 // matched as number/constant
116 if (sc
.Match('.') || sc
.Match('$') || sc
.Match('%') ||
118 sc
.SetState(SCE_B_OPERATOR
);
120 sc
.SetState(SCE_B_DEFAULT
);
124 } else if (sc
.state
== SCE_B_OPERATOR
) {
125 if (!IsOperator(sc
.ch
) || sc
.Match('#'))
126 sc
.SetState(SCE_B_DEFAULT
);
127 } else if (sc
.state
== SCE_B_LABEL
) {
128 if (!IsIdentifier(sc
.ch
))
129 sc
.SetState(SCE_B_DEFAULT
);
130 } else if (sc
.state
== SCE_B_CONSTANT
) {
131 if (!IsIdentifier(sc
.ch
))
132 sc
.SetState(SCE_B_DEFAULT
);
133 } else if (sc
.state
== SCE_B_NUMBER
) {
135 sc
.SetState(SCE_B_DEFAULT
);
136 } else if (sc
.state
== SCE_B_HEXNUMBER
) {
137 if (!IsHexDigit(sc
.ch
))
138 sc
.SetState(SCE_B_DEFAULT
);
139 } else if (sc
.state
== SCE_B_BINNUMBER
) {
140 if (!IsBinDigit(sc
.ch
))
141 sc
.SetState(SCE_B_DEFAULT
);
142 } else if (sc
.state
== SCE_B_STRING
) {
144 sc
.ForwardSetState(SCE_B_DEFAULT
);
147 sc
.ChangeState(SCE_B_ERROR
);
148 sc
.SetState(SCE_B_DEFAULT
);
150 } else if (sc
.state
== SCE_B_COMMENT
) {
152 sc
.SetState(SCE_B_DEFAULT
);
159 if (sc
.state
== SCE_B_DEFAULT
|| sc
.state
== SCE_B_ERROR
) {
160 if (isfirst
&& sc
.Match('.')) {
161 sc
.SetState(SCE_B_LABEL
);
162 } else if (isfirst
&& sc
.Match('#')) {
164 sc
.SetState(SCE_B_IDENTIFIER
);
165 } else if (sc
.Match(comment_char
)) {
166 sc
.SetState(SCE_B_COMMENT
);
167 } else if (sc
.Match('"')) {
168 sc
.SetState(SCE_B_STRING
);
169 } else if (IsDigit(sc
.ch
)) {
170 sc
.SetState(SCE_B_NUMBER
);
171 } else if (sc
.Match('$')) {
172 sc
.SetState(SCE_B_HEXNUMBER
);
173 } else if (sc
.Match('%')) {
174 sc
.SetState(SCE_B_BINNUMBER
);
175 } else if (sc
.Match('#')) {
176 sc
.SetState(SCE_B_CONSTANT
);
177 } else if (IsOperator(sc
.ch
)) {
178 sc
.SetState(SCE_B_OPERATOR
);
179 } else if (IsIdentifier(sc
.ch
)) {
181 sc
.SetState(SCE_B_IDENTIFIER
);
182 } else if (!IsSpace(sc
.ch
)) {
183 sc
.SetState(SCE_B_ERROR
);
196 static int CheckBlitzFoldPoint(char const *token
, int &level
) {
197 if (!strcmp(token
, "function") ||
198 !strcmp(token
, "type")) {
199 level
|= SC_FOLDLEVELHEADERFLAG
;
202 if (!strcmp(token
, "end function") ||
203 !strcmp(token
, "end type")) {
209 static int CheckPureFoldPoint(char const *token
, int &level
) {
210 if (!strcmp(token
, "procedure") ||
211 !strcmp(token
, "enumeration") ||
212 !strcmp(token
, "interface") ||
213 !strcmp(token
, "structure")) {
214 level
|= SC_FOLDLEVELHEADERFLAG
;
217 if (!strcmp(token
, "endprocedure") ||
218 !strcmp(token
, "endenumeration") ||
219 !strcmp(token
, "endinterface") ||
220 !strcmp(token
, "endstructure")) {
226 static int CheckFreeFoldPoint(char const *token
, int &level
) {
227 if (!strcmp(token
, "function") ||
228 !strcmp(token
, "sub") ||
229 !strcmp(token
, "type")) {
230 level
|= SC_FOLDLEVELHEADERFLAG
;
233 if (!strcmp(token
, "end function") ||
234 !strcmp(token
, "end sub") ||
235 !strcmp(token
, "end type")) {
241 static void FoldBasicDoc(unsigned int startPos
, int length
,
242 Accessor
&styler
, int (*CheckFoldPoint
)(char const *, int &)) {
243 int line
= styler
.GetLine(startPos
);
244 int level
= styler
.LevelAt(line
);
245 int go
= 0, done
= 0;
246 int endPos
= startPos
+ length
;
250 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
251 // Scan for tokens at the start of the line (they may include
252 // whitespace, for tokens like "End Function"
253 for (i
= startPos
; i
< endPos
; i
++) {
254 int c
= styler
.SafeGetCharAt(i
);
256 if (wordlen
) { // are we scanning a token already?
257 word
[wordlen
] = static_cast<char>(LowerCase(c
));
258 if (!IsIdentifier(c
)) { // done with token
259 word
[wordlen
] = '\0';
260 go
= CheckFoldPoint(word
, level
);
262 // Treat any whitespace as single blank, for
263 // things like "End Function".
264 if (IsSpace(c
) && IsIdentifier(word
[wordlen
- 1])) {
269 else // done with this line
272 } else if (wordlen
< 255) {
275 } else { // start scanning at first non-whitespace character
277 if (IsIdentifier(c
)) {
278 word
[0] = static_cast<char>(LowerCase(c
));
280 } else // done with this line
285 if (c
== '\n') { // line end
286 if (!done
&& wordlen
== 0 && foldCompact
) // line was only space
287 level
|= SC_FOLDLEVELWHITEFLAG
;
288 if (level
!= styler
.LevelAt(line
))
289 styler
.SetLevel(line
, level
);
294 level
&= ~SC_FOLDLEVELHEADERFLAG
;
295 level
&= ~SC_FOLDLEVELWHITEFLAG
;
302 static void ColouriseBlitzBasicDoc(unsigned int startPos
, int length
, int initStyle
,
303 WordList
*keywordlists
[], Accessor
&styler
) {
304 ColouriseBasicDoc(startPos
, length
, initStyle
, keywordlists
, styler
, ';');
307 static void ColourisePureBasicDoc(unsigned int startPos
, int length
, int initStyle
,
308 WordList
*keywordlists
[], Accessor
&styler
) {
309 ColouriseBasicDoc(startPos
, length
, initStyle
, keywordlists
, styler
, ';');
312 static void ColouriseFreeBasicDoc(unsigned int startPos
, int length
, int initStyle
,
313 WordList
*keywordlists
[], Accessor
&styler
) {
314 ColouriseBasicDoc(startPos
, length
, initStyle
, keywordlists
, styler
, '\'');
317 static void FoldBlitzBasicDoc(unsigned int startPos
, int length
, int,
318 WordList
*[], Accessor
&styler
) {
319 FoldBasicDoc(startPos
, length
, styler
, CheckBlitzFoldPoint
);
322 static void FoldPureBasicDoc(unsigned int startPos
, int length
, int,
323 WordList
*[], Accessor
&styler
) {
324 FoldBasicDoc(startPos
, length
, styler
, CheckPureFoldPoint
);
327 static void FoldFreeBasicDoc(unsigned int startPos
, int length
, int,
328 WordList
*[], Accessor
&styler
) {
329 FoldBasicDoc(startPos
, length
, styler
, CheckFreeFoldPoint
);
332 static const char * const blitzbasicWordListDesc
[] = {
333 "BlitzBasic Keywords",
340 static const char * const purebasicWordListDesc
[] = {
341 "PureBasic Keywords",
342 "PureBasic PreProcessor Keywords",
348 static const char * const freebasicWordListDesc
[] = {
349 "FreeBasic Keywords",
350 "FreeBasic PreProcessor Keywords",
356 LexerModule
lmBlitzBasic(SCLEX_BLITZBASIC
, ColouriseBlitzBasicDoc
, "blitzbasic",
357 FoldBlitzBasicDoc
, blitzbasicWordListDesc
);
359 LexerModule
lmPureBasic(SCLEX_PUREBASIC
, ColourisePureBasicDoc
, "purebasic",
360 FoldPureBasicDoc
, purebasicWordListDesc
);
362 LexerModule
lmFreeBasic(SCLEX_FREEBASIC
, ColouriseFreeBasicDoc
, "freebasic",
363 FoldFreeBasicDoc
, freebasicWordListDesc
);