]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexPB.cxx
7878a6bf8f0667414782da52b28dc043f70ad1fc
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"
51 static inline bool IsTypeCharacter(const int ch
)
53 return ch
== '%' || ch
== '&' || ch
== '@' || ch
== '!' || ch
== '#' || ch
== '$' || ch
== '?';
56 static inline bool IsAWordChar(const int ch
)
58 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
61 static inline bool IsAWordStart(const int ch
)
63 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
66 bool MatchUpperCase(Accessor
&styler
, int pos
, const char *s
) //Same as styler.Match() but uppercase comparison (a-z,A-Z and space only)
69 for (int i
=0; *s
; i
++)
71 ch
=styler
.SafeGetCharAt(pos
+i
);
72 if (ch
> 0x60) ch
-= '\x20';
73 if (*s
!= ch
) return false;
79 static void ColourisePBDoc(unsigned int startPos
, int length
, int initStyle
,WordList
*keywordlists
[],Accessor
&styler
) {
81 WordList
&keywords
= *keywordlists
[0];
83 styler
.StartAt(startPos
);
85 StyleContext
sc(startPos
, length
, initStyle
, styler
);
87 for (; sc
.More(); sc
.Forward()) {
92 sc
.SetState(SCE_B_DEFAULT
);
97 if (!IsAWordChar(sc
.ch
))
99 if (!IsTypeCharacter(sc
.ch
))
102 sc
.GetCurrentLowered(s
, sizeof(s
));
103 if (keywords
.InList(s
))
105 if (strcmp(s
, "rem") == 0)
107 sc
.ChangeState(SCE_B_COMMENT
);
108 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
110 else if (strcmp(s
, "asm") == 0)
112 sc
.ChangeState(SCE_B_ASM
);
113 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
117 sc
.SetState(SCE_B_DEFAULT
);
122 sc
.ChangeState(SCE_B_IDENTIFIER
);
123 sc
.SetState(SCE_B_DEFAULT
);
131 if (!IsAWordChar(sc
.ch
)) {sc
.SetState(SCE_B_DEFAULT
);}
136 if (sc
.ch
== '\"'){sc
.ForwardSetState(SCE_B_DEFAULT
);}
141 if (!IsAWordChar(sc
.ch
)) {sc
.SetState(SCE_B_DEFAULT
);}
146 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
151 if (sc
.atLineEnd
) {sc
.SetState(SCE_B_DEFAULT
);}
154 } //switch (sc.state)
156 // Determine if a new state should be entered:
157 if (sc
.state
== SCE_B_DEFAULT
)
159 if (sc
.ch
== '\'') {sc
.SetState(SCE_B_COMMENT
);}
160 else if (sc
.ch
== '\"') {sc
.SetState(SCE_B_STRING
);}
161 else if (sc
.ch
== '&' && tolower(sc
.chNext
) == 'h') {sc
.SetState(SCE_B_NUMBER
);}
162 else if (sc
.ch
== '&' && tolower(sc
.chNext
) == 'b') {sc
.SetState(SCE_B_NUMBER
);}
163 else if (sc
.ch
== '&' && tolower(sc
.chNext
) == 'o') {sc
.SetState(SCE_B_NUMBER
);}
164 else if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {sc
.SetState(SCE_B_NUMBER
);}
165 else if (IsAWordStart(sc
.ch
)) {sc
.SetState(SCE_B_KEYWORD
);}
166 else if (sc
.ch
== '%') {sc
.SetState(SCE_B_CONSTANT
);}
167 else if (sc
.ch
== '$') {sc
.SetState(SCE_B_CONSTANT
);}
168 else if (sc
.ch
== '#') {sc
.SetState(SCE_B_KEYWORD
);}
169 else if (sc
.ch
== '!') {sc
.SetState(SCE_B_ASM
);}
170 else if (isoperator(static_cast<char>(sc
.ch
)) || (sc
.ch
== '\\')) {sc
.SetState(SCE_B_OPERATOR
);}
172 } //for (; sc.More(); sc.Forward())
176 //The folding routine for PowerBasic toggles SUBs and FUNCTIONs only. This was exactly what I wanted,
177 //nothing more. I had worked with this kind of toggling for several years when I used the great good old
178 //GFA Basic which is dead now. After testing the feature of toggling FOR-NEXT loops, WHILE-WEND loops
179 //and so on too I found this is more disturbing then helping (for me). So if You think in another way
180 //you can (or must) write Your own toggling routine ;-)
181 static void FoldPBDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
)
183 // No folding enabled, no reason to continue...
184 if( styler
.GetPropertyInt("fold") == 0 )
187 unsigned int endPos
= startPos
+ length
;
188 int lineCurrent
= styler
.GetLine(startPos
);
189 int levelCurrent
= SC_FOLDLEVELBASE
;
191 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
192 int levelNext
= levelCurrent
;
193 char chNext
= styler
[startPos
];
196 bool fMightBeMultiLineMacro
=false;
197 bool fBeginOfCommentFound
=false;
198 for (unsigned int i
= startPos
; i
< endPos
; i
++)
201 chNext
= styler
.SafeGetCharAt(i
+ 1);
203 if (fNewLine
) //Begin of a new line (The Sub/Function/Macro keywords may occur at begin of line only)
206 fBeginOfCommentFound
=false;
209 case ' ': //Most lines start with space - so check this first, the code is the same as for 'default:'
210 case '\t': //Handle tab too
212 int levelUse
= levelCurrent
;
213 int lev
= levelUse
| levelNext
<< 16;
214 styler
.SetLevel(lineCurrent
, lev
);
225 if( MatchUpperCase(styler
,i
,"FUNCTION") )
227 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
228 levelNext
=SC_FOLDLEVELBASE
+1;
243 if( MatchUpperCase(styler
,i
,"SUB") )
245 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
246 levelNext
=SC_FOLDLEVELBASE
+1;
253 if( MatchUpperCase(styler
,i
,"STATIC FUNCTION") )
255 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
256 levelNext
=SC_FOLDLEVELBASE
+1;
258 else if( MatchUpperCase(styler
,i
,"STATIC SUB") )
260 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
261 levelNext
=SC_FOLDLEVELBASE
+1;
276 if( MatchUpperCase(styler
,i
,"CALLBACK FUNCTION") )
278 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
279 levelNext
=SC_FOLDLEVELBASE
+1;
294 if( MatchUpperCase(styler
,i
,"MACRO") )
296 fMightBeMultiLineMacro
=true; //Set folder level at end of line, we have to check for single line macro
305 int levelUse
= levelCurrent
;
306 int lev
= levelUse
| levelNext
<< 16;
307 styler
.SetLevel(lineCurrent
, lev
);
315 case '=': //To test single line macros
317 if (fBeginOfCommentFound
==false)
318 fMightBeMultiLineMacro
=false; //The found macro is a single line macro only;
321 case '\'': //A comment starts
323 fBeginOfCommentFound
=true;
328 if (fMightBeMultiLineMacro
) //The current line is the begin of a multi line macro
330 fMightBeMultiLineMacro
=false;
331 styler
.SetLevel(lineCurrent
, (SC_FOLDLEVELBASE
<< 16) | SC_FOLDLEVELHEADERFLAG
);
332 levelNext
=SC_FOLDLEVELBASE
+1;
335 levelCurrent
= levelNext
;
344 levelCurrent
= levelNext
;
350 } //for (unsigned int i = startPos; i < endPos; i++)
353 static const char * const pbWordListDesc
[] = {
358 LexerModule
lmPB(SCLEX_POWERBASIC
, ColourisePBDoc
, "powerbasic", FoldPBDoc
, pbWordListDesc
);