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