1
// Scintilla source code edit control
3
** Lexer for Inno Setup scripts.
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.
16
#include "Scintilla.h"
20
#include "LexAccessor.h"
22
#include "StyleContext.h"
23
#include "CharacterSet.h"
24
#include "LexerModule.h"
27
using namespace Scintilla;
30
static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
31
int state = SCE_INNO_DEFAULT;
34
char chNext = styler[startPos];
35
int lengthDoc = startPos + length;
36
char *buffer = new char[length];
38
bool isBOL, isEOL, isWS, isBOLWS = 0;
39
bool isCStyleComment = false;
41
WordList §ionKeywords = *keywordLists[0];
42
WordList &standardKeywords = *keywordLists[1];
43
WordList ¶meterKeywords = *keywordLists[2];
44
WordList &preprocessorKeywords = *keywordLists[3];
45
WordList &pascalKeywords = *keywordLists[4];
46
WordList &userKeywords = *keywordLists[5];
48
int curLine = styler.GetLine(startPos);
49
int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0;
50
bool isCode = (curLineState == 1);
52
// Go through all provided text segment
53
// using the hand-written state machine shown below
54
styler.StartAt(startPos);
55
styler.StartSegment(startPos);
56
for (int i = startPos; i < lengthDoc; i++) {
59
chNext = styler.SafeGetCharAt(i + 1);
61
if (styler.IsLeadByte(ch)) {
62
chNext = styler.SafeGetCharAt(i + 2);
67
isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n');
68
isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t'));
69
isEOL = (ch == '\n' || ch == '\r');
70
isWS = (ch == ' ' || ch == '\t');
72
if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
73
// Remember the line state for future incremental lexing
74
curLine = styler.GetLine(i);
75
styler.SetLineState(curLine, (isCode ? 1 : 0));
79
case SCE_INNO_DEFAULT:
80
if (!isCode && ch == ';' && isBOLWS) {
82
state = SCE_INNO_COMMENT;
83
} else if (ch == '[' && isBOLWS) {
84
// Start of a section name
86
state = SCE_INNO_SECTION;
87
} else if (ch == '#' && isBOLWS) {
88
// Start of a preprocessor directive
89
state = SCE_INNO_PREPROC;
90
} else if (!isCode && ch == '{' && chNext != '{' && chPrev != '{') {
91
// Start of an inline expansion
92
state = SCE_INNO_INLINE_EXPANSION;
93
} else if (isCode && (ch == '{' || (ch == '(' && chNext == '*'))) {
94
// Start of a Pascal comment
95
state = SCE_INNO_COMMENT_PASCAL;
96
isCStyleComment = false;
97
} else if (isCode && ch == '/' && chNext == '/') {
98
// Apparently, C-style comments are legal, too
99
state = SCE_INNO_COMMENT_PASCAL;
100
isCStyleComment = true;
101
} else if (ch == '"') {
102
// Start of a double-quote string
103
state = SCE_INNO_STRING_DOUBLE;
104
} else if (ch == '\'') {
105
// Start of a single-quote string
106
state = SCE_INNO_STRING_SINGLE;
107
} else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) {
108
// Start of an identifier
110
buffer[bufferCount++] = static_cast<char>(tolower(ch));
111
state = SCE_INNO_IDENTIFIER;
113
// Style it the default style
114
styler.ColourTo(i,SCE_INNO_DEFAULT);
118
case SCE_INNO_COMMENT:
120
state = SCE_INNO_DEFAULT;
121
styler.ColourTo(i,SCE_INNO_COMMENT);
125
case SCE_INNO_IDENTIFIER:
126
if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
127
buffer[bufferCount++] = static_cast<char>(tolower(ch));
129
state = SCE_INNO_DEFAULT;
130
buffer[bufferCount] = '\0';
132
// Check if the buffer contains a keyword
133
if (!isCode && standardKeywords.InList(buffer)) {
134
styler.ColourTo(i-1,SCE_INNO_KEYWORD);
135
} else if (!isCode && parameterKeywords.InList(buffer)) {
136
styler.ColourTo(i-1,SCE_INNO_PARAMETER);
137
} else if (isCode && pascalKeywords.InList(buffer)) {
138
styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL);
139
} else if (!isCode && userKeywords.InList(buffer)) {
140
styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER);
142
styler.ColourTo(i-1,SCE_INNO_DEFAULT);
145
// Push back the faulty character
146
chNext = styler[i--];
151
case SCE_INNO_SECTION:
153
state = SCE_INNO_DEFAULT;
154
buffer[bufferCount] = '\0';
156
// Check if the buffer contains a section name
157
if (sectionKeywords.InList(buffer)) {
158
styler.ColourTo(i,SCE_INNO_SECTION);
159
isCode = !CompareCaseInsensitive(buffer, "code");
161
styler.ColourTo(i,SCE_INNO_DEFAULT);
163
} else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
164
buffer[bufferCount++] = static_cast<char>(tolower(ch));
166
state = SCE_INNO_DEFAULT;
167
styler.ColourTo(i,SCE_INNO_DEFAULT);
171
case SCE_INNO_PREPROC:
173
if (isascii(chPrev) && isalpha(chPrev)) {
174
state = SCE_INNO_DEFAULT;
175
buffer[bufferCount] = '\0';
177
// Check if the buffer contains a preprocessor directive
178
if (preprocessorKeywords.InList(buffer)) {
179
styler.ColourTo(i-1,SCE_INNO_PREPROC);
181
styler.ColourTo(i-1,SCE_INNO_DEFAULT);
184
// Push back the faulty character
185
chNext = styler[i--];
188
} else if (isascii(ch) && isalpha(ch)) {
189
if (chPrev == '#' || chPrev == ' ' || chPrev == '\t')
191
buffer[bufferCount++] = static_cast<char>(tolower(ch));
195
case SCE_INNO_STRING_DOUBLE:
196
if (ch == '"' || isEOL) {
197
state = SCE_INNO_DEFAULT;
198
styler.ColourTo(i,SCE_INNO_STRING_DOUBLE);
202
case SCE_INNO_STRING_SINGLE:
203
if (ch == '\'' || isEOL) {
204
state = SCE_INNO_DEFAULT;
205
styler.ColourTo(i,SCE_INNO_STRING_SINGLE);
209
case SCE_INNO_INLINE_EXPANSION:
211
state = SCE_INNO_DEFAULT;
212
styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION);
214
state = SCE_INNO_DEFAULT;
215
styler.ColourTo(i,SCE_INNO_DEFAULT);
219
case SCE_INNO_COMMENT_PASCAL:
220
if (isCStyleComment) {
222
state = SCE_INNO_DEFAULT;
223
styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
226
if (ch == '}' || (ch == ')' && chPrev == '*')) {
227
state = SCE_INNO_DEFAULT;
228
styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
230
state = SCE_INNO_DEFAULT;
231
styler.ColourTo(i,SCE_INNO_DEFAULT);
241
static const char * const innoWordListDesc[] = {
245
"Preprocessor directives",
247
"User defined keywords",
251
static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
252
unsigned int endPos = startPos + length;
253
char chNext = styler[startPos];
255
int lineCurrent = styler.GetLine(startPos);
257
bool sectionFlag = false;
258
int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE;
261
for (unsigned int i = startPos; i < endPos; i++) {
263
chNext = styler[i+1];
264
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
265
int style = styler.StyleAt(i);
267
if (style == SCE_INNO_SECTION)
270
if (atEOL || i == endPos - 1) {
272
level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
273
if (level == levelPrev)
274
styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
276
level = levelPrev & SC_FOLDLEVELNUMBERMASK;
277
if (levelPrev & SC_FOLDLEVELHEADERFLAG)
281
styler.SetLevel(lineCurrent, level);
290
LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc);