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