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