]>
Commit | Line | Data |
---|---|---|
65ec6247 RD |
1 | // Scintilla source code edit control |
2 | /** @file LexLua.cxx | |
3 | ** Lexer for Lua language. | |
4 | ** | |
5 | ** Written by Paul Winwood. | |
6 | ** Folder by Alexey Yutkin. | |
7 | **/ | |
d134f170 RD |
8 | |
9 | #include <stdlib.h> | |
10 | #include <string.h> | |
11 | #include <ctype.h> | |
12 | #include <stdarg.h> | |
13 | #include <stdio.h> | |
14 | #include <fcntl.h> | |
15 | ||
16 | #include "Platform.h" | |
17 | ||
18 | #include "PropSet.h" | |
19 | #include "Accessor.h" | |
20 | #include "KeyWords.h" | |
21 | #include "Scintilla.h" | |
22 | #include "SciLexer.h" | |
23 | ||
65ec6247 RD |
24 | inline bool isLuaOperator(char ch) { |
25 | if (isalnum(ch)) | |
26 | return false; | |
27 | // '.' left out as it is used to make up numbers | |
28 | if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || | |
29 | ch == '(' || ch == ')' || ch == '=' || | |
30 | ch == '{' || ch == '}' || ch == '~' || | |
31 | ch == '[' || ch == ']' || ch == ';' || | |
32 | ch == '<' || ch == '>' || ch == ',' || | |
33 | ch == '.' || ch == '^' || ch == '%' || ch == ':') | |
34 | return true; | |
35 | return false; | |
36 | } | |
37 | ||
38 | static void classifyWordLua(unsigned int start, | |
39 | unsigned int end, | |
40 | WordList &keywords, | |
41 | Accessor &styler) { | |
42 | char s[100]; | |
43 | bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.'); | |
44 | ||
45 | for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { | |
46 | s[i] = styler[start + i]; | |
47 | s[i + 1] = '\0'; | |
48 | } | |
d134f170 | 49 | |
65ec6247 RD |
50 | char chAttr = SCE_LUA_IDENTIFIER; |
51 | ||
52 | if (wordIsNumber) | |
53 | chAttr = SCE_LUA_NUMBER; | |
54 | else { | |
55 | if (keywords.InList(s)) { | |
56 | chAttr = SCE_LUA_WORD; | |
57 | } | |
58 | } | |
59 | styler.ColourTo(end, chAttr); | |
d134f170 RD |
60 | } |
61 | ||
65ec6247 RD |
62 | static void ColouriseLuaDoc(unsigned int startPos, |
63 | int length, | |
64 | int initStyle, | |
65 | WordList *keywordlists[], | |
66 | Accessor &styler) { | |
67 | ||
68 | WordList &keywords = *keywordlists[0]; | |
d134f170 | 69 | |
65ec6247 RD |
70 | styler.StartAt(startPos); |
71 | styler.GetLine(startPos); | |
d134f170 | 72 | |
65ec6247 RD |
73 | int state = initStyle; |
74 | char chPrev = ' '; | |
75 | char chNext = styler[startPos]; | |
76 | unsigned int lengthDoc = startPos + length; | |
77 | bool firstChar = true; | |
d134f170 | 78 | |
65ec6247 RD |
79 | /* Must initialize the literalString level, if we are inside such a string. |
80 | * Note: this isn't enough, because literal strings can be nested, | |
81 | * we should go back to see at what level we are... | |
82 | */ | |
83 | int literalString = (initStyle == SCE_LUA_LITERALSTRING) ? 1 : 0; | |
d134f170 | 84 | |
65ec6247 RD |
85 | styler.StartSegment(startPos); |
86 | for (unsigned int i = startPos; i <= lengthDoc; i++) { | |
87 | char ch = chNext; | |
88 | chNext = styler.SafeGetCharAt(i + 1); | |
d134f170 | 89 | |
65ec6247 RD |
90 | if (styler.IsLeadByte(ch)) { |
91 | chNext = styler.SafeGetCharAt(i + 2); | |
92 | chPrev = ' '; | |
93 | i += 1; | |
94 | continue; | |
95 | } | |
96 | ||
97 | if (state == SCE_LUA_STRINGEOL) { | |
98 | if (ch != '\r' && ch != '\n') { | |
99 | styler.ColourTo(i - 1, state); | |
100 | state = SCE_LUA_DEFAULT; | |
101 | } | |
102 | } | |
103 | ||
104 | if (state == SCE_LUA_LITERALSTRING && ch == '[' && chNext == '[') { | |
105 | literalString++; | |
106 | } else if (state == SCE_LUA_DEFAULT) { | |
107 | if (ch == '-' && chNext == '-') { | |
108 | styler.ColourTo(i - 1, state); | |
109 | state = SCE_LUA_COMMENTLINE; | |
110 | } else if (ch == '[' && chNext == '[') { | |
111 | state = SCE_LUA_LITERALSTRING; | |
112 | literalString = 1; | |
113 | } else if (ch == '\"') { | |
114 | styler.ColourTo(i - 1, state); | |
115 | state = SCE_LUA_STRING; | |
116 | } else if (ch == '\'') { | |
117 | styler.ColourTo(i - 1, state); | |
118 | state = SCE_LUA_CHARACTER; | |
119 | } else if (ch == '$' && firstChar) { | |
120 | styler.ColourTo(i - 1, state); | |
121 | state = SCE_LUA_PREPROCESSOR; | |
122 | } else if (ch == '#' && firstChar) // Should be only on the first line of the file! Cannot be tested here | |
123 | { | |
124 | styler.ColourTo(i - 1, state); | |
125 | state = SCE_LUA_COMMENTLINE; | |
126 | } else if (isLuaOperator(ch)) { | |
127 | styler.ColourTo(i - 1, state); | |
128 | styler.ColourTo(i, SCE_LUA_OPERATOR); | |
129 | } else if (iswordstart(ch)) { | |
130 | styler.ColourTo(i - 1, state); | |
131 | state = SCE_LUA_WORD; | |
132 | } | |
133 | } else if (state == SCE_LUA_WORD) { | |
134 | if (!iswordchar(ch)) { | |
135 | classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler); | |
136 | state = SCE_LUA_DEFAULT; | |
137 | if (ch == '[' && chNext == '[') { | |
138 | literalString = 1; | |
139 | state = SCE_LUA_LITERALSTRING; | |
140 | } else if (ch == '-' && chNext == '-') { | |
141 | state = SCE_LUA_COMMENTLINE; | |
142 | } else if (ch == '\"') { | |
143 | state = SCE_LUA_STRING; | |
144 | } else if (ch == '\'') { | |
145 | state = SCE_LUA_CHARACTER; | |
146 | } else if (ch == '$' && firstChar) { | |
147 | state = SCE_LUA_PREPROCESSOR; | |
148 | } else if (isLuaOperator(ch)) { | |
149 | styler.ColourTo(i, SCE_LUA_OPERATOR); | |
150 | } | |
151 | } else if (ch == '.' && chNext == '.') { | |
152 | classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler); | |
153 | styler.ColourTo(i, SCE_LUA_OPERATOR); | |
154 | state = SCE_LUA_DEFAULT; | |
155 | } | |
156 | } else { | |
157 | if (state == SCE_LUA_LITERALSTRING) { | |
158 | if (ch == ']' && (chPrev == ']') && (--literalString == 0)) { | |
159 | styler.ColourTo(i, state); | |
160 | state = SCE_LUA_DEFAULT; | |
161 | } | |
162 | } else if (state == SCE_LUA_PREPROCESSOR) { | |
163 | if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { | |
164 | styler.ColourTo(i - 1, state); | |
165 | state = SCE_LUA_DEFAULT; | |
166 | } | |
167 | } else if (state == SCE_LUA_COMMENTLINE) { | |
168 | if (ch == '\r' || ch == '\n') { | |
169 | styler.ColourTo(i - 1, state); | |
170 | state = SCE_LUA_DEFAULT; | |
171 | } | |
172 | } else if (state == SCE_LUA_STRING) { | |
173 | if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { | |
174 | styler.ColourTo(i - 1, state); | |
175 | state = SCE_LUA_STRINGEOL; | |
176 | } else if (ch == '\\') { | |
177 | if (chNext == '\"' || chNext == '\\') { | |
178 | i++; | |
179 | ch = chNext; | |
180 | chNext = styler.SafeGetCharAt(i + 1); | |
181 | } | |
182 | } else if (ch == '\"') { | |
183 | styler.ColourTo(i, state); | |
184 | state = SCE_LUA_DEFAULT; | |
185 | i++; | |
186 | ch = chNext; | |
187 | chNext = styler.SafeGetCharAt(i + 1); | |
188 | } | |
189 | } else if (state == SCE_LUA_CHARACTER) { | |
190 | if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { | |
191 | styler.ColourTo(i - 1, state); | |
192 | state = SCE_LUA_STRINGEOL; | |
193 | } else if (ch == '\\') { | |
194 | if (chNext == '\'' || chNext == '\\') { | |
195 | i++; | |
196 | ch = chNext; | |
197 | chNext = styler.SafeGetCharAt(i + 1); | |
198 | } | |
199 | } else if (ch == '\'') { | |
200 | styler.ColourTo(i, state); | |
201 | state = SCE_LUA_DEFAULT; | |
202 | i++; | |
203 | ch = chNext; | |
204 | chNext = styler.SafeGetCharAt(i + 1); | |
205 | } | |
206 | } | |
207 | ||
208 | if (state == SCE_LUA_DEFAULT) { | |
209 | if (ch == '-' && chNext == '-') { | |
210 | state = SCE_LUA_COMMENTLINE; | |
211 | } else if (ch == '\"') { | |
212 | state = SCE_LUA_STRING; | |
213 | } else if (ch == '\'') { | |
214 | state = SCE_LUA_CHARACTER; | |
215 | } else if (ch == '$' && firstChar) { | |
216 | state = SCE_LUA_PREPROCESSOR; | |
217 | } else if (iswordstart(ch)) { | |
218 | state = SCE_LUA_WORD; | |
219 | } else if (isLuaOperator(ch)) { | |
220 | styler.ColourTo(i, SCE_LUA_OPERATOR); | |
221 | } | |
222 | } | |
223 | } | |
224 | chPrev = ch; | |
225 | firstChar = (ch == '\r' || ch == '\n'); | |
226 | } | |
227 | styler.ColourTo(lengthDoc - 1, state); | |
228 | } | |
d134f170 | 229 | |
65ec6247 RD |
230 | static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], |
231 | Accessor &styler) { | |
232 | unsigned int lengthDoc = startPos + length; | |
233 | int visibleChars = 0; | |
234 | int lineCurrent = styler.GetLine(startPos); | |
235 | int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; | |
236 | int levelCurrent = levelPrev; | |
237 | char chNext = styler[startPos]; | |
238 | int styleNext = styler.StyleAt(startPos); | |
239 | char s[10]; | |
240 | for (unsigned int i = startPos; i < lengthDoc; i++) { | |
241 | char ch = chNext; | |
242 | chNext = styler.SafeGetCharAt(i + 1); | |
243 | int style = styleNext; | |
244 | styleNext = styler.StyleAt(i + 1); | |
245 | bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); | |
246 | if (style == SCE_LUA_WORD) | |
247 | if ( ch == 'e' || ch == 't' || ch == 'd' || ch == 'f') { | |
248 | for (unsigned int j = 0; j < 8; j++) { | |
249 | if (!iswordchar(styler[i + j])) break; | |
250 | s[j] = styler[i + j]; | |
251 | s[j + 1] = '\0'; | |
252 | } | |
d134f170 | 253 | |
65ec6247 RD |
254 | if ((strcmp(s, "then") == 0) || (strcmp(s, "do") == 0) |
255 | || (strcmp(s, "function") == 0)) | |
256 | levelCurrent++; | |
257 | if (strcmp(s, "end") == 0) levelCurrent--; | |
258 | } | |
d134f170 | 259 | |
65ec6247 RD |
260 | if (atEOL) { |
261 | int lev = levelPrev; | |
262 | if (visibleChars == 0) | |
263 | lev |= SC_FOLDLEVELWHITEFLAG; | |
264 | if ((levelCurrent > levelPrev) && (visibleChars > 0)) | |
265 | lev |= SC_FOLDLEVELHEADERFLAG; | |
266 | if (lev != styler.LevelAt(lineCurrent)) { | |
267 | styler.SetLevel(lineCurrent, lev); | |
268 | } | |
269 | lineCurrent++; | |
270 | levelPrev = levelCurrent; | |
271 | visibleChars = 0; | |
272 | } | |
273 | if (!isspacechar(ch)) | |
274 | visibleChars++; | |
275 | } | |
276 | // Fill in the real level of the next line, keeping the current flags as they will be filled in later | |
277 | int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; | |
278 | styler.SetLevel(lineCurrent, levelPrev | flagsNext); | |
d134f170 RD |
279 | } |
280 | ||
65ec6247 | 281 | LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc); |