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