]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexLua.cxx
338a04e327f0661683fbed476cf9c0f10bfee388
[wxWidgets.git] / contrib / src / stc / scintilla / src / LexLua.cxx
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 ** Modified by Marcos E. Wurzius
8 **/
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <stdarg.h>
14 #include <stdio.h>
15 #include <fcntl.h>
16
17 #include "Platform.h"
18
19 #include "PropSet.h"
20 #include "Accessor.h"
21 #include "StyleContext.h"
22 #include "KeyWords.h"
23 #include "Scintilla.h"
24 #include "SciLexer.h"
25
26
27 static inline bool IsAWordChar(const int ch) {
28 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
29 }
30
31 inline bool IsAWordStart(const int ch) {
32 return (ch < 0x80) && (isalnum(ch) || ch == '_');
33 }
34
35
36 inline bool isLuaOperator(char ch) {
37 if (isalnum(ch))
38 return false;
39 // '.' left out as it is used to make up numbers
40 if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
41 ch == '(' || ch == ')' || ch == '=' ||
42 ch == '{' || ch == '}' || ch == '~' ||
43 ch == '[' || ch == ']' || ch == ';' ||
44 ch == '<' || ch == '>' || ch == ',' ||
45 ch == '.' || ch == '^' || ch == '%' || ch == ':')
46 return true;
47 return false;
48 }
49
50
51 static void ColouriseLuaDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
52 Accessor &styler) {
53
54 WordList &keywords = *keywordlists[0];
55 WordList &keywords2 = *keywordlists[1];
56 WordList &keywords3 = *keywordlists[2];
57 WordList &keywords4 = *keywordlists[3];
58 WordList &keywords5 = *keywordlists[4];
59 WordList &keywords6 = *keywordlists[5];
60 int literalString = 0;
61 int literalStringFlag =0;
62
63 // Do not leak onto next line
64 if (initStyle == SCE_LUA_STRINGEOL)
65 initStyle = SCE_LUA_DEFAULT;
66
67 StyleContext sc(startPos, length, initStyle, styler);
68 if(startPos == 0 && sc.ch == '#') sc.SetState(SCE_LUA_COMMENTLINE);
69 for (; sc.More(); sc.Forward()) {
70
71 // Handle line continuation generically.
72 if (sc.ch == '\\') {
73 if (sc.Match("\\\n")) {
74 sc.Forward();
75 sc.Forward();
76 continue;
77 }
78 if (sc.Match("\\\r\n")) {
79 sc.Forward();
80 sc.Forward();
81 sc.Forward();
82 continue;
83 }
84 }
85
86 // Determine if the current state should terminate.
87 if (sc.state == SCE_LUA_OPERATOR) {
88 sc.SetState(SCE_LUA_DEFAULT);
89 } else if (sc.state == SCE_LUA_NUMBER) {
90 if (!IsAWordChar(sc.ch)) {
91 sc.SetState(SCE_LUA_DEFAULT);
92 }
93 } else if (sc.state == SCE_LUA_IDENTIFIER) {
94 if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
95 char s[100];
96 sc.GetCurrent(s, sizeof(s));
97 if (keywords.InList(s)) {
98 sc.ChangeState(SCE_LUA_WORD);
99 } else if (keywords2.InList(s)) {
100 sc.ChangeState(SCE_LUA_WORD2);
101 } else if (keywords3.InList(s)) {
102 sc.ChangeState(SCE_LUA_WORD3);
103 } else if (keywords4.InList(s)) {
104 sc.ChangeState(SCE_LUA_WORD4);
105 } else if (keywords5.InList(s)) {
106 sc.ChangeState(SCE_LUA_WORD5);
107 } else if (keywords6.InList(s)) {
108 sc.ChangeState(SCE_LUA_WORD6);
109 }
110 sc.SetState(SCE_LUA_DEFAULT);
111 }
112
113
114 } else if (sc.state == SCE_LUA_COMMENTLINE ) {
115 if (sc.atLineEnd) {
116 sc.SetState(SCE_LUA_DEFAULT);
117 }
118 } else if (sc.state == SCE_LUA_STRING) {
119 if (sc.ch == '\\') {
120 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
121 sc.Forward();
122 }
123 } else if (sc.ch == '\"') {
124 sc.ForwardSetState(SCE_LUA_DEFAULT);
125 } else if (sc.atLineEnd) {
126 sc.ChangeState(SCE_LUA_STRINGEOL);
127 sc.ForwardSetState(SCE_LUA_DEFAULT);
128 }
129
130 } else if (sc.state == SCE_LUA_CHARACTER) {
131 if (sc.ch == '\\') {
132 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
133 sc.Forward();
134 }
135 } else if (sc.ch == '\'') {
136 sc.ForwardSetState(SCE_LUA_DEFAULT);
137 } else if (sc.atLineEnd) {
138 sc.ChangeState(SCE_LUA_STRINGEOL);
139 sc.ForwardSetState(SCE_LUA_DEFAULT);
140 }
141 } else if (sc.state == SCE_LUA_LITERALSTRING) {
142 if (sc.chPrev == '[' && sc.ch == '[' && literalStringFlag != 1) {
143 literalString++;
144 literalStringFlag = 1;
145 }
146 else if (sc.chPrev == ']' && sc.ch == ']' && literalStringFlag != 2 ) {
147 if((--literalString == 1))
148 sc.ForwardSetState(SCE_LUA_DEFAULT);
149 literalStringFlag = 2;
150 }
151 else literalStringFlag = 0;
152 }
153 // Determine if a new state should be entered.
154 if (sc.state == SCE_LUA_DEFAULT) {
155 if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
156 sc.SetState(SCE_LUA_NUMBER);
157 } else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
158 sc.SetState(SCE_LUA_IDENTIFIER);
159 } else if (sc.ch == '\"') {
160 sc.SetState(SCE_LUA_STRING);
161 } else if (sc.ch == '\'') {
162 sc.SetState(SCE_LUA_CHARACTER);
163 } else if (sc.ch == '[' && sc.chNext == '[') {
164 sc.SetState(SCE_LUA_LITERALSTRING);
165 literalString = 1;
166 } else if (sc.ch == '-' && sc.chNext == '-') {
167 sc.SetState(SCE_LUA_COMMENTLINE);
168 } else if (isLuaOperator(static_cast<char>(sc.ch))) {
169 sc.SetState(SCE_LUA_OPERATOR);
170 }
171 }
172 }
173 sc.Complete();
174 }
175
176
177 static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
178 Accessor &styler) {
179 unsigned int lengthDoc = startPos + length;
180 int visibleChars = 0;
181 int lineCurrent = styler.GetLine(startPos);
182 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
183 int levelCurrent = levelPrev;
184 char chNext = styler[startPos];
185 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
186 int styleNext = styler.StyleAt(startPos);
187 char s[10];
188 for (unsigned int i = startPos; i < lengthDoc; i++) {
189 char ch = chNext;
190 chNext = styler.SafeGetCharAt(i + 1);
191 int style = styleNext;
192 styleNext = styler.StyleAt(i + 1);
193 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
194 if (style == SCE_LUA_WORD) {
195 if ( ch == 'i' || ch == 'e' || ch == 't' || ch == 'd' || ch == 'f') {
196 for (unsigned int j = 0; j < 8; j++) {
197 if (!iswordchar(styler[i + j]))
198 break;
199 s[j] = styler[i + j];
200 s[j + 1] = '\0';
201 }
202
203 if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0)
204 || (strcmp(s, "function") == 0))
205 levelCurrent++;
206 if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0))
207 levelCurrent--;
208
209 }
210 }
211 else if (style == SCE_LUA_OPERATOR)
212 {
213 if(ch == '{' || ch == '(')
214 levelCurrent++;
215 else if(ch == '}' || ch == ')')
216 levelCurrent--;
217 }
218
219 if (atEOL) {
220 int lev = levelPrev;
221 if (visibleChars == 0 && foldCompact)
222 lev |= SC_FOLDLEVELWHITEFLAG;
223 if ((levelCurrent > levelPrev) && (visibleChars > 0))
224 lev |= SC_FOLDLEVELHEADERFLAG;
225 if (lev != styler.LevelAt(lineCurrent)) {
226 styler.SetLevel(lineCurrent, lev);
227 }
228 lineCurrent++;
229 levelPrev = levelCurrent;
230 visibleChars = 0;
231 }
232 if (!isspacechar(ch))
233 visibleChars++;
234 }
235 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
236
237 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
238 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
239 }
240
241 LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc);