1 // SciTE - Scintilla based Text Editor
2 // LexBullant.cxx - lexer for Bullant
3
4 #include <stdlib.h>
5 #include <string.h>
6 #include <stdio.h>
7 #include <stdarg.h>
8 #include <assert.h>
9 #include <ctype.h>
10
11 #include "ILexer.h"
12 #include "Scintilla.h"
13 #include "SciLexer.h"
14
15 #include "WordList.h"
16 #include "LexAccessor.h"
17 #include "Accessor.h"
18 #include "StyleContext.h"
19 #include "CharacterSet.h"
20 #include "LexerModule.h"
21
22 using namespace Scintilla;
23
classifyWordBullant(Sci_PositionU start,Sci_PositionU end,WordList & keywords,Accessor & styler)24 static int classifyWordBullant(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler) {
25 char s[100];
26 s[0] = '\0';
27 for (Sci_PositionU i = 0; i < end - start + 1 && i < 30; i++) {
28 s[i] = static_cast<char>(tolower(styler[start + i]));
29 s[i + 1] = '\0';
30 }
31 int lev= 0;
32 char chAttr = SCE_C_IDENTIFIER;
33 if (isdigit(s[0]) || (s[0] == '.')){
34 chAttr = SCE_C_NUMBER;
35 }
36 else {
37 if (keywords.InList(s)) {
38 chAttr = SCE_C_WORD;
39 if (strcmp(s, "end") == 0)
40 lev = -1;
41 else if (strcmp(s, "method") == 0 ||
42 strcmp(s, "case") == 0 ||
43 strcmp(s, "class") == 0 ||
44 strcmp(s, "debug") == 0 ||
45 strcmp(s, "test") == 0 ||
46 strcmp(s, "if") == 0 ||
47 strcmp(s, "lock") == 0 ||
48 strcmp(s, "transaction") == 0 ||
49 strcmp(s, "trap") == 0 ||
50 strcmp(s, "until") == 0 ||
51 strcmp(s, "while") == 0)
52 lev = 1;
53 }
54 }
55 styler.ColourTo(end, chAttr);
56 return lev;
57 }
58
ColouriseBullantDoc(Sci_PositionU startPos,Sci_Position length,int initStyle,WordList * keywordlists[],Accessor & styler)59 static void ColouriseBullantDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[],
60 Accessor &styler) {
61 WordList &keywords = *keywordlists[0];
62
63 styler.StartAt(startPos);
64
65 bool fold = styler.GetPropertyInt("fold") != 0;
66 Sci_Position lineCurrent = styler.GetLine(startPos);
67 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
68 int levelCurrent = levelPrev;
69
70 int state = initStyle;
71 if (state == SCE_C_STRINGEOL) // Does not leak onto next line
72 state = SCE_C_DEFAULT;
73 char chPrev = ' ';
74 char chNext = styler[startPos];
75 Sci_PositionU lengthDoc = startPos + length;
76 int visibleChars = 0;
77 styler.StartSegment(startPos);
78 int endFoundThisLine = 0;
79 for (Sci_PositionU i = startPos; i < lengthDoc; i++) {
80 char ch = chNext;
81 chNext = styler.SafeGetCharAt(i + 1);
82
83 if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
84 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
85 // Avoid triggering two times on Dos/Win
86 // End of line
87 endFoundThisLine = 0;
88 if (state == SCE_C_STRINGEOL) {
89 styler.ColourTo(i, state);
90 state = SCE_C_DEFAULT;
91 }
92 if (fold) {
93 int lev = levelPrev;
94 if (visibleChars == 0)
95 lev |= SC_FOLDLEVELWHITEFLAG;
96 if ((levelCurrent > levelPrev) && (visibleChars > 0))
97 lev |= SC_FOLDLEVELHEADERFLAG;
98 styler.SetLevel(lineCurrent, lev);
99 lineCurrent++;
100 levelPrev = levelCurrent;
101 }
102 visibleChars = 0;
103
104 /* int indentBlock = GetLineIndentation(lineCurrent);
105 if (blockChange==1){
106 lineCurrent++;
107 int pos=SetLineIndentation(lineCurrent, indentBlock + indentSize);
108 } else if (blockChange==-1) {
109 indentBlock -= indentSize;
110 if (indentBlock < 0)
111 indentBlock = 0;
112 SetLineIndentation(lineCurrent, indentBlock);
113 lineCurrent++;
114 }
115 blockChange=0;
116 */ }
117 if (!(IsASCII(ch) && isspace(ch)))
118 visibleChars++;
119
120 if (styler.IsLeadByte(ch)) {
121 chNext = styler.SafeGetCharAt(i + 2);
122 chPrev = ' ';
123 i += 1;
124 continue;
125 }
126
127 if (state == SCE_C_DEFAULT) {
128 if (iswordstart(ch)) {
129 styler.ColourTo(i-1, state);
130 state = SCE_C_IDENTIFIER;
131 } else if (ch == '@' && chNext == 'o') {
132 if ((styler.SafeGetCharAt(i+2) =='f') && (styler.SafeGetCharAt(i+3) == 'f')) {
133 styler.ColourTo(i-1, state);
134 state = SCE_C_COMMENT;
135 }
136 } else if (ch == '#') {
137 styler.ColourTo(i-1, state);
138 state = SCE_C_COMMENTLINE;
139 } else if (ch == '\"') {
140 styler.ColourTo(i-1, state);
141 state = SCE_C_STRING;
142 } else if (ch == '\'') {
143 styler.ColourTo(i-1, state);
144 state = SCE_C_CHARACTER;
145 } else if (isoperator(ch)) {
146 styler.ColourTo(i-1, state);
147 styler.ColourTo(i, SCE_C_OPERATOR);
148 }
149 } else if (state == SCE_C_IDENTIFIER) {
150 if (!iswordchar(ch)) {
151 int levelChange = classifyWordBullant(styler.GetStartSegment(), i - 1, keywords, styler);
152 state = SCE_C_DEFAULT;
153 chNext = styler.SafeGetCharAt(i + 1);
154 if (ch == '#') {
155 state = SCE_C_COMMENTLINE;
156 } else if (ch == '\"') {
157 state = SCE_C_STRING;
158 } else if (ch == '\'') {
159 state = SCE_C_CHARACTER;
160 } else if (isoperator(ch)) {
161 styler.ColourTo(i, SCE_C_OPERATOR);
162 }
163 if (endFoundThisLine == 0)
164 levelCurrent+=levelChange;
165 if (levelChange == -1)
166 endFoundThisLine=1;
167 }
168 } else if (state == SCE_C_COMMENT) {
169 if (ch == '@' && chNext == 'o') {
170 if (styler.SafeGetCharAt(i+2) == 'n') {
171 styler.ColourTo(i+2, state);
172 state = SCE_C_DEFAULT;
173 i+=2;
174 }
175 }
176 } else if (state == SCE_C_COMMENTLINE) {
177 if (ch == '\r' || ch == '\n') {
178 endFoundThisLine = 0;
179 styler.ColourTo(i-1, state);
180 state = SCE_C_DEFAULT;
181 }
182 } else if (state == SCE_C_STRING) {
183 if (ch == '\\') {
184 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
185 i++;
186 ch = chNext;
187 chNext = styler.SafeGetCharAt(i + 1);
188 }
189 } else if (ch == '\"') {
190 styler.ColourTo(i, state);
191 state = SCE_C_DEFAULT;
192 } else if (chNext == '\r' || chNext == '\n') {
193 endFoundThisLine = 0;
194 styler.ColourTo(i-1, SCE_C_STRINGEOL);
195 state = SCE_C_STRINGEOL;
196 }
197 } else if (state == SCE_C_CHARACTER) {
198 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
199 endFoundThisLine = 0;
200 styler.ColourTo(i-1, SCE_C_STRINGEOL);
201 state = SCE_C_STRINGEOL;
202 } else if (ch == '\\') {
203 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
204 i++;
205 ch = chNext;
206 chNext = styler.SafeGetCharAt(i + 1);
207 }
208 } else if (ch == '\'') {
209 styler.ColourTo(i, state);
210 state = SCE_C_DEFAULT;
211 }
212 }
213 chPrev = ch;
214 }
215 styler.ColourTo(lengthDoc - 1, state);
216
217 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
218 if (fold) {
219 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
220 //styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
221 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
222
223 }
224 }
225
226 static const char * const bullantWordListDesc[] = {
227 "Keywords",
228 0
229 };
230
231 LexerModule lmBullant(SCLEX_BULLANT, ColouriseBullantDoc, "bullant", 0, bullantWordListDesc);
232