]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexForth.cxx
Cast to void* before casting to Node** to make the compiler do no strict-aliasing...
[wxWidgets.git] / contrib / src / stc / scintilla / src / LexForth.cxx
1 // Scintilla source code edit control
2 /** @file LexCrontab.cxx
3 ** Lexer to use with extended crontab files used by a powerful
4 ** Windows scheduler/event monitor/automation manager nnCron.
5 ** (http://nemtsev.eserv.ru/)
6 **/
7 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
8 // The License.txt file describes the conditions under which this software may be distributed.
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <stdio.h>
14 #include <stdarg.h>
15
16 #include "Platform.h"
17
18 #include "PropSet.h"
19 #include "Accessor.h"
20 #include "KeyWords.h"
21 #include "Scintilla.h"
22 #include "SciLexer.h"
23
24 bool is_whitespace(int ch){
25 return ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ';
26 }
27
28 bool is_blank(int ch){
29 return ch == '\t' || ch == ' ';
30 }
31 //#define FORTH_DEBUG
32 #ifdef FORTH_DEBUG
33 static FILE *f_debug;
34 #define log(x) fputs(f_debug,x);
35 #else
36 #define log(x)
37 #endif
38
39 #define STATE_LOCALE
40 #define BL ' '
41
42 static Accessor *st;
43 static int cur_pos,pos1,pos2,pos0,lengthDoc;
44 char *buffer;
45
46 char getChar(bool is_bl){
47 char ch=st->SafeGetCharAt(cur_pos);
48 if(is_bl) if(is_whitespace(ch)) ch=BL;
49 return ch;
50 }
51
52 char getCharBL(){
53 char ch=st->SafeGetCharAt(cur_pos);
54 return ch;
55 }
56 bool is_eol(char ch){
57 return ch=='\n' || ch=='\r';
58 }
59
60 int parse(char ch, bool skip_eol){
61 // pos1 - start pos of word
62 // pos2 - pos after of word
63 // pos0 - start pos
64 char c=0;
65 int len;
66 bool is_bl=ch==BL;
67 pos0=pos1=pos2=cur_pos;
68 for(;cur_pos<lengthDoc && (c=getChar(is_bl))==ch; cur_pos++){
69 if(is_eol(c) && !skip_eol){
70 pos2=pos1;
71 return 0;
72 }
73 }
74 pos1=cur_pos;
75 pos2=pos1;
76 if(cur_pos==lengthDoc) return 0;
77 for(len=0;cur_pos<lengthDoc && (c=getChar(is_bl))!=ch; cur_pos++){
78 if(is_eol(c) && !skip_eol) break;
79 pos2++;
80 buffer[len++]=c;
81 }
82 if(c==ch) pos2--;
83 buffer[len]='\0';
84 #ifdef FORTH_DEBUG
85 fprintf(f_debug,"parse: %c %s\n",ch,buffer);
86 #endif
87 return len;
88 }
89
90 bool _is_number(char *s,int base){
91 for(;*s;s++){
92 int digit=((int)*s)-(int)'0';
93 #ifdef FORTH_DEBUG
94 fprintf(f_debug,"digit: %c %d\n",*s,digit);
95 #endif
96 if(digit>9 && base>10) digit-=7;
97 if(digit<0) return false;
98 if(digit>=base) return false;
99 }
100 return true;
101 }
102
103 bool is_number(char *s){
104 if(strncmp(s,"0x",2)==0) return _is_number(s+2,16);
105 return _is_number(s,10);
106 }
107
108 static void ColouriseForthDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
109 {
110 st=&styler;
111 cur_pos=startPos;
112 lengthDoc = startPos + length;
113 buffer = new char[length];
114
115 #ifdef FORTH_DEBUG
116 f_debug=fopen("c:\\sci.log","at");
117 #endif
118
119 WordList &control = *keywordLists[0];
120 WordList &keyword = *keywordLists[1];
121 WordList &defword = *keywordLists[2];
122 WordList &preword1 = *keywordLists[3];
123 WordList &preword2 = *keywordLists[4];
124 WordList &strings = *keywordLists[5];
125
126 // go through all provided text segment
127 // using the hand-written state machine shown below
128 styler.StartAt(startPos);
129 styler.StartSegment(startPos);
130 while(parse(BL,true)!=0){
131 if(pos0!=pos1){
132 styler.ColourTo(pos0,SCE_FORTH_DEFAULT);
133 styler.ColourTo(pos1-1,SCE_FORTH_DEFAULT);
134 }
135 if(strcmp("\\",buffer)==0){
136 styler.ColourTo(pos1,SCE_FORTH_COMMENT);
137 parse(1,false);
138 styler.ColourTo(pos2,SCE_FORTH_COMMENT);
139 }else if(strcmp("(",buffer)==0){
140 styler.ColourTo(pos1,SCE_FORTH_COMMENT);
141 parse(')',true);
142 if(cur_pos<lengthDoc) cur_pos++;
143 styler.ColourTo(cur_pos,SCE_FORTH_COMMENT);
144 }else if(strcmp("[",buffer)==0){
145 styler.ColourTo(pos1,SCE_FORTH_STRING);
146 parse(']',true);
147 if(cur_pos<lengthDoc) cur_pos++;
148 styler.ColourTo(cur_pos,SCE_FORTH_STRING);
149 }else if(strcmp("{",buffer)==0){
150 styler.ColourTo(pos1,SCE_FORTH_LOCALE);
151 parse('}',false);
152 if(cur_pos<lengthDoc) cur_pos++;
153 styler.ColourTo(cur_pos,SCE_FORTH_LOCALE);
154 }else if(strings.InList(buffer)) {
155 styler.ColourTo(pos1,SCE_FORTH_STRING);
156 parse('"',false);
157 if(cur_pos<lengthDoc) cur_pos++;
158 styler.ColourTo(cur_pos,SCE_FORTH_STRING);
159 }else if(control.InList(buffer)) {
160 styler.ColourTo(pos1,SCE_FORTH_CONTROL);
161 styler.ColourTo(pos2,SCE_FORTH_CONTROL);
162 }else if(keyword.InList(buffer)) {
163 styler.ColourTo(pos1,SCE_FORTH_KEYWORD);
164 styler.ColourTo(pos2,SCE_FORTH_KEYWORD);
165 }else if(defword.InList(buffer)) {
166 styler.ColourTo(pos1,SCE_FORTH_KEYWORD);
167 styler.ColourTo(pos2,SCE_FORTH_KEYWORD);
168 parse(BL,false);
169 styler.ColourTo(pos1-1,SCE_FORTH_DEFAULT);
170 styler.ColourTo(pos1,SCE_FORTH_DEFWORD);
171 styler.ColourTo(pos2,SCE_FORTH_DEFWORD);
172 }else if(preword1.InList(buffer)) {
173 styler.ColourTo(pos1,SCE_FORTH_PREWORD1);
174 parse(BL,false);
175 styler.ColourTo(pos2,SCE_FORTH_PREWORD1);
176 }else if(preword2.InList(buffer)) {
177 styler.ColourTo(pos1,SCE_FORTH_PREWORD2);
178 parse(BL,false);
179 styler.ColourTo(pos2,SCE_FORTH_PREWORD2);
180 parse(BL,false);
181 styler.ColourTo(pos1,SCE_FORTH_STRING);
182 styler.ColourTo(pos2,SCE_FORTH_STRING);
183 }else if(is_number(buffer)){
184 styler.ColourTo(pos1,SCE_FORTH_NUMBER);
185 styler.ColourTo(pos2,SCE_FORTH_NUMBER);
186 }
187 }
188 #ifdef FORTH_DEBUG
189 fclose(f_debug);
190 #endif
191 delete []buffer;
192 return;
193 /*
194 if(control.InList(buffer)) {
195 styler.ColourTo(i,SCE_FORTH_CONTROL);
196 } else if(keyword.InList(buffer)) {
197 styler.ColourTo(i-1,SCE_FORTH_KEYWORD );
198 } else if(defword.InList(buffer)) {
199 styler.ColourTo(i-1,SCE_FORTH_DEFWORD );
200 // prev_state=SCE_FORTH_DEFWORD
201 } else if(preword1.InList(buffer)) {
202 styler.ColourTo(i-1,SCE_FORTH_PREWORD1 );
203 // state=SCE_FORTH_PREWORD1;
204 } else if(preword2.InList(buffer)) {
205 styler.ColourTo(i-1,SCE_FORTH_PREWORD2 );
206 } else {
207 styler.ColourTo(i-1,SCE_FORTH_DEFAULT);
208 }
209 */
210 /*
211 chPrev=' ';
212 for (int i = startPos; i < lengthDoc; i++) {
213 char ch = chNext;
214 chNext = styler.SafeGetCharAt(i + 1);
215 if(i!=startPos) chPrev=styler.SafeGetCharAt(i - 1);
216
217 if (styler.IsLeadByte(ch)) {
218 chNext = styler.SafeGetCharAt(i + 2);
219 i++;
220 continue;
221 }
222 #ifdef FORTH_DEBUG
223 fprintf(f_debug,"%c %d ",ch,state);
224 #endif
225 switch(state) {
226 case SCE_FORTH_DEFAULT:
227 if(is_whitespace(ch)) {
228 // whitespace is simply ignored here...
229 styler.ColourTo(i,SCE_FORTH_DEFAULT);
230 break;
231 } else if( ch == '\\' && is_blank(chNext)) {
232 // signals the start of an one line comment...
233 state = SCE_FORTH_COMMENT;
234 styler.ColourTo(i,SCE_FORTH_COMMENT);
235 } else if( is_whitespace(chPrev) && ch == '(' && is_whitespace(chNext)) {
236 // signals the start of a plain comment...
237 state = SCE_FORTH_COMMENT_ML;
238 styler.ColourTo(i,SCE_FORTH_COMMENT_ML);
239 } else if( isdigit(ch) ) {
240 // signals the start of a number
241 bufferCount = 0;
242 buffer[bufferCount++] = ch;
243 state = SCE_FORTH_NUMBER;
244 } else if( !is_whitespace(ch)) {
245 // signals the start of an identifier
246 bufferCount = 0;
247 buffer[bufferCount++] = ch;
248 state = SCE_FORTH_IDENTIFIER;
249 } else {
250 // style it the default style..
251 styler.ColourTo(i,SCE_FORTH_DEFAULT);
252 }
253 break;
254
255 case SCE_FORTH_COMMENT:
256 // if we find a newline here,
257 // we simply go to default state
258 // else continue to work on it...
259 if( ch == '\n' || ch == '\r' ) {
260 state = SCE_FORTH_DEFAULT;
261 } else {
262 styler.ColourTo(i,SCE_FORTH_COMMENT);
263 }
264 break;
265
266 case SCE_FORTH_COMMENT_ML:
267 if( ch == ')') {
268 state = SCE_FORTH_DEFAULT;
269 } else {
270 styler.ColourTo(i+1,SCE_FORTH_COMMENT_ML);
271 }
272 break;
273
274 case SCE_FORTH_IDENTIFIER:
275 // stay in CONF_IDENTIFIER state until we find a non-alphanumeric
276 if( !is_whitespace(ch) ) {
277 buffer[bufferCount++] = ch;
278 } else {
279 state = SCE_FORTH_DEFAULT;
280 buffer[bufferCount] = '\0';
281 #ifdef FORTH_DEBUG
282 fprintf(f_debug,"\nid %s\n",buffer);
283 #endif
284
285 // check if the buffer contains a keyword,
286 // and highlight it if it is a keyword...
287 // switch(prev_state)
288 // case SCE_FORTH_DEFAULT:
289 if(control.InList(buffer)) {
290 styler.ColourTo(i,SCE_FORTH_CONTROL);
291 } else if(keyword.InList(buffer)) {
292 styler.ColourTo(i-1,SCE_FORTH_KEYWORD );
293 } else if(defword.InList(buffer)) {
294 styler.ColourTo(i-1,SCE_FORTH_DEFWORD );
295 // prev_state=SCE_FORTH_DEFWORD
296 } else if(preword1.InList(buffer)) {
297 styler.ColourTo(i-1,SCE_FORTH_PREWORD1 );
298 // state=SCE_FORTH_PREWORD1;
299 } else if(preword2.InList(buffer)) {
300 styler.ColourTo(i-1,SCE_FORTH_PREWORD2 );
301 } else {
302 styler.ColourTo(i-1,SCE_FORTH_DEFAULT);
303 }
304 // break;
305 // case
306
307 // push back the faulty character
308 chNext = styler[i--];
309 }
310 break;
311
312 case SCE_FORTH_NUMBER:
313 // stay in CONF_NUMBER state until we find a non-numeric
314 if( isdigit(ch) ) {
315 buffer[bufferCount++] = ch;
316 } else {
317 state = SCE_FORTH_DEFAULT;
318 buffer[bufferCount] = '\0';
319 // Colourize here... (normal number)
320 styler.ColourTo(i-1,SCE_FORTH_NUMBER);
321 // push back a character
322 chNext = styler[i--];
323 }
324 break;
325 }
326 }
327 #ifdef FORTH_DEBUG
328 fclose(f_debug);
329 #endif
330 delete []buffer;
331 */
332 }
333
334 static void FoldForthDoc(unsigned int, int, int, WordList *[],
335 Accessor &) {
336 }
337
338 static const char * const forthWordLists[] = {
339 "control keywords",
340 "keywords",
341 "definition words",
342 "prewords with one argument",
343 "prewords with two arguments",
344 "string definition keywords",
345 0,
346 };
347
348 LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth",FoldForthDoc,forthWordLists);