]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexPB.cxx
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.
46 #include "StyleContext.h"
48 #include "Scintilla.h"
52 using namespace Scintilla
;
55 static inline bool IsTypeCharacter(const int ch
)
57 return ch
== '%' || ch
== '&' || ch
== '@' || ch
== '!' || ch
== '#' || ch
== '$' || ch
== '?';
60 static inline bool IsAWordChar(const int ch
)
62 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
65 static inline bool IsAWordStart(const int ch
)
67 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
70 bool MatchUpperCase(Accessor
&styler
, int pos
, const char *s
) //Same as styler.Match() but uppercase comparison (a-z,A-Z and space only)
73 for (int i
=0; *s
; i
++)
75 ch
=styler
.SafeGetCharAt(pos
+i
);
76 if (ch
> 0x60) ch
-= '\x20';
77 if (*s
!= ch
) return false;
83 static void ColourisePBDoc(unsigned int startPos
, int length
, int initStyle
,WordList
*keywordlists
[],Accessor
&styler
) {
85 WordList
&keywords
= *keywordlists
[0];
87 styler
.StartAt(startPos
);
89 StyleContext
sc(startPos
, length
, initStyle
, styler
);
91 for (; sc
.More(); sc
.Forward()) {
96 sc
.SetState(SCE_B_DEFAULT
);
101 if (!IsAWordChar(sc
.ch
))
103 if (!IsTypeCharacter(sc
.ch
))
106 sc
.GetCurrentLowered(s
, sizeof(s
));
107 if (keywords
.InList(s
))
109 if (strcmp(s
, "rem") == 0)
111 sc
.ChangeState(SCE_B_COMMENT
);
112 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
114 else if (strcmp(s
, "asm") == 0)
116 sc
.ChangeState(SCE_B_ASM
);
117 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
121 sc
.SetState(SCE_B_DEFAULT
);
126 sc
.ChangeState(SCE_B_IDENTIFIER
);
127 sc
.SetState(SCE_B_DEFAULT
);
135 if (!IsAWordChar(sc
.ch
)) {sc
.SetState(SCE_B_DEFAULT
);}
140 if (sc
.ch
== '\"'){sc
.ForwardSetState(SCE_B_DEFAULT
);}
145 if (!IsAWordChar(sc
.ch
)) {sc
.SetState(SCE_B_DEFAULT
);}
150 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
155 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
158 } //switch (sc.state)
160 // Determine if a new state should be entered:
161 if (sc
.state
== SCE_B_DEFAULT
)
163 if (sc
.ch
== '\'') {sc
.SetState(SCE_B_COMMENT
);}
164 else if (sc
.ch
== '\"') {sc
.SetState(SCE_B_STRING
);}
165 else if (sc
.ch
== '&' && tolower(sc
.chNext
) == 'h') {sc
.SetState(SCE_B_NUMBER
);}
166 else if (sc
.ch
== '&' && tolower(sc
.chNext
) == 'b') {sc
.SetState(SCE_B_NUMBER
);}
167 else if (sc
.ch
== '&' && tolower(sc
.chNext
) == 'o') {sc
.SetState(SCE_B_NUMBER
);}
168 else if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {sc
.SetState(SCE_B_NUMBER
);}
169 else if (IsAWordStart(sc
.ch
)) {sc
.SetState(SCE_B_KEYWORD
);}
170 else if (sc
.ch
== '%') {sc
.SetState(SCE_B_CONSTANT
);}
171 else if (sc
.ch
== '$') {sc
.SetState(SCE_B_CONSTANT
);}
172 else if (sc
.ch
== '#') {sc
.SetState(SCE_B_KEYWORD
);}
173 else if (sc
.ch
== '!') {sc
.SetState(SCE_B_ASM
);}
174 else if (isoperator(static_cast<char>(sc
.ch
)) || (sc
.ch
== '\\')) {sc
.SetState(SCE_B_OPERATOR
);}
176 } //for (; sc.More(); sc.Forward())
180 //The folding routine for PowerBasic toggles SUBs and FUNCTIONs only. This was exactly what I wanted,
181 //nothing more. I had worked with this kind of toggling for several years when I used the great good old
182 //GFA Basic which is dead now. After testing the feature of toggling FOR-NEXT loops, WHILE-WEND loops
183 //and so on too I found this is more disturbing then helping (for me). So if You think in another way
184 //you can (or must) write Your own toggling routine ;-)
185 static void FoldPBDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
)
187 // No folding enabled, no reason to continue...
188 if( styler
.GetPropertyInt("fold") == 0 )
191 unsigned int endPos
= startPos
+ length
;
192 int lineCurrent
= styler
.GetLine(startPos
);
193 int levelCurrent
= SC_FOLDLEVELBASE
;
195 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
196 int levelNext
= levelCurrent
;
197 char chNext
= styler
[startPos
];
200 bool fMightBeMultiLineMacro
=false;
201 bool fBeginOfCommentFound
=false;
202 for (unsigned int i
= startPos
; i
< endPos
; i
++)
205 chNext
= styler
.SafeGetCharAt(i
+ 1);
207 if (fNewLine
) //Begin of a new line (The Sub/Function/Macro keywords may occur at begin of line only)
210 fBeginOfCommentFound
=false;
213 case ' ': //Most lines start with space - so check this first, the code is the same as for 'default:'
214 case '\t': //Handle tab too
216 int levelUse
= levelCurrent
;
217 int lev
= levelUse
| levelNext
<< 16;
218 styler
.SetLevel(lineCurrent
, lev
);
229 if( MatchUpperCase(styler
,i
,"FUNCTION") )
231 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
232 levelNext
=SC_FOLDLEVELBASE
+1;
247 if( MatchUpperCase(styler
,i
,"SUB") )
249 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
250 levelNext
=SC_FOLDLEVELBASE
+1;
257 if( MatchUpperCase(styler
,i
,"STATIC FUNCTION") )
259 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
260 levelNext
=SC_FOLDLEVELBASE
+1;
262 else if( MatchUpperCase(styler
,i
,"STATIC SUB") )
264 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
265 levelNext
=SC_FOLDLEVELBASE
+1;
280 if( MatchUpperCase(styler
,i
,"CALLBACK FUNCTION") )
282 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
283 levelNext
=SC_FOLDLEVELBASE
+1;
298 if( MatchUpperCase(styler
,i
,"MACRO") )
300 fMightBeMultiLineMacro
=true; //Set folder level at end of line, we have to check for single line macro
309 int levelUse
= levelCurrent
;
310 int lev
= levelUse
| levelNext
<< 16;
311 styler
.SetLevel(lineCurrent
, lev
);
319 case '=': //To test single line macros
321 if (fBeginOfCommentFound
==false)
322 fMightBeMultiLineMacro
=false; //The found macro is a single line macro only;
325 case '\'': //A comment starts
327 fBeginOfCommentFound
=true;
332 if (fMightBeMultiLineMacro
) //The current line is the begin of a multi line macro
334 fMightBeMultiLineMacro
=false;
335 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
336 levelNext
=SC_FOLDLEVELBASE
+1;
339 levelCurrent
= levelNext
;
348 levelCurrent
= levelNext
;
354 } //for (unsigned int i = startPos; i < endPos; i++)
357 static const char * const pbWordListDesc
[] = {
362 LexerModule
lmPB(SCLEX_POWERBASIC
, ColourisePBDoc
, "powerbasic", FoldPBDoc
, pbWordListDesc
);