1 // Scintilla source code edit control
2 /** @file LexBaan.cxx
3 ** Lexer for Baan.
4 ** Based heavily on LexCPP.cxx
5 **/
6 // Copyright 2001- by Vamsi Potluru <vamsi@who.net> & Praveen Ambekar <ambekarpraveen@yahoo.com>
7 // Maintainer Email: oirfeodent@yahoo.co.in
8 // The License.txt file describes the conditions under which this software may be distributed.
9
10 // C standard library
11 #include <stdlib.h>
12 #include <string.h>
13
14 // C++ wrappers of C standard library
15 #include <cassert>
16
17 // C++ standard library
18 #include <string>
19 #include <map>
20
21 // Scintilla headers
22
23 // Non-platform-specific headers
24
25 // include
26 #include "ILexer.h"
27 #include "Scintilla.h"
28 #include "SciLexer.h"
29
30 // lexlib
31 #include "WordList.h"
32 #include "LexAccessor.h"
33 #include "StyleContext.h"
34 #include "CharacterSet.h"
35 #include "LexerModule.h"
36 #include "OptionSet.h"
37 #include "DefaultLexer.h"
38
39 using namespace Scintilla;
40
41 namespace {
42 // Use an unnamed namespace to protect the functions and classes from name conflicts
43
44 // Options used for LexerBaan
45 struct OptionsBaan {
46 bool fold;
47 bool foldComment;
48 bool foldPreprocessor;
49 bool foldCompact;
50 bool baanFoldSyntaxBased;
51 bool baanFoldKeywordsBased;
52 bool baanFoldSections;
53 bool baanFoldInnerLevel;
54 bool baanStylingWithinPreprocessor;
OptionsBaan__anon0a5c74cb0111::OptionsBaan55 OptionsBaan() {
56 fold = false;
57 foldComment = false;
58 foldPreprocessor = false;
59 foldCompact = false;
60 baanFoldSyntaxBased = false;
61 baanFoldKeywordsBased = false;
62 baanFoldSections = false;
63 baanFoldInnerLevel = false;
64 baanStylingWithinPreprocessor = false;
65 }
66 };
67
68 const char *const baanWordLists[] = {
69 "Baan & BaanSQL Reserved Keywords ",
70 "Baan Standard functions",
71 "Baan Functions Abridged",
72 "Baan Main Sections ",
73 "Baan Sub Sections",
74 "PreDefined Variables",
75 "PreDefined Attributes",
76 "Enumerates",
77 0,
78 };
79
80 struct OptionSetBaan : public OptionSet<OptionsBaan> {
OptionSetBaan__anon0a5c74cb0111::OptionSetBaan81 OptionSetBaan() {
82 DefineProperty("fold", &OptionsBaan::fold);
83
84 DefineProperty("fold.comment", &OptionsBaan::foldComment);
85
86 DefineProperty("fold.preprocessor", &OptionsBaan::foldPreprocessor);
87
88 DefineProperty("fold.compact", &OptionsBaan::foldCompact);
89
90 DefineProperty("fold.baan.syntax.based", &OptionsBaan::baanFoldSyntaxBased,
91 "Set this property to 0 to disable syntax based folding, which is folding based on '{' & '('.");
92
93 DefineProperty("fold.baan.keywords.based", &OptionsBaan::baanFoldKeywordsBased,
94 "Set this property to 0 to disable keywords based folding, which is folding based on "
95 " for, if, on (case), repeat, select, while and fold ends based on endfor, endif, endcase, until, endselect, endwhile respectively."
96 "Also folds declarations which are grouped together.");
97
98 DefineProperty("fold.baan.sections", &OptionsBaan::baanFoldSections,
99 "Set this property to 0 to disable folding of Main Sections as well as Sub Sections.");
100
101 DefineProperty("fold.baan.inner.level", &OptionsBaan::baanFoldInnerLevel,
102 "Set this property to 1 to enable folding of inner levels of select statements."
103 "Disabled by default. case and if statements are also eligible" );
104
105 DefineProperty("lexer.baan.styling.within.preprocessor", &OptionsBaan::baanStylingWithinPreprocessor,
106 "For Baan code, determines whether all preprocessor code is styled in the "
107 "preprocessor style (0, the default) or only from the initial # to the end "
108 "of the command word(1).");
109
110 DefineWordListSets(baanWordLists);
111 }
112 };
113
IsAWordChar(const int ch)114 static inline bool IsAWordChar(const int ch) {
115 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$');
116 }
117
IsAnOperator(int ch)118 static inline bool IsAnOperator(int ch) {
119 if (IsAlphaNumeric(ch))
120 return false;
121 if (ch == '#' || ch == '^' || ch == '&' || ch == '*' ||
122 ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
123 ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
124 ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
125 ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
126 ch == '?' || ch == '!' || ch == '"' || ch == '~' ||
127 ch == '\\')
128 return true;
129 return false;
130 }
131
IsAnyOtherIdentifier(char * s,Sci_Position sLength)132 static inline int IsAnyOtherIdentifier(char *s, Sci_Position sLength) {
133
134 /* IsAnyOtherIdentifier uses standard templates used in baan.
135 The matching template is shown as comments just above the return condition.
136 ^ - refers to any character [a-z].
137 # - refers to any number [0-9].
138 Other characters shown are compared as is.
139 Tried implementing with Regex... it was too complicated for me.
140 Any other implementation suggestion welcome.
141 */
142 switch (sLength) {
143 case 8:
144 if (isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
145 //^^^^^###
146 return(SCE_BAAN_TABLEDEF);
147 }
148 break;
149 case 9:
150 if (s[0] == 't' && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && isalpha(s[5]) && IsADigit(s[6]) && IsADigit(s[7]) && IsADigit(s[8])) {
151 //t^^^^^###
152 return(SCE_BAAN_TABLEDEF);
153 }
154 else if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
155 //^^^^^###.
156 return(SCE_BAAN_TABLESQL);
157 }
158 break;
159 case 13:
160 if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
161 //^^^^^###.****
162 return(SCE_BAAN_TABLESQL);
163 }
164 else if (s[0] == 'r' && s[1] == 'c' && s[2] == 'd' && s[3] == '.' && s[4] == 't' && isalpha(s[5]) && isalpha(s[6]) && isalpha(s[7]) && isalpha(s[8]) && isalpha(s[9]) && IsADigit(s[10]) && IsADigit(s[11]) && IsADigit(s[12])) {
165 //rcd.t^^^^^###
166 return(SCE_BAAN_TABLEDEF);
167 }
168 break;
169 case 14:
170 case 15:
171 if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
172 if (s[13] != ':') {
173 //^^^^^###.******
174 return(SCE_BAAN_TABLESQL);
175 }
176 }
177 break;
178 case 16:
179 case 17:
180 if (s[8] == '.' && s[9] == '_' && s[10] == 'i' && s[11] == 'n' && s[12] == 'd' && s[13] == 'e' && s[14] == 'x' && IsADigit(s[15]) && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
181 //^^^^^###._index##
182 return(SCE_BAAN_TABLEDEF);
183 }
184 else if (s[8] == '.' && s[9] == '_' && s[10] == 'c' && s[11] == 'o' && s[12] == 'm' && s[13] == 'p' && s[14] == 'n' && s[15] == 'r' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
185 //^^^^^###._compnr
186 return(SCE_BAAN_TABLEDEF);
187 }
188 break;
189 default:
190 break;
191 }
192 if (sLength > 14 && s[5] == '.' && s[6] == 'd' && s[7] == 'l' && s[8] == 'l' && s[13] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[9]) && IsADigit(s[10]) && IsADigit(s[11]) && IsADigit(s[12])) {
193 //^^^^^.dll####.
194 return(SCE_BAAN_FUNCTION);
195 }
196 else if (sLength > 15 && s[2] == 'i' && s[3] == 'n' && s[4] == 't' && s[5] == '.' && s[6] == 'd' && s[7] == 'l' && s[8] == 'l' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[9]) && isalpha(s[10]) && isalpha(s[11]) && isalpha(s[12]) && isalpha(s[13])) {
197 //^^int.dll^^^^^.
198 return(SCE_BAAN_FUNCTION);
199 }
200 else if (sLength > 11 && s[0] == 'i' && s[10] == '.' && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && isalpha(s[5]) && IsADigit(s[6]) && IsADigit(s[7]) && IsADigit(s[8]) && IsADigit(s[9])) {
201 //i^^^^^####.
202 return(SCE_BAAN_FUNCTION);
203 }
204
205 return(SCE_BAAN_DEFAULT);
206 }
207
IsCommentLine(Sci_Position line,LexAccessor & styler)208 static bool IsCommentLine(Sci_Position line, LexAccessor &styler) {
209 Sci_Position pos = styler.LineStart(line);
210 Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
211 for (Sci_Position i = pos; i < eol_pos; i++) {
212 char ch = styler[i];
213 int style = styler.StyleAt(i);
214 if (ch == '|' && style == SCE_BAAN_COMMENT)
215 return true;
216 else if (!IsASpaceOrTab(ch))
217 return false;
218 }
219 return false;
220 }
221
IsPreProcLine(Sci_Position line,LexAccessor & styler)222 static bool IsPreProcLine(Sci_Position line, LexAccessor &styler) {
223 Sci_Position pos = styler.LineStart(line);
224 Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
225 for (Sci_Position i = pos; i < eol_pos; i++) {
226 char ch = styler[i];
227 int style = styler.StyleAt(i);
228 if (ch == '#' && style == SCE_BAAN_PREPROCESSOR) {
229 if (styler.Match(i, "#elif") || styler.Match(i, "#else") || styler.Match(i, "#endif")
230 || styler.Match(i, "#if") || styler.Match(i, "#ifdef") || styler.Match(i, "#ifndef"))
231 // Above PreProcessors has a seperate fold mechanism.
232 return false;
233 else
234 return true;
235 }
236 else if (ch == '^')
237 return true;
238 else if (!IsASpaceOrTab(ch))
239 return false;
240 }
241 return false;
242 }
243
mainOrSubSectionLine(Sci_Position line,LexAccessor & styler)244 static int mainOrSubSectionLine(Sci_Position line, LexAccessor &styler) {
245 Sci_Position pos = styler.LineStart(line);
246 Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
247 for (Sci_Position i = pos; i < eol_pos; i++) {
248 char ch = styler[i];
249 int style = styler.StyleAt(i);
250 if (style == SCE_BAAN_WORD5 || style == SCE_BAAN_WORD4)
251 return style;
252 else if (IsASpaceOrTab(ch))
253 continue;
254 else
255 break;
256 }
257 return 0;
258 }
259
priorSectionIsSubSection(Sci_Position line,LexAccessor & styler)260 static bool priorSectionIsSubSection(Sci_Position line, LexAccessor &styler){
261 while (line > 0) {
262 Sci_Position pos = styler.LineStart(line);
263 Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
264 for (Sci_Position i = pos; i < eol_pos; i++) {
265 char ch = styler[i];
266 int style = styler.StyleAt(i);
267 if (style == SCE_BAAN_WORD4)
268 return true;
269 else if (style == SCE_BAAN_WORD5)
270 return false;
271 else if (IsASpaceOrTab(ch))
272 continue;
273 else
274 break;
275 }
276 line--;
277 }
278 return false;
279 }
280
nextSectionIsSubSection(Sci_Position line,LexAccessor & styler)281 static bool nextSectionIsSubSection(Sci_Position line, LexAccessor &styler) {
282 while (line > 0) {
283 Sci_Position pos = styler.LineStart(line);
284 Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
285 for (Sci_Position i = pos; i < eol_pos; i++) {
286 char ch = styler[i];
287 int style = styler.StyleAt(i);
288 if (style == SCE_BAAN_WORD4)
289 return true;
290 else if (style == SCE_BAAN_WORD5)
291 return false;
292 else if (IsASpaceOrTab(ch))
293 continue;
294 else
295 break;
296 }
297 line++;
298 }
299 return false;
300 }
301
IsDeclarationLine(Sci_Position line,LexAccessor & styler)302 static bool IsDeclarationLine(Sci_Position line, LexAccessor &styler) {
303 Sci_Position pos = styler.LineStart(line);
304 Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
305 for (Sci_Position i = pos; i < eol_pos; i++) {
306 char ch = styler[i];
307 int style = styler.StyleAt(i);
308 if (style == SCE_BAAN_WORD) {
309 if (styler.Match(i, "table") || styler.Match(i, "extern") || styler.Match(i, "long")
310 || styler.Match(i, "double") || styler.Match(i, "boolean") || styler.Match(i, "string")
311 || styler.Match(i, "domain")) {
312 for (Sci_Position j = eol_pos; j > pos; j--) {
313 int styleFromEnd = styler.StyleAt(j);
314 if (styleFromEnd == SCE_BAAN_COMMENT)
315 continue;
316 else if (IsASpace(styler[j]))
317 continue;
318 else if (styler[j] != ',')
319 //Above conditions ensures, Declaration is not part of any function parameters.
320 return true;
321 else
322 return false;
323 }
324 }
325 else
326 return false;
327 }
328 else if (!IsASpaceOrTab(ch))
329 return false;
330 }
331 return false;
332 }
333
IsInnerLevelFold(Sci_Position line,LexAccessor & styler)334 static bool IsInnerLevelFold(Sci_Position line, LexAccessor &styler) {
335 Sci_Position pos = styler.LineStart(line);
336 Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
337 for (Sci_Position i = pos; i < eol_pos; i++) {
338 char ch = styler[i];
339 int style = styler.StyleAt(i);
340 if (style == SCE_BAAN_WORD && (styler.Match(i, "else" ) || styler.Match(i, "case")
341 || styler.Match(i, "default") || styler.Match(i, "selectdo") || styler.Match(i, "selecteos")
342 || styler.Match(i, "selectempty") || styler.Match(i, "selecterror")))
343 return true;
344 else if (IsASpaceOrTab(ch))
345 continue;
346 else
347 return false;
348 }
349 return false;
350 }
351
wordInArray(const std::string & value,std::string * array,int length)352 static inline bool wordInArray(const std::string& value, std::string *array, int length)
353 {
354 for (int i = 0; i < length; i++)
355 {
356 if (value == array[i])
357 {
358 return true;
359 }
360 }
361
362 return false;
363 }
364
365 class WordListAbridged : public WordList {
366 public:
WordListAbridged()367 WordListAbridged() {
368 kwAbridged = false;
369 kwHasSection = false;
370 };
~WordListAbridged()371 ~WordListAbridged() {
372 Clear();
373 };
374 bool kwAbridged;
375 bool kwHasSection;
Contains(const char * s)376 bool Contains(const char *s) {
377 return kwAbridged ? InListAbridged(s, '~') : InList(s);
378 };
379 };
380
381 }
382
383 class LexerBaan : public DefaultLexer {
384 WordListAbridged keywords;
385 WordListAbridged keywords2;
386 WordListAbridged keywords3;
387 WordListAbridged keywords4;
388 WordListAbridged keywords5;
389 WordListAbridged keywords6;
390 WordListAbridged keywords7;
391 WordListAbridged keywords8;
392 WordListAbridged keywords9;
393 OptionsBaan options;
394 OptionSetBaan osBaan;
395 public:
LexerBaan()396 LexerBaan() {
397 }
398
~LexerBaan()399 virtual ~LexerBaan() {
400 }
401
Version() const402 int SCI_METHOD Version() const override {
403 return lvOriginal;
404 }
405
Release()406 void SCI_METHOD Release() override {
407 delete this;
408 }
409
PropertyNames()410 const char * SCI_METHOD PropertyNames() override {
411 return osBaan.PropertyNames();
412 }
413
PropertyType(const char * name)414 int SCI_METHOD PropertyType(const char * name) override {
415 return osBaan.PropertyType(name);
416 }
417
DescribeProperty(const char * name)418 const char * SCI_METHOD DescribeProperty(const char * name) override {
419 return osBaan.DescribeProperty(name);
420 }
421
422 Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
423
DescribeWordListSets()424 const char * SCI_METHOD DescribeWordListSets() override {
425 return osBaan.DescribeWordListSets();
426 }
427
428 Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
429
430 void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
431
432 void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
433
PrivateCall(int,void *)434 void * SCI_METHOD PrivateCall(int, void *) override {
435 return NULL;
436 }
437
LexerFactoryBaan()438 static ILexer * LexerFactoryBaan() {
439 return new LexerBaan();
440 }
441 };
442
PropertySet(const char * key,const char * val)443 Sci_Position SCI_METHOD LexerBaan::PropertySet(const char *key, const char *val) {
444 if (osBaan.PropertySet(&options, key, val)) {
445 return 0;
446 }
447 return -1;
448 }
449
WordListSet(int n,const char * wl)450 Sci_Position SCI_METHOD LexerBaan::WordListSet(int n, const char *wl) {
451 WordListAbridged *WordListAbridgedN = 0;
452 switch (n) {
453 case 0:
454 WordListAbridgedN = &keywords;
455 break;
456 case 1:
457 WordListAbridgedN = &keywords2;
458 break;
459 case 2:
460 WordListAbridgedN = &keywords3;
461 break;
462 case 3:
463 WordListAbridgedN = &keywords4;
464 break;
465 case 4:
466 WordListAbridgedN = &keywords5;
467 break;
468 case 5:
469 WordListAbridgedN = &keywords6;
470 break;
471 case 6:
472 WordListAbridgedN = &keywords7;
473 break;
474 case 7:
475 WordListAbridgedN = &keywords8;
476 break;
477 case 8:
478 WordListAbridgedN = &keywords9;
479 break;
480 }
481 Sci_Position firstModification = -1;
482 if (WordListAbridgedN) {
483 WordListAbridged wlNew;
484 wlNew.Set(wl);
485 if (*WordListAbridgedN != wlNew) {
486 WordListAbridgedN->Set(wl);
487 WordListAbridgedN->kwAbridged = strchr(wl, '~') != NULL;
488 WordListAbridgedN->kwHasSection = strchr(wl, ':') != NULL;
489
490 firstModification = 0;
491 }
492 }
493 return firstModification;
494 }
495
Lex(Sci_PositionU startPos,Sci_Position length,int initStyle,IDocument * pAccess)496 void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
497
498 if (initStyle == SCE_BAAN_STRINGEOL) // Does not leak onto next line
499 initStyle = SCE_BAAN_DEFAULT;
500
501 int visibleChars = 0;
502 bool lineHasDomain = false;
503 bool lineHasFunction = false;
504 bool lineHasPreProc = false;
505 bool lineIgnoreString = false;
506 bool lineHasDefines = false;
507 bool numberIsHex = false;
508 char word[1000];
509 int wordlen = 0;
510
511 std::string preProcessorTags[13] = { "#context_off", "#context_on",
512 "#define", "#elif", "#else", "#endif",
513 "#ident", "#if", "#ifdef", "#ifndef",
514 "#include", "#pragma", "#undef" };
515 LexAccessor styler(pAccess);
516 StyleContext sc(startPos, length, initStyle, styler);
517
518 for (; sc.More(); sc.Forward()) {
519
520 // Determine if the current state should terminate.
521 switch (sc.state) {
522 case SCE_BAAN_OPERATOR:
523 sc.SetState(SCE_BAAN_DEFAULT);
524 break;
525 case SCE_BAAN_NUMBER:
526 if (IsASpaceOrTab(sc.ch) || sc.ch == '\r' || sc.ch == '\n' || IsAnOperator(sc.ch)) {
527 sc.SetState(SCE_BAAN_DEFAULT);
528 }
529 else if ((numberIsHex && !(MakeLowerCase(sc.ch) == 'x' || MakeLowerCase(sc.ch) == 'e' ||
530 IsADigit(sc.ch, 16) || sc.ch == '.' || sc.ch == '-' || sc.ch == '+')) ||
531 (!numberIsHex && !(MakeLowerCase(sc.ch) == 'e' || IsADigit(sc.ch)
532 || sc.ch == '.' || sc.ch == '-' || sc.ch == '+'))) {
533 // check '-' for possible -10e-5. Add '+' as well.
534 numberIsHex = false;
535 sc.ChangeState(SCE_BAAN_IDENTIFIER);
536 sc.SetState(SCE_BAAN_DEFAULT);
537 }
538 break;
539 case SCE_BAAN_IDENTIFIER:
540 if (!IsAWordChar(sc.ch)) {
541 char s[1000];
542 char s1[1000];
543 sc.GetCurrentLowered(s, sizeof(s));
544 if (sc.ch == ':') {
545 memcpy(s1, s, sizeof(s));
546 s1[sc.LengthCurrent()] = sc.ch;
547 s1[sc.LengthCurrent() + 1] = '\0';
548 }
549 if ((keywords.kwHasSection && (sc.ch == ':')) ? keywords.Contains(s1) : keywords.Contains(s)) {
550 sc.ChangeState(SCE_BAAN_WORD);
551 if (0 == strcmp(s, "domain")) {
552 lineHasDomain = true;
553 }
554 else if (0 == strcmp(s, "function")) {
555 lineHasFunction = true;
556 }
557 }
558 else if (lineHasDomain) {
559 sc.ChangeState(SCE_BAAN_DOMDEF);
560 lineHasDomain = false;
561 }
562 else if (lineHasFunction) {
563 sc.ChangeState(SCE_BAAN_FUNCDEF);
564 lineHasFunction = false;
565 }
566 else if ((keywords2.kwHasSection && (sc.ch == ':')) ? keywords2.Contains(s1) : keywords2.Contains(s)) {
567 sc.ChangeState(SCE_BAAN_WORD2);
568 }
569 else if ((keywords3.kwHasSection && (sc.ch == ':')) ? keywords3.Contains(s1) : keywords3.Contains(s)) {
570 if (sc.ch == '(')
571 sc.ChangeState(SCE_BAAN_WORD3);
572 else
573 sc.ChangeState(SCE_BAAN_IDENTIFIER);
574 }
575 else if ((keywords4.kwHasSection && (sc.ch == ':')) ? keywords4.Contains(s1) : keywords4.Contains(s)) {
576 sc.ChangeState(SCE_BAAN_WORD4);
577 }
578 else if ((keywords5.kwHasSection && (sc.ch == ':')) ? keywords5.Contains(s1) : keywords5.Contains(s)) {
579 sc.ChangeState(SCE_BAAN_WORD5);
580 }
581 else if ((keywords6.kwHasSection && (sc.ch == ':')) ? keywords6.Contains(s1) : keywords6.Contains(s)) {
582 sc.ChangeState(SCE_BAAN_WORD6);
583 }
584 else if ((keywords7.kwHasSection && (sc.ch == ':')) ? keywords7.Contains(s1) : keywords7.Contains(s)) {
585 sc.ChangeState(SCE_BAAN_WORD7);
586 }
587 else if ((keywords8.kwHasSection && (sc.ch == ':')) ? keywords8.Contains(s1) : keywords8.Contains(s)) {
588 sc.ChangeState(SCE_BAAN_WORD8);
589 }
590 else if ((keywords9.kwHasSection && (sc.ch == ':')) ? keywords9.Contains(s1) : keywords9.Contains(s)) {
591 sc.ChangeState(SCE_BAAN_WORD9);
592 }
593 else if (lineHasPreProc) {
594 sc.ChangeState(SCE_BAAN_OBJECTDEF);
595 lineHasPreProc = false;
596 }
597 else if (lineHasDefines) {
598 sc.ChangeState(SCE_BAAN_DEFINEDEF);
599 lineHasDefines = false;
600 }
601 else {
602 int state = IsAnyOtherIdentifier(s, sc.LengthCurrent());
603 if (state > 0) {
604 sc.ChangeState(state);
605 }
606 }
607 sc.SetState(SCE_BAAN_DEFAULT);
608 }
609 break;
610 case SCE_BAAN_PREPROCESSOR:
611 if (options.baanStylingWithinPreprocessor) {
612 if (IsASpace(sc.ch) || IsAnOperator(sc.ch)) {
613 sc.SetState(SCE_BAAN_DEFAULT);
614 }
615 }
616 else {
617 if (sc.atLineEnd && (sc.chNext != '^')) {
618 sc.SetState(SCE_BAAN_DEFAULT);
619 }
620 }
621 break;
622 case SCE_BAAN_COMMENT:
623 if (sc.ch == '\r' || sc.ch == '\n') {
624 sc.SetState(SCE_BAAN_DEFAULT);
625 }
626 break;
627 case SCE_BAAN_COMMENTDOC:
628 if (sc.MatchIgnoreCase("enddllusage")) {
629 for (unsigned int i = 0; i < 10; i++) {
630 sc.Forward();
631 }
632 sc.ForwardSetState(SCE_BAAN_DEFAULT);
633 }
634 else if (sc.MatchIgnoreCase("endfunctionusage")) {
635 for (unsigned int i = 0; i < 15; i++) {
636 sc.Forward();
637 }
638 sc.ForwardSetState(SCE_BAAN_DEFAULT);
639 }
640 break;
641 case SCE_BAAN_STRING:
642 if (sc.ch == '\"') {
643 sc.ForwardSetState(SCE_BAAN_DEFAULT);
644 }
645 else if ((sc.atLineEnd) && (sc.chNext != '^')) {
646 sc.ChangeState(SCE_BAAN_STRINGEOL);
647 sc.ForwardSetState(SCE_BAAN_DEFAULT);
648 visibleChars = 0;
649 }
650 break;
651 }
652
653 // Determine if a new state should be entered.
654 if (sc.state == SCE_BAAN_DEFAULT) {
655 if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))
656 || ((sc.ch == '-' || sc.ch == '+') && (IsADigit(sc.chNext) || sc.chNext == '.'))
657 || (MakeLowerCase(sc.ch) == 'e' && (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-'))) {
658 if ((sc.ch == '0' && MakeLowerCase(sc.chNext) == 'x') ||
659 ((sc.ch == '-' || sc.ch == '+') && sc.chNext == '0' && MakeLowerCase(sc.GetRelativeCharacter(2)) == 'x')){
660 numberIsHex = true;
661 }
662 sc.SetState(SCE_BAAN_NUMBER);
663 }
664 else if (sc.MatchIgnoreCase("dllusage") || sc.MatchIgnoreCase("functionusage")) {
665 sc.SetState(SCE_BAAN_COMMENTDOC);
666 do {
667 sc.Forward();
668 } while ((!sc.atLineEnd) && sc.More());
669 }
670 else if (iswordstart(sc.ch)) {
671 sc.SetState(SCE_BAAN_IDENTIFIER);
672 }
673 else if (sc.Match('|')) {
674 sc.SetState(SCE_BAAN_COMMENT);
675 }
676 else if (sc.ch == '\"' && !(lineIgnoreString)) {
677 sc.SetState(SCE_BAAN_STRING);
678 }
679 else if (sc.ch == '#' && visibleChars == 0) {
680 // Preprocessor commands are alone on their line
681 sc.SetState(SCE_BAAN_PREPROCESSOR);
682 word[0] = '\0';
683 wordlen = 0;
684 while (sc.More() && !(IsASpace(sc.chNext) || IsAnOperator(sc.chNext))) {
685 sc.Forward();
686 wordlen++;
687 }
688 sc.GetCurrentLowered(word, sizeof(word));
689 if (!sc.atLineEnd) {
690 word[wordlen++] = sc.ch;
691 word[wordlen++] = '\0';
692 }
693 if (!wordInArray(word, preProcessorTags, 13))
694 // Colorise only preprocessor built in Baan.
695 sc.ChangeState(SCE_BAAN_IDENTIFIER);
696 if (strcmp(word, "#pragma") == 0 || strcmp(word, "#include") == 0) {
697 lineHasPreProc = true;
698 lineIgnoreString = true;
699 }
700 else if (strcmp(word, "#define") == 0 || strcmp(word, "#undef") == 0 ||
701 strcmp(word, "#ifdef") == 0 || strcmp(word, "#if") == 0 || strcmp(word, "#ifndef") == 0) {
702 lineHasDefines = true;
703 lineIgnoreString = false;
704 }
705 }
706 else if (IsAnOperator(static_cast<char>(sc.ch))) {
707 sc.SetState(SCE_BAAN_OPERATOR);
708 }
709 }
710
711 if (sc.atLineEnd) {
712 // Reset states to begining of colourise so no surprises
713 // if different sets of lines lexed.
714 visibleChars = 0;
715 lineHasDomain = false;
716 lineHasFunction = false;
717 lineHasPreProc = false;
718 lineIgnoreString = false;
719 lineHasDefines = false;
720 numberIsHex = false;
721 }
722 if (!IsASpace(sc.ch)) {
723 visibleChars++;
724 }
725 }
726 sc.Complete();
727 }
728
Fold(Sci_PositionU startPos,Sci_Position length,int initStyle,IDocument * pAccess)729 void SCI_METHOD LexerBaan::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
730 if (!options.fold)
731 return;
732
733 char word[100];
734 int wordlen = 0;
735 bool foldStart = true;
736 bool foldNextSelect = true;
737 bool afterFunctionSection = false;
738 bool beforeDeclarationSection = false;
739 int currLineStyle = 0;
740 int nextLineStyle = 0;
741
742 std::string startTags[6] = { "for", "if", "on", "repeat", "select", "while" };
743 std::string endTags[6] = { "endcase", "endfor", "endif", "endselect", "endwhile", "until" };
744 std::string selectCloseTags[5] = { "selectdo", "selecteos", "selectempty", "selecterror", "endselect" };
745
746 LexAccessor styler(pAccess);
747 Sci_PositionU endPos = startPos + length;
748 int visibleChars = 0;
749 Sci_Position lineCurrent = styler.GetLine(startPos);
750
751 // Backtrack to previous line in case need to fix its fold status
752 if (startPos > 0) {
753 if (lineCurrent > 0) {
754 lineCurrent--;
755 startPos = styler.LineStart(lineCurrent);
756 }
757 }
758
759 int levelPrev = SC_FOLDLEVELBASE;
760 if (lineCurrent > 0)
761 levelPrev = styler.LevelAt(lineCurrent - 1) >> 16;
762 int levelCurrent = levelPrev;
763 char chNext = styler[startPos];
764 int style = initStyle;
765 int styleNext = styler.StyleAt(startPos);
766
767 for (Sci_PositionU i = startPos; i < endPos; i++) {
768 char ch = chNext;
769 chNext = styler.SafeGetCharAt(i + 1);
770 style = styleNext;
771 styleNext = styler.StyleAt(i + 1);
772 int stylePrev = (i) ? styler.StyleAt(i - 1) : SCE_BAAN_DEFAULT;
773 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
774
775 // Comment folding
776 if (options.foldComment && style == SCE_BAAN_COMMENTDOC) {
777 if (style != stylePrev) {
778 levelCurrent++;
779 }
780 else if (style != styleNext) {
781 levelCurrent--;
782 }
783 }
784 if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) {
785 if (!IsCommentLine(lineCurrent - 1, styler)
786 && IsCommentLine(lineCurrent + 1, styler))
787 levelCurrent++;
788 else if (IsCommentLine(lineCurrent - 1, styler)
789 && !IsCommentLine(lineCurrent + 1, styler))
790 levelCurrent--;
791 }
792 // PreProcessor Folding
793 if (options.foldPreprocessor) {
794 if (atEOL && IsPreProcLine(lineCurrent, styler)) {
795 if (!IsPreProcLine(lineCurrent - 1, styler)
796 && IsPreProcLine(lineCurrent + 1, styler))
797 levelCurrent++;
798 else if (IsPreProcLine(lineCurrent - 1, styler)
799 && !IsPreProcLine(lineCurrent + 1, styler))
800 levelCurrent--;
801 }
802 else if (style == SCE_BAAN_PREPROCESSOR) {
803 // folds #ifdef/#if/#ifndef - they are not part of the IsPreProcLine folding.
804 if (ch == '#') {
805 if (styler.Match(i, "#ifdef") || styler.Match(i, "#if") || styler.Match(i, "#ifndef")
806 || styler.Match(i, "#context_on"))
807 levelCurrent++;
808 else if (styler.Match(i, "#endif") || styler.Match(i, "#context_off"))
809 levelCurrent--;
810 }
811 }
812 }
813 //Syntax Folding
814 if (options.baanFoldSyntaxBased && (style == SCE_BAAN_OPERATOR)) {
815 if (ch == '{' || ch == '(') {
816 levelCurrent++;
817 }
818 else if (ch == '}' || ch == ')') {
819 levelCurrent--;
820 }
821 }
822 //Keywords Folding
823 if (options.baanFoldKeywordsBased) {
824 if (atEOL && IsDeclarationLine(lineCurrent, styler)) {
825 if (!IsDeclarationLine(lineCurrent - 1, styler)
826 && IsDeclarationLine(lineCurrent + 1, styler))
827 levelCurrent++;
828 else if (IsDeclarationLine(lineCurrent - 1, styler)
829 && !IsDeclarationLine(lineCurrent + 1, styler))
830 levelCurrent--;
831 }
832 else if (style == SCE_BAAN_WORD) {
833 word[wordlen++] = static_cast<char>(MakeLowerCase(ch));
834 if (wordlen == 100) { // prevent overflow
835 word[0] = '\0';
836 wordlen = 1;
837 }
838 if (styleNext != SCE_BAAN_WORD) {
839 word[wordlen] = '\0';
840 wordlen = 0;
841 if (strcmp(word, "for") == 0) {
842 Sci_PositionU j = i + 1;
843 while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
844 j++;
845 }
846 if (styler.Match(j, "update")) {
847 // Means this is a "for update" used by Select which is already folded.
848 foldStart = false;
849 }
850 }
851 else if (strcmp(word, "on") == 0) {
852 Sci_PositionU j = i + 1;
853 while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
854 j++;
855 }
856 if (!styler.Match(j, "case")) {
857 // Means this is not a "on Case" statement... could be "on" used by index.
858 foldStart = false;
859 }
860 }
861 else if (strcmp(word, "select") == 0) {
862 if (foldNextSelect) {
863 // Next Selects are sub-clause till reach of selectCloseTags[] array.
864 foldNextSelect = false;
865 foldStart = true;
866 }
867 else {
868 foldNextSelect = false;
869 foldStart = false;
870 }
871 }
872 else if (wordInArray(word, selectCloseTags, 5)) {
873 // select clause ends, next select clause can be folded.
874 foldNextSelect = true;
875 foldStart = true;
876 }
877 else {
878 foldStart = true;
879 }
880 if (foldStart) {
881 if (wordInArray(word, startTags, 6)) {
882 levelCurrent++;
883 }
884 else if (wordInArray(word, endTags, 6)) {
885 levelCurrent--;
886 }
887 }
888 }
889 }
890 }
891 // Fold inner level of if/select/case statements
892 if (options.baanFoldInnerLevel && atEOL) {
893 bool currLineInnerLevel = IsInnerLevelFold(lineCurrent, styler);
894 bool nextLineInnerLevel = IsInnerLevelFold(lineCurrent + 1, styler);
895 if (currLineInnerLevel && currLineInnerLevel != nextLineInnerLevel) {
896 levelCurrent++;
897 }
898 else if (nextLineInnerLevel && nextLineInnerLevel != currLineInnerLevel) {
899 levelCurrent--;
900 }
901 }
902 // Section Foldings.
903 // One way of implementing Section Foldings, as there is no END markings of sections.
904 // first section ends on the previous line of next section.
905 // Re-written whole folding to accomodate this.
906 if (options.baanFoldSections && atEOL) {
907 currLineStyle = mainOrSubSectionLine(lineCurrent, styler);
908 nextLineStyle = mainOrSubSectionLine(lineCurrent + 1, styler);
909 if (currLineStyle != 0 && currLineStyle != nextLineStyle) {
910 if (levelCurrent < levelPrev)
911 --levelPrev;
912 for (Sci_Position j = styler.LineStart(lineCurrent); j < styler.LineStart(lineCurrent + 1) - 1; j++) {
913 if (IsASpaceOrTab(styler[j]))
914 continue;
915 else if (styler.StyleAt(j) == SCE_BAAN_WORD5) {
916 if (styler.Match(j, "functions:")) {
917 // Means functions: is the end of MainSections.
918 // Nothing to fold after this.
919 afterFunctionSection = true;
920 break;
921 }
922 else {
923 afterFunctionSection = false;
924 break;
925 }
926 }
927 else {
928 afterFunctionSection = false;
929 break;
930 }
931 }
932 if (!afterFunctionSection)
933 levelCurrent++;
934 }
935 else if (nextLineStyle != 0 && currLineStyle != nextLineStyle
936 && (priorSectionIsSubSection(lineCurrent -1 ,styler)
937 || !nextSectionIsSubSection(lineCurrent + 1, styler))) {
938 for (Sci_Position j = styler.LineStart(lineCurrent + 1); j < styler.LineStart(lineCurrent + 1 + 1) - 1; j++) {
939 if (IsASpaceOrTab(styler[j]))
940 continue;
941 else if (styler.StyleAt(j) == SCE_BAAN_WORD5) {
942 if (styler.Match(j, "declaration:")) {
943 // Means declaration: is the start of MainSections.
944 // Nothing to fold before this.
945 beforeDeclarationSection = true;
946 break;
947 }
948 else {
949 beforeDeclarationSection = false;
950 break;
951 }
952 }
953 else {
954 beforeDeclarationSection = false;
955 break;
956 }
957 }
958 if (!beforeDeclarationSection) {
959 levelCurrent--;
960 if (nextLineStyle == SCE_BAAN_WORD5 && priorSectionIsSubSection(lineCurrent-1, styler))
961 // next levelCurrent--; is to unfold previous subsection fold.
962 // On reaching the next main section, the previous main as well sub section ends.
963 levelCurrent--;
964 }
965 }
966 }
967 if (atEOL) {
968 int lev = levelPrev;
969 lev |= levelCurrent << 16;
970 if (visibleChars == 0 && options.foldCompact)
971 lev |= SC_FOLDLEVELWHITEFLAG;
972 if ((levelCurrent > levelPrev) && (visibleChars > 0))
973 lev |= SC_FOLDLEVELHEADERFLAG;
974 if (lev != styler.LevelAt(lineCurrent)) {
975 styler.SetLevel(lineCurrent, lev);
976 }
977 lineCurrent++;
978 levelPrev = levelCurrent;
979 visibleChars = 0;
980 }
981 if (!isspacechar(ch))
982 visibleChars++;
983 }
984 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
985 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
986 }
987
988 LexerModule lmBaan(SCLEX_BAAN, LexerBaan::LexerFactoryBaan, "baan", baanWordLists);
989