updated Scintilla to 2.29
[TortoiseGit.git] / ext / scintilla / lexers / LexInno.cxx
blob117160d146198477b6ea92a5d4693f8c04736667
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.
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <assert.h>
13 #include <ctype.h>
15 #include "ILexer.h"
16 #include "Scintilla.h"
17 #include "SciLexer.h"
19 #include "WordList.h"
20 #include "LexAccessor.h"
21 #include "Accessor.h"
22 #include "StyleContext.h"
23 #include "CharacterSet.h"
24 #include "LexerModule.h"
26 #ifdef SCI_NAMESPACE
27 using namespace Scintilla;
28 #endif
30 static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
31 int state = SCE_INNO_DEFAULT;
32 char chPrev;
33 char ch = 0;
34 char chNext = styler[startPos];
35 int lengthDoc = startPos + length;
36 char *buffer = new char[length];
37 int bufferCount = 0;
38 bool isBOL, isEOL, isWS, isBOLWS = 0;
39 bool isCStyleComment = false;
41 WordList &sectionKeywords = *keywordLists[0];
42 WordList &standardKeywords = *keywordLists[1];
43 WordList &parameterKeywords = *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++) {
57 chPrev = ch;
58 ch = chNext;
59 chNext = styler.SafeGetCharAt(i + 1);
61 if (styler.IsLeadByte(ch)) {
62 chNext = styler.SafeGetCharAt(i + 2);
63 i++;
64 continue;
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));
78 switch(state) {
79 case SCE_INNO_DEFAULT:
80 if (!isCode && ch == ';' && isBOLWS) {
81 // Start of a comment
82 state = SCE_INNO_COMMENT;
83 } else if (ch == '[' && isBOLWS) {
84 // Start of a section name
85 bufferCount = 0;
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
109 bufferCount = 0;
110 buffer[bufferCount++] = static_cast<char>(tolower(ch));
111 state = SCE_INNO_IDENTIFIER;
112 } else {
113 // Style it the default style
114 styler.ColourTo(i,SCE_INNO_DEFAULT);
116 break;
118 case SCE_INNO_COMMENT:
119 if (isEOL) {
120 state = SCE_INNO_DEFAULT;
121 styler.ColourTo(i,SCE_INNO_COMMENT);
123 break;
125 case SCE_INNO_IDENTIFIER:
126 if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
127 buffer[bufferCount++] = static_cast<char>(tolower(ch));
128 } else {
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);
141 } else {
142 styler.ColourTo(i-1,SCE_INNO_DEFAULT);
145 // Push back the faulty character
146 chNext = styler[i--];
147 ch = chPrev;
149 break;
151 case SCE_INNO_SECTION:
152 if (ch == ']') {
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");
160 } else {
161 styler.ColourTo(i,SCE_INNO_DEFAULT);
163 } else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
164 buffer[bufferCount++] = static_cast<char>(tolower(ch));
165 } else {
166 state = SCE_INNO_DEFAULT;
167 styler.ColourTo(i,SCE_INNO_DEFAULT);
169 break;
171 case SCE_INNO_PREPROC:
172 if (isWS || isEOL) {
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);
180 } else {
181 styler.ColourTo(i-1,SCE_INNO_DEFAULT);
184 // Push back the faulty character
185 chNext = styler[i--];
186 ch = chPrev;
188 } else if (isascii(ch) && isalpha(ch)) {
189 if (chPrev == '#' || chPrev == ' ' || chPrev == '\t')
190 bufferCount = 0;
191 buffer[bufferCount++] = static_cast<char>(tolower(ch));
193 break;
195 case SCE_INNO_STRING_DOUBLE:
196 if (ch == '"' || isEOL) {
197 state = SCE_INNO_DEFAULT;
198 styler.ColourTo(i,SCE_INNO_STRING_DOUBLE);
200 break;
202 case SCE_INNO_STRING_SINGLE:
203 if (ch == '\'' || isEOL) {
204 state = SCE_INNO_DEFAULT;
205 styler.ColourTo(i,SCE_INNO_STRING_SINGLE);
207 break;
209 case SCE_INNO_INLINE_EXPANSION:
210 if (ch == '}') {
211 state = SCE_INNO_DEFAULT;
212 styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION);
213 } else if (isEOL) {
214 state = SCE_INNO_DEFAULT;
215 styler.ColourTo(i,SCE_INNO_DEFAULT);
217 break;
219 case SCE_INNO_COMMENT_PASCAL:
220 if (isCStyleComment) {
221 if (isEOL) {
222 state = SCE_INNO_DEFAULT;
223 styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
225 } else {
226 if (ch == '}' || (ch == ')' && chPrev == '*')) {
227 state = SCE_INNO_DEFAULT;
228 styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
229 } else if (isEOL) {
230 state = SCE_INNO_DEFAULT;
231 styler.ColourTo(i,SCE_INNO_DEFAULT);
234 break;
238 delete []buffer;
241 static const char * const innoWordListDesc[] = {
242 "Sections",
243 "Keywords",
244 "Parameters",
245 "Preprocessor directives",
246 "Pascal keywords",
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;
259 int level;
261 for (unsigned int i = startPos; i < endPos; i++) {
262 char ch = chNext;
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)
268 sectionFlag = true;
270 if (atEOL || i == endPos - 1) {
271 if (sectionFlag) {
272 level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
273 if (level == levelPrev)
274 styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
275 } else {
276 level = levelPrev & SC_FOLDLEVELNUMBERMASK;
277 if (levelPrev & SC_FOLDLEVELHEADERFLAG)
278 level++;
281 styler.SetLevel(lineCurrent, level);
283 levelPrev = level;
284 lineCurrent++;
285 sectionFlag = false;
290 LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc);