]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexPB.cxx
d35944ecf7caebef022ff8a0aeea2041025f9b1e
[wxWidgets.git] / src / stc / scintilla / src / LexPB.cxx
1 // Scintilla source code edit control
2 /** @file LexPB.cxx
3 ** Lexer for PowerBasic by Roland Walter, roland@rowalt.de
4 ** Last update: 17.10.2003 (toggling of subs/functions now until next sub/functin - this gives better results)
5 **/
6 //
7 // Necessary changes in Scintilla project:
8 // - In SciLexer.h and Scintilla.iface:
9 //
10 // #define SCLEX_PB 51 //ID for PowerBasic lexer
11 // (...)
12 // #define SCE_B_DEFAULT 0 //in both VB and PB lexer
13 // #define SCE_B_COMMENT 1 //in both VB and PB lexer
14 // #define SCE_B_NUMBER 2 //in both VB and PB lexer
15 // #define SCE_B_KEYWORD 3 //in both VB and PB lexer
16 // #define SCE_B_STRING 4 //in both VB and PB lexer
17 // #define SCE_B_PREPROCESSOR 5 //VB lexer only, unsupported by PB lexer
18 // #define SCE_B_OPERATOR 6 //in both VB and PB lexer
19 // #define SCE_B_IDENTIFIER 7 //in both VB and PB lexer
20 // #define SCE_B_DATE 8 //VB lexer only, unsupported by PB lexer
21
22 // - Statement added to KeyWords.cxx: 'LINK_LEXER(lmPB);'
23 // - Statement added to scintilla_vc6.mak: '$(DIR_O)\LexPB.obj: ...\src\LexPB.cxx $(LEX_HEADERS)'
24 //
25 // Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org>
26 // The License.txt file describes the conditions under which this software may be distributed.
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33
34 #include "Platform.h"
35
36 #include "PropSet.h"
37 #include "Accessor.h"
38 #include "StyleContext.h"
39 #include "KeyWords.h"
40 #include "Scintilla.h"
41 #include "SciLexer.h"
42
43 static inline bool IsTypeCharacter(const int ch) {
44 return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$';
45 }
46
47 static inline bool IsAWordChar(const int ch) {
48 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
49 }
50
51 static inline bool IsAWordStart(const int ch) {
52 return (ch < 0x80) && (isalnum(ch) || ch == '_');
53 }
54
55 bool MatchUpperCase(Accessor &styler, int pos, const char *s) //Same as styler.Match() but uppercase comparison (a-z,A-Z and space only)
56 {
57 char ch;
58 for (int i=0; *s; i++)
59 {
60 ch=styler.SafeGetCharAt(pos+i);
61 if (ch > 0x60) ch -= '\x20';
62 if (*s != ch) return false;
63 s++;
64 }
65 return true;
66 }
67
68 static void ColourisePBDoc(unsigned int startPos, int length, int initStyle,WordList *keywordlists[],
69 Accessor &styler) {
70
71 WordList &keywords = *keywordlists[0];
72
73 styler.StartAt(startPos);
74
75 StyleContext sc(startPos, length, initStyle, styler);
76
77 for (; sc.More(); sc.Forward()) {
78
79 if (sc.state == SCE_B_OPERATOR)
80 {
81 sc.SetState(SCE_B_DEFAULT);
82 }
83 else if (sc.state == SCE_B_KEYWORD)
84 {
85 if (!IsAWordChar(sc.ch))
86 {
87 if (!IsTypeCharacter(sc.ch))
88 {
89 if (sc.ch == ']') {sc.Forward();}
90 char s[100];
91 sc.GetCurrentLowered(s, sizeof(s));
92 if (keywords.InList(s))
93 {
94 if (strcmp(s, "rem") == 0)
95 {
96 sc.ChangeState(SCE_B_COMMENT);
97 if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
98 }
99 else
100 {
101 sc.SetState(SCE_B_DEFAULT);
102 }
103 }
104 else
105 {
106 sc.ChangeState(SCE_B_IDENTIFIER);
107 sc.SetState(SCE_B_DEFAULT);
108 }
109 }
110 }
111 }
112 else if (sc.state == SCE_B_NUMBER)
113 {
114 if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_B_DEFAULT);}
115 }
116 else if (sc.state == SCE_B_STRING)
117 {
118 // PB doubles quotes to preserve them, so just end this string
119 // state now as a following quote will start again
120 if (sc.ch == '\"')
121 {
122 if (tolower(sc.chNext) == 'c') {sc.Forward();}
123 sc.ForwardSetState(SCE_B_DEFAULT);
124 }
125 }
126 else if (sc.state == SCE_B_COMMENT)
127 {
128 if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
129 }
130
131 if (sc.state == SCE_B_DEFAULT)
132 {
133 if (sc.ch == '\'') {sc.SetState(SCE_B_COMMENT);}
134 else if (sc.ch == '\"') {sc.SetState(SCE_B_STRING);}
135 else if (sc.ch == '#')
136 { int n = 1;
137 int chSeek = ' ';
138 while ((n < 100) && (chSeek == ' ' || chSeek == '\t'))
139 {
140 chSeek = sc.GetRelative(n);
141 n++;
142 }
143 sc.SetState(SCE_B_OPERATOR);
144 }
145 else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {sc.SetState(SCE_B_NUMBER);}
146 else if (sc.ch == '&' && tolower(sc.chNext) == 'b') {sc.SetState(SCE_B_NUMBER);}
147 else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {sc.SetState(SCE_B_NUMBER);}
148 else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_B_NUMBER);}
149 else if (IsAWordStart(sc.ch) || (sc.ch == '[')) {sc.SetState(SCE_B_KEYWORD);}
150 else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {sc.SetState(SCE_B_OPERATOR);}
151 }
152
153 }
154 sc.Complete();
155 }
156
157 static void FoldPBDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
158 {
159 // No folding enabled, no reason to continue...
160 if( styler.GetPropertyInt("fold") == 0 )
161 return;
162
163 unsigned int endPos = startPos + length;
164 int lineCurrent = styler.GetLine(startPos);
165 int levelCurrent = SC_FOLDLEVELBASE;
166 if (lineCurrent > 0)
167 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
168 int levelNext = levelCurrent;
169 char chNext = styler[startPos];
170
171 bool atEOL=1;
172 for (unsigned int i = startPos; i < endPos; i++)
173 {
174 char ch = chNext;
175 chNext = styler.SafeGetCharAt(i + 1);
176
177 if( atEOL ) //Begin of a new line (The Sub/Function/Macro keywords may occur at begin of line only)
178 {
179 if( MatchUpperCase(styler,i,"FUNCTION") ) //else if(
180 {
181 styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
182 levelNext=SC_FOLDLEVELBASE+1;
183 }
184 else if( MatchUpperCase(styler,i,"CALLBACK FUNCTION") )
185 {
186 styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
187 levelNext=SC_FOLDLEVELBASE+1;
188 }
189 else if( MatchUpperCase(styler,i,"STATIC FUNCTION") )
190 {
191 styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
192 levelNext=SC_FOLDLEVELBASE+1;
193 }
194 else if( MatchUpperCase(styler,i,"SUB") )
195 {
196 styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
197 levelNext=SC_FOLDLEVELBASE+1;
198 }
199 else if( MatchUpperCase(styler,i,"STATIC SUB") )
200 {
201 styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
202 levelNext=SC_FOLDLEVELBASE+1;
203 }
204 //else if( MatchUpperCase(styler,i,"MACRO") ) //ToDo: What's with single-line macros?
205 }
206
207 atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
208 if( atEOL )
209 {
210 lineCurrent++;
211 levelCurrent = levelNext;
212 }
213 }
214
215 if (levelNext == SC_FOLDLEVELBASE)
216 {
217 int levelUse = levelCurrent;
218 int lev = levelUse | levelNext << 16;
219 styler.SetLevel(lineCurrent, lev);
220 }
221 }
222
223 static const char * const pbWordListDesc[] = {
224 "Keywords",
225 0
226 };
227
228 LexerModule lmPB(SCLEX_POWERBASIC, ColourisePBDoc, "powerbasic", FoldPBDoc, pbWordListDesc);