]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexPB.cxx
a7b5690ebb30997549dce318532fc8701a4c8d2a
1 // Scintilla source code edit control
3 // Lexer for PowerBasic by Roland Walter, roland@rowalt.de (for PowerBasic see www.powerbasic.com)
6 // 17.10.2003: Toggling of subs/functions now until next sub/function - this gives better results
7 // 29.10.2003: 1. Bug: Toggling didn't work for subs/functions added in editor
8 // 2. Own colors for PB constants and Inline Assembler SCE_B_CONSTANT and SCE_B_ASM
9 // 3. Several smaller syntax coloring improvements and speed optimizations
10 // 12.07.2004: 1. Toggling for macros added
11 // 2. Further folding speed optimitations (for people dealing with very large listings)
13 // Necessary changes for the PB lexer in Scintilla project:
14 // - In SciLexer.h and Scintilla.iface:
16 // #define SCLEX_POWERBASIC 51 //ID for PowerBasic lexer
18 // #define SCE_B_DEFAULT 0 //in both VB and PB lexer
19 // #define SCE_B_COMMENT 1 //in both VB and PB lexer
20 // #define SCE_B_NUMBER 2 //in both VB and PB lexer
21 // #define SCE_B_KEYWORD 3 //in both VB and PB lexer
22 // #define SCE_B_STRING 4 //in both VB and PB lexer
23 // #define SCE_B_PREPROCESSOR 5 //VB lexer only, not in PB lexer
24 // #define SCE_B_OPERATOR 6 //in both VB and PB lexer
25 // #define SCE_B_IDENTIFIER 7 //in both VB and PB lexer
26 // #define SCE_B_DATE 8 //VB lexer only, not in PB lexer
27 // #define SCE_B_CONSTANT 13 //PB lexer only, not in VB lexer
28 // #define SCE_B_ASM 14 //PB lexer only, not in VB lexer
30 // - Statement added to KeyWords.cxx: 'LINK_LEXER(lmPB);'
31 // - Statement added to scintilla_vc6.mak: '$(DIR_O)\LexPB.obj: ...\src\LexPB.cxx $(LEX_HEADERS)'
33 // Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org>
34 // The License.txt file describes the conditions under which this software may be distributed.
44 #include "Scintilla.h"
48 #include "LexAccessor.h"
50 #include "StyleContext.h"
51 #include "CharacterSet.h"
52 #include "LexerModule.h"
55 using namespace Scintilla
;
58 static inline bool IsTypeCharacter(const int ch
)
60 return ch
== '%' || ch
== '&' || ch
== '@' || ch
== '!' || ch
== '#' || ch
== '$' || ch
== '?';
63 static inline bool IsAWordChar(const int ch
)
65 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
68 static inline bool IsAWordStart(const int ch
)
70 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
73 bool MatchUpperCase(Accessor
&styler
, int pos
, const char *s
) //Same as styler.Match() but uppercase comparison (a-z,A-Z and space only)
76 for (int i
=0; *s
; i
++)
78 ch
=styler
.SafeGetCharAt(pos
+i
);
79 if (ch
> 0x60) ch
-= '\x20';
80 if (*s
!= ch
) return false;
86 static void ColourisePBDoc(unsigned int startPos
, int length
, int initStyle
,WordList
*keywordlists
[],Accessor
&styler
) {
88 WordList
&keywords
= *keywordlists
[0];
90 styler
.StartAt(startPos
);
92 StyleContext
sc(startPos
, length
, initStyle
, styler
);
94 for (; sc
.More(); sc
.Forward()) {
99 sc
.SetState(SCE_B_DEFAULT
);
104 if (!IsAWordChar(sc
.ch
))
106 if (!IsTypeCharacter(sc
.ch
))
109 sc
.GetCurrentLowered(s
, sizeof(s
));
110 if (keywords
.InList(s
))
112 if (strcmp(s
, "rem") == 0)
114 sc
.ChangeState(SCE_B_COMMENT
);
115 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
117 else if (strcmp(s
, "asm") == 0)
119 sc
.ChangeState(SCE_B_ASM
);
120 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
124 sc
.SetState(SCE_B_DEFAULT
);
129 sc
.ChangeState(SCE_B_IDENTIFIER
);
130 sc
.SetState(SCE_B_DEFAULT
);
138 if (!IsAWordChar(sc
.ch
)) {sc
.SetState(SCE_B_DEFAULT
);}
143 if (sc
.ch
== '\"'){sc
.ForwardSetState(SCE_B_DEFAULT
);}
148 if (!IsAWordChar(sc
.ch
)) {sc
.SetState(SCE_B_DEFAULT
);}
153 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
158 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
161 } //switch (sc.state)
163 // Determine if a new state should be entered:
164 if (sc
.state
== SCE_B_DEFAULT
)
166 if (sc
.ch
== '\'') {sc
.SetState(SCE_B_COMMENT
);}
167 else if (sc
.ch
== '\"') {sc
.SetState(SCE_B_STRING
);}
168 else if (sc
.ch
== '&' && tolower(sc
.chNext
) == 'h') {sc
.SetState(SCE_B_NUMBER
);}
169 else if (sc
.ch
== '&' && tolower(sc
.chNext
) == 'b') {sc
.SetState(SCE_B_NUMBER
);}
170 else if (sc
.ch
== '&' && tolower(sc
.chNext
) == 'o') {sc
.SetState(SCE_B_NUMBER
);}
171 else if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {sc
.SetState(SCE_B_NUMBER
);}
172 else if (IsAWordStart(sc
.ch
)) {sc
.SetState(SCE_B_KEYWORD
);}
173 else if (sc
.ch
== '%') {sc
.SetState(SCE_B_CONSTANT
);}
174 else if (sc
.ch
== '$') {sc
.SetState(SCE_B_CONSTANT
);}
175 else if (sc
.ch
== '#') {sc
.SetState(SCE_B_KEYWORD
);}
176 else if (sc
.ch
== '!') {sc
.SetState(SCE_B_ASM
);}
177 else if (isoperator(static_cast<char>(sc
.ch
)) || (sc
.ch
== '\\')) {sc
.SetState(SCE_B_OPERATOR
);}
179 } //for (; sc.More(); sc.Forward())
183 //The folding routine for PowerBasic toggles SUBs and FUNCTIONs only. This was exactly what I wanted,
184 //nothing more. I had worked with this kind of toggling for several years when I used the great good old
185 //GFA Basic which is dead now. After testing the feature of toggling FOR-NEXT loops, WHILE-WEND loops
186 //and so on too I found this is more disturbing then helping (for me). So if You think in another way
187 //you can (or must) write Your own toggling routine ;-)
188 static void FoldPBDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
)
190 // No folding enabled, no reason to continue...
191 if( styler
.GetPropertyInt("fold") == 0 )
194 unsigned int endPos
= startPos
+ length
;
195 int lineCurrent
= styler
.GetLine(startPos
);
196 int levelCurrent
= SC_FOLDLEVELBASE
;
198 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
199 int levelNext
= levelCurrent
;
200 char chNext
= styler
[startPos
];
203 bool fMightBeMultiLineMacro
=false;
204 bool fBeginOfCommentFound
=false;
205 for (unsigned int i
= startPos
; i
< endPos
; i
++)
208 chNext
= styler
.SafeGetCharAt(i
+ 1);
210 if (fNewLine
) //Begin of a new line (The Sub/Function/Macro keywords may occur at begin of line only)
213 fBeginOfCommentFound
=false;
216 case ' ': //Most lines start with space - so check this first, the code is the same as for 'default:'
217 case '\t': //Handle tab too
219 int levelUse
= levelCurrent
;
220 int lev
= levelUse
| levelNext
<< 16;
221 styler
.SetLevel(lineCurrent
, lev
);
232 if( MatchUpperCase(styler
,i
,"FUNCTION") )
234 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
235 levelNext
=SC_FOLDLEVELBASE
+1;
250 if( MatchUpperCase(styler
,i
,"SUB") )
252 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
253 levelNext
=SC_FOLDLEVELBASE
+1;
260 if( MatchUpperCase(styler
,i
,"STATIC FUNCTION") )
262 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
263 levelNext
=SC_FOLDLEVELBASE
+1;
265 else if( MatchUpperCase(styler
,i
,"STATIC SUB") )
267 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
268 levelNext
=SC_FOLDLEVELBASE
+1;
283 if( MatchUpperCase(styler
,i
,"CALLBACK FUNCTION") )
285 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
286 levelNext
=SC_FOLDLEVELBASE
+1;
301 if( MatchUpperCase(styler
,i
,"MACRO") )
303 fMightBeMultiLineMacro
=true; //Set folder level at end of line, we have to check for single line macro
312 int levelUse
= levelCurrent
;
313 int lev
= levelUse
| levelNext
<< 16;
314 styler
.SetLevel(lineCurrent
, lev
);
322 case '=': //To test single line macros
324 if (fBeginOfCommentFound
==false)
325 fMightBeMultiLineMacro
=false; //The found macro is a single line macro only;
328 case '\'': //A comment starts
330 fBeginOfCommentFound
=true;
335 if (fMightBeMultiLineMacro
) //The current line is the begin of a multi line macro
337 fMightBeMultiLineMacro
=false;
338 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
339 levelNext
=SC_FOLDLEVELBASE
+1;
342 levelCurrent
= levelNext
;
351 levelCurrent
= levelNext
;
357 } //for (unsigned int i = startPos; i < endPos; i++)
360 static const char * const pbWordListDesc
[] = {
365 LexerModule
lmPB(SCLEX_POWERBASIC
, ColourisePBDoc
, "powerbasic", FoldPBDoc
, pbWordListDesc
);