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
);