]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexInno.cxx
6d1102c65480e3da3e9fd19e250a08a299f5129f
[wxWidgets.git] / src / stc / scintilla / src / LexInno.cxx
1 // Scintilla source code edit control
2 /** @file LexInno.cxx
3 ** Lexer for Inno Setup scripts.
4 **/
5 // Written by Friedrich Vedder <fvedd@t-online.de>, using code from LexOthers.cxx.
6 // The License.txt file describes the conditions under which this software may be distributed.
7
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13
14 #include "Platform.h"
15
16 #include "CharClassify.h"
17 #include "PropSet.h"
18 #include "Accessor.h"
19 #include "StyleContext.h"
20 #include "KeyWords.h"
21 #include "Scintilla.h"
22 #include "SciLexer.h"
23
24 #ifdef SCI_NAMESPACE
25 using namespace Scintilla;
26 #endif
27
28 static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
29 int state = SCE_INNO_DEFAULT;
30 char chPrev;
31 char ch = 0;
32 char chNext = styler[startPos];
33 int lengthDoc = startPos + length;
34 char *buffer = new char[length];
35 int bufferCount = 0;
36 bool isBOL, isEOL, isWS, isBOLWS = 0;
37 bool isCode = false;
38 bool isCStyleComment = false;
39
40 WordList &sectionKeywords = *keywordLists[0];
41 WordList &standardKeywords = *keywordLists[1];
42 WordList &parameterKeywords = *keywordLists[2];
43 WordList &preprocessorKeywords = *keywordLists[3];
44 WordList &pascalKeywords = *keywordLists[4];
45 WordList &userKeywords = *keywordLists[5];
46
47 // Go through all provided text segment
48 // using the hand-written state machine shown below
49 styler.StartAt(startPos);
50 styler.StartSegment(startPos);
51 for (int i = startPos; i < lengthDoc; i++) {
52 chPrev = ch;
53 ch = chNext;
54 chNext = styler.SafeGetCharAt(i + 1);
55
56 if (styler.IsLeadByte(ch)) {
57 chNext = styler.SafeGetCharAt(i + 2);
58 i++;
59 continue;
60 }
61
62 isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n');
63 isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t'));
64 isEOL = (ch == '\n' || ch == '\r');
65 isWS = (ch == ' ' || ch == '\t');
66
67 switch(state) {
68 case SCE_INNO_DEFAULT:
69 if (!isCode && ch == ';' && isBOLWS) {
70 // Start of a comment
71 state = SCE_INNO_COMMENT;
72 } else if (ch == '[' && isBOLWS) {
73 // Start of a section name
74 bufferCount = 0;
75 state = SCE_INNO_SECTION;
76 } else if (ch == '#' && isBOLWS) {
77 // Start of a preprocessor directive
78 state = SCE_INNO_PREPROC;
79 } else if (!isCode && ch == '{' && chNext != '{' && chPrev != '{') {
80 // Start of an inline expansion
81 state = SCE_INNO_INLINE_EXPANSION;
82 } else if (isCode && (ch == '{' || (ch == '(' && chNext == '*'))) {
83 // Start of a Pascal comment
84 state = SCE_INNO_COMMENT_PASCAL;
85 isCStyleComment = false;
86 } else if (isCode && ch == '/' && chNext == '/') {
87 // Apparently, C-style comments are legal, too
88 state = SCE_INNO_COMMENT_PASCAL;
89 isCStyleComment = true;
90 } else if (ch == '"') {
91 // Start of a double-quote string
92 state = SCE_INNO_STRING_DOUBLE;
93 } else if (ch == '\'') {
94 // Start of a single-quote string
95 state = SCE_INNO_STRING_SINGLE;
96 } else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) {
97 // Start of an identifier
98 bufferCount = 0;
99 buffer[bufferCount++] = static_cast<char>(tolower(ch));
100 state = SCE_INNO_IDENTIFIER;
101 } else {
102 // Style it the default style
103 styler.ColourTo(i,SCE_INNO_DEFAULT);
104 }
105 break;
106
107 case SCE_INNO_COMMENT:
108 if (isEOL) {
109 state = SCE_INNO_DEFAULT;
110 styler.ColourTo(i,SCE_INNO_COMMENT);
111 }
112 break;
113
114 case SCE_INNO_IDENTIFIER:
115 if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
116 buffer[bufferCount++] = static_cast<char>(tolower(ch));
117 } else {
118 state = SCE_INNO_DEFAULT;
119 buffer[bufferCount] = '\0';
120
121 // Check if the buffer contains a keyword
122 if (!isCode && standardKeywords.InList(buffer)) {
123 styler.ColourTo(i-1,SCE_INNO_KEYWORD);
124 } else if (!isCode && parameterKeywords.InList(buffer)) {
125 styler.ColourTo(i-1,SCE_INNO_PARAMETER);
126 } else if (isCode && pascalKeywords.InList(buffer)) {
127 styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL);
128 } else if (!isCode && userKeywords.InList(buffer)) {
129 styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER);
130 } else {
131 styler.ColourTo(i-1,SCE_INNO_DEFAULT);
132 }
133
134 // Push back the faulty character
135 chNext = styler[i--];
136 ch = chPrev;
137 }
138 break;
139
140 case SCE_INNO_SECTION:
141 if (ch == ']') {
142 state = SCE_INNO_DEFAULT;
143 buffer[bufferCount] = '\0';
144
145 // Check if the buffer contains a section name
146 if (sectionKeywords.InList(buffer)) {
147 styler.ColourTo(i,SCE_INNO_SECTION);
148 isCode = !CompareCaseInsensitive(buffer, "code");
149 } else {
150 styler.ColourTo(i,SCE_INNO_DEFAULT);
151 }
152 } else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
153 buffer[bufferCount++] = static_cast<char>(tolower(ch));
154 } else {
155 state = SCE_INNO_DEFAULT;
156 styler.ColourTo(i,SCE_INNO_DEFAULT);
157 }
158 break;
159
160 case SCE_INNO_PREPROC:
161 if (isWS || isEOL) {
162 if (isascii(chPrev) && isalpha(chPrev)) {
163 state = SCE_INNO_DEFAULT;
164 buffer[bufferCount] = '\0';
165
166 // Check if the buffer contains a preprocessor directive
167 if (preprocessorKeywords.InList(buffer)) {
168 styler.ColourTo(i-1,SCE_INNO_PREPROC);
169 } else {
170 styler.ColourTo(i-1,SCE_INNO_DEFAULT);
171 }
172
173 // Push back the faulty character
174 chNext = styler[i--];
175 ch = chPrev;
176 }
177 } else if (isascii(ch) && isalpha(ch)) {
178 if (chPrev == '#' || chPrev == ' ' || chPrev == '\t')
179 bufferCount = 0;
180 buffer[bufferCount++] = static_cast<char>(tolower(ch));
181 }
182 break;
183
184 case SCE_INNO_STRING_DOUBLE:
185 if (ch == '"' || isEOL) {
186 state = SCE_INNO_DEFAULT;
187 styler.ColourTo(i,SCE_INNO_STRING_DOUBLE);
188 }
189 break;
190
191 case SCE_INNO_STRING_SINGLE:
192 if (ch == '\'' || isEOL) {
193 state = SCE_INNO_DEFAULT;
194 styler.ColourTo(i,SCE_INNO_STRING_SINGLE);
195 }
196 break;
197
198 case SCE_INNO_INLINE_EXPANSION:
199 if (ch == '}') {
200 state = SCE_INNO_DEFAULT;
201 styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION);
202 } else if (isEOL) {
203 state = SCE_INNO_DEFAULT;
204 styler.ColourTo(i,SCE_INNO_DEFAULT);
205 }
206 break;
207
208 case SCE_INNO_COMMENT_PASCAL:
209 if (isCStyleComment) {
210 if (isEOL) {
211 state = SCE_INNO_DEFAULT;
212 styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
213 }
214 } else {
215 if (ch == '}' || (ch == ')' && chPrev == '*')) {
216 state = SCE_INNO_DEFAULT;
217 styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
218 } else if (isEOL) {
219 state = SCE_INNO_DEFAULT;
220 styler.ColourTo(i,SCE_INNO_DEFAULT);
221 }
222 }
223 break;
224
225 }
226 }
227 delete []buffer;
228 }
229
230 static const char * const innoWordListDesc[] = {
231 "Sections",
232 "Keywords",
233 "Parameters",
234 "Preprocessor directives",
235 "Pascal keywords",
236 "User defined keywords",
237 0
238 };
239
240 static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
241 unsigned int endPos = startPos + length;
242 char chNext = styler[startPos];
243
244 int lineCurrent = styler.GetLine(startPos);
245
246 bool sectionFlag = false;
247 int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE;
248 int level;
249
250 for (unsigned int i = startPos; i < endPos; i++) {
251 char ch = chNext;
252 chNext = styler[i+1];
253 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
254 int style = styler.StyleAt(i);
255
256 if (style == SCE_INNO_SECTION)
257 sectionFlag = true;
258
259 if (atEOL || i == endPos - 1) {
260 if (sectionFlag) {
261 level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
262 if (level == levelPrev)
263 styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
264 } else {
265 level = levelPrev & SC_FOLDLEVELNUMBERMASK;
266 if (levelPrev & SC_FOLDLEVELHEADERFLAG)
267 level++;
268 }
269
270 styler.SetLevel(lineCurrent, level);
271
272 levelPrev = level;
273 lineCurrent++;
274 sectionFlag = false;
275 }
276 }
277 }
278
279 LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc);