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 "CharClassify.h"
19
#include "StyleContext.h"
21
#include "Scintilla.h"
25
using namespace Scintilla;
28
static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
29
int state = SCE_INNO_DEFAULT;
32
char chNext = styler[startPos];
33
int lengthDoc = startPos + length;
34
char *buffer = new char[length];
36
bool isBOL, isEOL, isWS, isBOLWS = 0;
38
bool isCStyleComment = false;
40
WordList §ionKeywords = *keywordLists[0];
41
WordList &standardKeywords = *keywordLists[1];
42
WordList ¶meterKeywords = *keywordLists[2];
43
WordList &preprocessorKeywords = *keywordLists[3];
44
WordList &pascalKeywords = *keywordLists[4];
45
WordList &userKeywords = *keywordLists[5];
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++) {
54
chNext = styler.SafeGetCharAt(i + 1);
56
if (styler.IsLeadByte(ch)) {
57
chNext = styler.SafeGetCharAt(i + 2);
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');
68
case SCE_INNO_DEFAULT:
69
if (!isCode && ch == ';' && isBOLWS) {
71
state = SCE_INNO_COMMENT;
72
} else if (ch == '[' && isBOLWS) {
73
// Start of a section name
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
99
buffer[bufferCount++] = static_cast<char>(tolower(ch));
100
state = SCE_INNO_IDENTIFIER;
102
// Style it the default style
103
styler.ColourTo(i,SCE_INNO_DEFAULT);
107
case SCE_INNO_COMMENT:
109
state = SCE_INNO_DEFAULT;
110
styler.ColourTo(i,SCE_INNO_COMMENT);
114
case SCE_INNO_IDENTIFIER:
115
if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
116
buffer[bufferCount++] = static_cast<char>(tolower(ch));
118
state = SCE_INNO_DEFAULT;
119
buffer[bufferCount] = '\0';
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);
131
styler.ColourTo(i-1,SCE_INNO_DEFAULT);
134
// Push back the faulty character
135
chNext = styler[i--];
140
case SCE_INNO_SECTION:
142
state = SCE_INNO_DEFAULT;
143
buffer[bufferCount] = '\0';
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");
150
styler.ColourTo(i,SCE_INNO_DEFAULT);
152
} else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
153
buffer[bufferCount++] = static_cast<char>(tolower(ch));
155
state = SCE_INNO_DEFAULT;
156
styler.ColourTo(i,SCE_INNO_DEFAULT);
160
case SCE_INNO_PREPROC:
162
if (isascii(chPrev) && isalpha(chPrev)) {
163
state = SCE_INNO_DEFAULT;
164
buffer[bufferCount] = '\0';
166
// Check if the buffer contains a preprocessor directive
167
if (preprocessorKeywords.InList(buffer)) {
168
styler.ColourTo(i-1,SCE_INNO_PREPROC);
170
styler.ColourTo(i-1,SCE_INNO_DEFAULT);
173
// Push back the faulty character
174
chNext = styler[i--];
177
} else if (isascii(ch) && isalpha(ch)) {
178
if (chPrev == '#' || chPrev == ' ' || chPrev == '\t')
180
buffer[bufferCount++] = static_cast<char>(tolower(ch));
184
case SCE_INNO_STRING_DOUBLE:
185
if (ch == '"' || isEOL) {
186
state = SCE_INNO_DEFAULT;
187
styler.ColourTo(i,SCE_INNO_STRING_DOUBLE);
191
case SCE_INNO_STRING_SINGLE:
192
if (ch == '\'' || isEOL) {
193
state = SCE_INNO_DEFAULT;
194
styler.ColourTo(i,SCE_INNO_STRING_SINGLE);
198
case SCE_INNO_INLINE_EXPANSION:
200
state = SCE_INNO_DEFAULT;
201
styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION);
203
state = SCE_INNO_DEFAULT;
204
styler.ColourTo(i,SCE_INNO_DEFAULT);
208
case SCE_INNO_COMMENT_PASCAL:
209
if (isCStyleComment) {
211
state = SCE_INNO_DEFAULT;
212
styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
215
if (ch == '}' || (ch == ')' && chPrev == '*')) {
216
state = SCE_INNO_DEFAULT;
217
styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
219
state = SCE_INNO_DEFAULT;
220
styler.ColourTo(i,SCE_INNO_DEFAULT);
230
static const char * const innoWordListDesc[] = {
234
"Preprocessor directives",
236
"User defined keywords",
240
static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
241
unsigned int endPos = startPos + length;
242
char chNext = styler[startPos];
244
int lineCurrent = styler.GetLine(startPos);
246
bool sectionFlag = false;
247
int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE;
250
for (unsigned int i = startPos; i < endPos; i++) {
252
chNext = styler[i+1];
253
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
254
int style = styler.StyleAt(i);
256
if (style == SCE_INNO_SECTION)
259
if (atEOL || i == endPos - 1) {
261
level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
262
if (level == levelPrev)
263
styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
265
level = levelPrev & SC_FOLDLEVELNUMBERMASK;
266
if (levelPrev & SC_FOLDLEVELHEADERFLAG)
270
styler.SetLevel(lineCurrent, level);
279
LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc);