]>
Commit | Line | Data |
---|---|---|
8e54aaed RD |
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); |