1 // Scintilla source code edit control
\r
2 /** @file LexInno.cxx
\r
3 ** Lexer for Inno Setup scripts.
\r
5 // Written by Friedrich Vedder <fvedd@t-online.de>, using code from LexOthers.cxx.
\r
6 // The License.txt file describes the conditions under which this software may be distributed.
\r
14 #include "Platform.h"
\r
16 #include "PropSet.h"
\r
17 #include "Accessor.h"
\r
18 #include "StyleContext.h"
\r
19 #include "KeyWords.h"
\r
20 #include "Scintilla.h"
\r
21 #include "SciLexer.h"
\r
23 #ifdef SCI_NAMESPACE
\r
24 using namespace Scintilla;
\r
27 static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
\r
28 int state = SCE_INNO_DEFAULT;
\r
31 char chNext = styler[startPos];
\r
32 int lengthDoc = startPos + length;
\r
33 char *buffer = new char[length];
\r
34 int bufferCount = 0;
\r
35 bool isBOL, isEOL, isWS, isBOLWS = 0;
\r
37 WordList §ionKeywords = *keywordLists[0];
\r
38 WordList &standardKeywords = *keywordLists[1];
\r
39 WordList ¶meterKeywords = *keywordLists[2];
\r
40 WordList &preprocessorKeywords = *keywordLists[3];
\r
41 WordList &pascalKeywords = *keywordLists[4];
\r
42 WordList &userKeywords = *keywordLists[5];
\r
44 // Go through all provided text segment
\r
45 // using the hand-written state machine shown below
\r
46 styler.StartAt(startPos);
\r
47 styler.StartSegment(startPos);
\r
48 for (int i = startPos; i < lengthDoc; i++) {
\r
51 chNext = styler.SafeGetCharAt(i + 1);
\r
53 if (styler.IsLeadByte(ch)) {
\r
54 chNext = styler.SafeGetCharAt(i + 2);
\r
59 isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n');
\r
60 isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t'));
\r
61 isEOL = (ch == '\n' || ch == '\r');
\r
62 isWS = (ch == ' ' || ch == '\t');
\r
65 case SCE_INNO_DEFAULT:
\r
66 if (ch == ';' && isBOLWS) {
\r
67 // Start of a comment
\r
68 state = SCE_INNO_COMMENT;
\r
69 } else if (ch == '[' && isBOLWS) {
\r
70 // Start of a section name
\r
72 state = SCE_INNO_SECTION;
\r
73 } else if (ch == '#' && isBOLWS) {
\r
74 // Start of a preprocessor directive
\r
75 state = SCE_INNO_PREPROC;
\r
76 } else if (ch == '{' && chNext == '#') {
\r
77 // Start of a preprocessor inline directive
\r
78 state = SCE_INNO_PREPROC_INLINE;
\r
79 } else if ((ch == '{' && (chNext == ' ' || chNext == '\t'))
\r
80 || (ch == '(' && chNext == '*')) {
\r
81 // Start of a Pascal comment
\r
82 state = SCE_INNO_COMMENT_PASCAL;
\r
83 } else if (ch == '"') {
\r
84 // Start of a double-quote string
\r
85 state = SCE_INNO_STRING_DOUBLE;
\r
86 } else if (ch == '\'') {
\r
87 // Start of a single-quote string
\r
88 state = SCE_INNO_STRING_SINGLE;
\r
89 } else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) {
\r
90 // Start of an identifier
\r
92 buffer[bufferCount++] = static_cast<char>(tolower(ch));
\r
93 state = SCE_INNO_IDENTIFIER;
\r
95 // Style it the default style
\r
96 styler.ColourTo(i,SCE_INNO_DEFAULT);
\r
100 case SCE_INNO_COMMENT:
\r
102 state = SCE_INNO_DEFAULT;
\r
103 styler.ColourTo(i,SCE_INNO_COMMENT);
\r
107 case SCE_INNO_IDENTIFIER:
\r
108 if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
\r
109 buffer[bufferCount++] = static_cast<char>(tolower(ch));
\r
111 state = SCE_INNO_DEFAULT;
\r
112 buffer[bufferCount] = '\0';
\r
114 // Check if the buffer contains a keyword
\r
115 if (standardKeywords.InList(buffer)) {
\r
116 styler.ColourTo(i-1,SCE_INNO_KEYWORD);
\r
117 } else if (parameterKeywords.InList(buffer)) {
\r
118 styler.ColourTo(i-1,SCE_INNO_PARAMETER);
\r
119 } else if (pascalKeywords.InList(buffer)) {
\r
120 styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL);
\r
121 } else if (userKeywords.InList(buffer)) {
\r
122 styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER);
\r
124 styler.ColourTo(i-1,SCE_INNO_DEFAULT);
\r
127 // Push back the faulty character
\r
128 chNext = styler[i--];
\r
133 case SCE_INNO_SECTION:
\r
135 state = SCE_INNO_DEFAULT;
\r
136 buffer[bufferCount] = '\0';
\r
138 // Check if the buffer contains a section name
\r
139 if (sectionKeywords.InList(buffer)) {
\r
140 styler.ColourTo(i,SCE_INNO_SECTION);
\r
142 styler.ColourTo(i,SCE_INNO_DEFAULT);
\r
144 } else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
\r
145 buffer[bufferCount++] = static_cast<char>(tolower(ch));
\r
147 state = SCE_INNO_DEFAULT;
\r
148 styler.ColourTo(i,SCE_INNO_DEFAULT);
\r
152 case SCE_INNO_PREPROC:
\r
153 if (isWS || isEOL) {
\r
154 if (isascii(chPrev) && isalpha(chPrev)) {
\r
155 state = SCE_INNO_DEFAULT;
\r
156 buffer[bufferCount] = '\0';
\r
158 // Check if the buffer contains a preprocessor directive
\r
159 if (preprocessorKeywords.InList(buffer)) {
\r
160 styler.ColourTo(i-1,SCE_INNO_PREPROC);
\r
162 styler.ColourTo(i-1,SCE_INNO_DEFAULT);
\r
165 // Push back the faulty character
\r
166 chNext = styler[i--];
\r
169 } else if (isascii(ch) && isalpha(ch)) {
\r
170 if (chPrev == '#' || chPrev == ' ' || chPrev == '\t')
\r
172 buffer[bufferCount++] = static_cast<char>(tolower(ch));
\r
176 case SCE_INNO_STRING_DOUBLE:
\r
177 if (ch == '"' || isEOL) {
\r
178 state = SCE_INNO_DEFAULT;
\r
179 styler.ColourTo(i,SCE_INNO_STRING_DOUBLE);
\r
183 case SCE_INNO_STRING_SINGLE:
\r
184 if (ch == '\'' || isEOL) {
\r
185 state = SCE_INNO_DEFAULT;
\r
186 styler.ColourTo(i,SCE_INNO_STRING_SINGLE);
\r
190 case SCE_INNO_PREPROC_INLINE:
\r
192 state = SCE_INNO_DEFAULT;
\r
193 styler.ColourTo(i,SCE_INNO_PREPROC_INLINE);
\r
194 } else if (isEOL) {
\r
195 state = SCE_INNO_DEFAULT;
\r
196 styler.ColourTo(i,SCE_INNO_DEFAULT);
\r
200 case SCE_INNO_COMMENT_PASCAL:
\r
201 if (ch == '}' || (ch == ')' && chPrev == '*')) {
\r
202 state = SCE_INNO_DEFAULT;
\r
203 styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
\r
204 } else if (isEOL) {
\r
205 state = SCE_INNO_DEFAULT;
\r
206 styler.ColourTo(i,SCE_INNO_DEFAULT);
\r
215 static const char * const innoWordListDesc[] = {
\r
219 "Preprocessor directives",
\r
221 "User defined keywords",
\r
225 static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
\r
226 unsigned int endPos = startPos + length;
\r
227 char chNext = styler[startPos];
\r
229 int lineCurrent = styler.GetLine(startPos);
\r
231 bool sectionFlag = false;
\r
232 int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE;
\r
235 for (unsigned int i = startPos; i < endPos; i++) {
\r
237 chNext = styler[i+1];
\r
238 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
\r
239 int style = styler.StyleAt(i);
\r
241 if (style == SCE_INNO_SECTION)
\r
242 sectionFlag = true;
\r
244 if (atEOL || i == endPos - 1) {
\r
246 level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
\r
247 if (level == levelPrev)
\r
248 styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
\r
250 level = levelPrev & SC_FOLDLEVELNUMBERMASK;
\r
251 if (levelPrev & SC_FOLDLEVELHEADERFLAG)
\r
255 styler.SetLevel(lineCurrent, level);
\r
259 sectionFlag = false;
\r
264 LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc);
\r