18
16
#include "PropSet.h"
19
17
#include "Accessor.h"
18
#include "StyleContext.h"
20
19
#include "KeyWords.h"
21
20
#include "Scintilla.h"
22
21
#include "SciLexer.h"
24
bool is_whitespace(int ch){
25
return ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ';
28
bool is_blank(int ch){
29
return ch == '\t' || ch == ' ';
34
#define log(x) fputs(f_debug,x);
43
static int cur_pos,pos1,pos2,pos0,lengthDoc;
46
char getChar(bool is_bl){
47
char ch=st->SafeGetCharAt(cur_pos);
48
if(is_bl) if(is_whitespace(ch)) ch=BL;
53
char ch=st->SafeGetCharAt(cur_pos);
57
return ch=='\n' || ch=='\r';
60
int parse(char ch, bool skip_eol){
61
// pos1 - start pos of word
62
// pos2 - pos after of word
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){
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;
85
fprintf(f_debug,"parse: %c %s\n",ch,buffer);
90
bool _is_number(char *s,int base){
92
int digit=((int)*s)-(int)'0';
94
fprintf(f_debug,"digit: %c %d\n",*s,digit);
96
if(digit>9 && base>10) digit-=7;
97
if(digit<0) return false;
98
if(digit>=base) return false;
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);
108
static void ColouriseForthDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
112
lengthDoc = startPos + length;
113
buffer = new char[length];
116
f_debug=fopen("c:\\sci.log","at");
24
using namespace Scintilla;
27
static inline bool IsAWordChar(int ch) {
28
return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
29
ch == '_' || ch == '?' || ch == '"' || ch == '@' ||
30
ch == '!' || ch == '[' || ch == ']' || ch == '/' ||
31
ch == '+' || ch == '-' || ch == '*' || ch == '<' ||
32
ch == '>' || ch == '=' || ch == ';' || ch == '(' ||
36
static inline bool IsAWordStart(int ch) {
37
return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
40
static inline bool IsANumChar(int ch) {
41
return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' );
44
static inline bool IsASpaceChar(int ch) {
45
return (ch < 0x80) && isspace(ch);
48
static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[],
119
51
WordList &control = *keywordLists[0];
120
52
WordList &keyword = *keywordLists[1];
123
55
WordList &preword2 = *keywordLists[4];
124
56
WordList &strings = *keywordLists[5];
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){
132
styler.ColourTo(pos0,SCE_FORTH_DEFAULT);
133
styler.ColourTo(pos1-1,SCE_FORTH_DEFAULT);
135
if(strcmp("\\",buffer)==0){
136
styler.ColourTo(pos1,SCE_FORTH_COMMENT);
138
styler.ColourTo(pos2,SCE_FORTH_COMMENT);
139
}else if(strcmp("(",buffer)==0){
140
styler.ColourTo(pos1,SCE_FORTH_COMMENT);
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);
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);
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);
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);
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);
175
styler.ColourTo(pos2,SCE_FORTH_PREWORD1);
176
}else if(preword2.InList(buffer)) {
177
styler.ColourTo(pos1,SCE_FORTH_PREWORD2);
179
styler.ColourTo(pos2,SCE_FORTH_PREWORD2);
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);
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 );
207
styler.ColourTo(i-1,SCE_FORTH_DEFAULT);
212
for (int i = startPos; i < lengthDoc; i++) {
214
chNext = styler.SafeGetCharAt(i + 1);
215
if(i!=startPos) chPrev=styler.SafeGetCharAt(i - 1);
217
if (styler.IsLeadByte(ch)) {
218
chNext = styler.SafeGetCharAt(i + 2);
223
fprintf(f_debug,"%c %d ",ch,state);
226
case SCE_FORTH_DEFAULT:
227
if(is_whitespace(ch)) {
228
// whitespace is simply ignored here...
229
styler.ColourTo(i,SCE_FORTH_DEFAULT);
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
242
buffer[bufferCount++] = ch;
243
state = SCE_FORTH_NUMBER;
244
} else if( !is_whitespace(ch)) {
245
// signals the start of an identifier
247
buffer[bufferCount++] = ch;
248
state = SCE_FORTH_IDENTIFIER;
250
// style it the default style..
251
styler.ColourTo(i,SCE_FORTH_DEFAULT);
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;
262
styler.ColourTo(i,SCE_FORTH_COMMENT);
266
case SCE_FORTH_COMMENT_ML:
268
state = SCE_FORTH_DEFAULT;
270
styler.ColourTo(i+1,SCE_FORTH_COMMENT_ML);
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;
279
state = SCE_FORTH_DEFAULT;
280
buffer[bufferCount] = '\0';
282
fprintf(f_debug,"\nid %s\n",buffer);
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 );
302
styler.ColourTo(i-1,SCE_FORTH_DEFAULT);
307
// push back the faulty character
308
chNext = styler[i--];
312
case SCE_FORTH_NUMBER:
313
// stay in CONF_NUMBER state until we find a non-numeric
315
buffer[bufferCount++] = ch;
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--];
58
StyleContext sc(startPos, length, initStyle, styler);
60
for (; sc.More(); sc.Forward())
62
// Determine if the current state should terminate.
63
if (sc.state == SCE_FORTH_COMMENT) {
65
sc.SetState(SCE_FORTH_DEFAULT);
67
}else if (sc.state == SCE_FORTH_COMMENT_ML) {
69
sc.ForwardSetState(SCE_FORTH_DEFAULT);
71
}else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) {
72
// handle numbers here too, because what we thought was a number might
73
// turn out to be a keyword e.g. 2DUP
74
if (IsASpaceChar(sc.ch) ) {
76
sc.GetCurrentLowered(s, sizeof(s));
77
int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT;
78
if (control.InList(s)) {
79
sc.ChangeState(SCE_FORTH_CONTROL);
80
} else if (keyword.InList(s)) {
81
sc.ChangeState(SCE_FORTH_KEYWORD);
82
} else if (defword.InList(s)) {
83
sc.ChangeState(SCE_FORTH_DEFWORD);
84
} else if (preword1.InList(s)) {
85
sc.ChangeState(SCE_FORTH_PREWORD1);
86
} else if (preword2.InList(s)) {
87
sc.ChangeState(SCE_FORTH_PREWORD2);
88
} else if (strings.InList(s)) {
89
sc.ChangeState(SCE_FORTH_STRING);
90
newState = SCE_FORTH_STRING;
92
sc.SetState(newState);
94
if (sc.state == SCE_FORTH_NUMBER) {
95
if (IsASpaceChar(sc.ch)) {
96
sc.SetState(SCE_FORTH_DEFAULT);
97
} else if (!IsANumChar(sc.ch)) {
98
sc.ChangeState(SCE_FORTH_IDENTIFIER);
101
}else if (sc.state == SCE_FORTH_STRING) {
103
sc.ForwardSetState(SCE_FORTH_DEFAULT);
105
}else if (sc.state == SCE_FORTH_LOCALE) {
107
sc.ForwardSetState(SCE_FORTH_DEFAULT);
109
}else if (sc.state == SCE_FORTH_DEFWORD) {
110
if (IsASpaceChar(sc.ch)) {
111
sc.SetState(SCE_FORTH_DEFAULT);
115
// Determine if a new state should be entered.
116
if (sc.state == SCE_FORTH_DEFAULT) {
118
sc.SetState(SCE_FORTH_COMMENT);
119
} else if (sc.ch == '(' &&
120
(sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
121
(sc.atLineEnd || IsASpaceChar(sc.chNext))) {
122
sc.SetState(SCE_FORTH_COMMENT_ML);
123
} else if ( (sc.ch == '$' && (isascii(sc.chNext) && isxdigit(sc.chNext))) ) {
124
// number starting with $ is a hex number
125
sc.SetState(SCE_FORTH_NUMBER);
126
while(sc.More() && isascii(sc.chNext) && isxdigit(sc.chNext))
128
} else if ( (sc.ch == '%' && (isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) {
129
// number starting with % is binary
130
sc.SetState(SCE_FORTH_NUMBER);
131
while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))
133
} else if ( isascii(sc.ch) &&
134
(isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) )
136
sc.SetState(SCE_FORTH_NUMBER);
137
} else if (IsAWordStart(sc.ch)) {
138
sc.SetState(SCE_FORTH_IDENTIFIER);
139
} else if (sc.ch == '{') {
140
sc.SetState(SCE_FORTH_LOCALE);
141
} else if (sc.ch == ':' && isascii(sc.chNext) && isspace(sc.chNext)) {
142
// highlight word definitions e.g. : GCD ( n n -- n ) ..... ;
144
sc.SetState(SCE_FORTH_DEFWORD);
145
while(sc.More() && isascii(sc.chNext) && isspace(sc.chNext))
147
} else if (sc.ch == ';' &&
148
(sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
149
(sc.atLineEnd || IsASpaceChar(sc.chNext)) ) {
150
// mark the ';' that ends a word
151
sc.SetState(SCE_FORTH_DEFWORD);
152
sc.ForwardSetState(SCE_FORTH_DEFAULT);
334
160
static void FoldForthDoc(unsigned int, int, int, WordList *[],
338
164
static const char * const forthWordLists[] = {
342
"prewords with one argument",
343
"prewords with two arguments",
344
"string definition keywords",
348
LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth",FoldForthDoc,forthWordLists);
168
"prewords with one argument",
169
"prewords with two arguments",
170
"string definition keywords",
174
LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists);