You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
8.1 KiB
290 lines
8.1 KiB
// Scintilla source code edit control |
|
/** @file LexInno.cxx |
|
** Lexer for Inno Setup scripts. |
|
**/ |
|
// Written by Friedrich Vedder <fvedd@t-online.de>, using code from LexOthers.cxx. |
|
// The License.txt file describes the conditions under which this software may be distributed. |
|
|
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <ctype.h> |
|
#include <stdio.h> |
|
#include <stdarg.h> |
|
|
|
#include "Platform.h" |
|
|
|
#include "PropSet.h" |
|
#include "Accessor.h" |
|
#include "StyleContext.h" |
|
#include "KeyWords.h" |
|
#include "Scintilla.h" |
|
#include "SciLexer.h" |
|
|
|
static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) { |
|
int state = SCE_INNO_DEFAULT; |
|
char chPrev; |
|
char ch = 0; |
|
char chNext = styler[startPos]; |
|
int lengthDoc = startPos + length; |
|
char *buffer = new char[length]; |
|
int bufferCount = 0; |
|
bool isBOL, isEOL, isWS, isBOLWS = 0; |
|
|
|
WordList §ionKeywords = *keywordLists[0]; |
|
WordList &standardKeywords = *keywordLists[1]; |
|
WordList ¶meterKeywords = *keywordLists[2]; |
|
WordList &preprocessorKeywords = *keywordLists[3]; |
|
WordList &pascalKeywords = *keywordLists[4]; |
|
WordList &userKeywords = *keywordLists[5]; |
|
|
|
// Go through all provided text segment |
|
// using the hand-written state machine shown below |
|
styler.StartAt(startPos); |
|
styler.StartSegment(startPos); |
|
for (int i = startPos; i < lengthDoc; i++) { |
|
chPrev = ch; |
|
ch = chNext; |
|
chNext = styler.SafeGetCharAt(i + 1); |
|
|
|
if (styler.IsLeadByte(ch)) { |
|
chNext = styler.SafeGetCharAt(i + 2); |
|
i++; |
|
continue; |
|
} |
|
|
|
isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n'); |
|
isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t')); |
|
isEOL = (ch == '\n' || ch == '\r'); |
|
isWS = (ch == ' ' || ch == '\t'); |
|
|
|
switch(state) { |
|
case SCE_INNO_DEFAULT: |
|
if (ch == ';' && isBOLWS) { |
|
// Start of a comment |
|
state = SCE_INNO_COMMENT; |
|
} else if (ch == '[' && isBOLWS) { |
|
// Start of a section name |
|
bufferCount = 0; |
|
state = SCE_INNO_SECTION; |
|
} else if (ch == '#' && isBOLWS) { |
|
// Start of a preprocessor directive |
|
state = SCE_INNO_PREPROC; |
|
} else if (ch == '{' && chNext == '#') { |
|
// Start of a preprocessor inline directive |
|
state = SCE_INNO_PREPROC_INLINE; |
|
} else if ((ch == '{' && (chNext == ' ' || chNext == '\t')) |
|
|| (ch == '(' && chNext == '*')) { |
|
// Start of a Pascal comment |
|
state = SCE_INNO_COMMENT_PASCAL; |
|
} else if (ch == '"') { |
|
// Start of a double-quote string |
|
state = SCE_INNO_STRING_DOUBLE; |
|
} else if (ch == '\'') { |
|
// Start of a single-quote string |
|
state = SCE_INNO_STRING_SINGLE; |
|
} else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) { |
|
// Start of an identifier |
|
bufferCount = 0; |
|
buffer[bufferCount++] = static_cast<char>(tolower(ch)); |
|
state = SCE_INNO_IDENTIFIER; |
|
} else { |
|
// Style it the default style |
|
styler.ColourTo(i,SCE_INNO_DEFAULT); |
|
} |
|
break; |
|
|
|
case SCE_INNO_COMMENT: |
|
if (isEOL) { |
|
state = SCE_INNO_DEFAULT; |
|
styler.ColourTo(i,SCE_INNO_COMMENT); |
|
} |
|
break; |
|
|
|
case SCE_INNO_IDENTIFIER: |
|
if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { |
|
buffer[bufferCount++] = static_cast<char>(tolower(ch)); |
|
} else { |
|
state = SCE_INNO_DEFAULT; |
|
buffer[bufferCount] = '\0'; |
|
|
|
// Check if the buffer contains a keyword |
|
if (standardKeywords.InList(buffer)) { |
|
styler.ColourTo(i-1,SCE_INNO_KEYWORD); |
|
} else if (parameterKeywords.InList(buffer)) { |
|
styler.ColourTo(i-1,SCE_INNO_PARAMETER); |
|
} else if (pascalKeywords.InList(buffer)) { |
|
styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL); |
|
} else if (userKeywords.InList(buffer)) { |
|
styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER); |
|
} else { |
|
styler.ColourTo(i-1,SCE_INNO_DEFAULT); |
|
} |
|
|
|
// Push back the faulty character |
|
chNext = styler[i--]; |
|
ch = chPrev; |
|
} |
|
break; |
|
|
|
case SCE_INNO_SECTION: |
|
if (ch == ']') { |
|
state = SCE_INNO_DEFAULT; |
|
buffer[bufferCount] = '\0'; |
|
|
|
// Check if the buffer contains a section name |
|
if (sectionKeywords.InList(buffer)) { |
|
styler.ColourTo(i,SCE_INNO_SECTION); |
|
} else { |
|
styler.ColourTo(i,SCE_INNO_DEFAULT); |
|
} |
|
} else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { |
|
buffer[bufferCount++] = static_cast<char>(tolower(ch)); |
|
} else { |
|
state = SCE_INNO_DEFAULT; |
|
styler.ColourTo(i,SCE_INNO_DEFAULT); |
|
} |
|
break; |
|
|
|
case SCE_INNO_PREPROC: |
|
if (isWS || isEOL) { |
|
if (isascii(chPrev) && isalpha(chPrev)) { |
|
state = SCE_INNO_DEFAULT; |
|
buffer[bufferCount] = '\0'; |
|
|
|
// Check if the buffer contains a preprocessor directive |
|
if (preprocessorKeywords.InList(buffer)) { |
|
styler.ColourTo(i-1,SCE_INNO_PREPROC); |
|
} else { |
|
styler.ColourTo(i-1,SCE_INNO_DEFAULT); |
|
} |
|
|
|
// Push back the faulty character |
|
chNext = styler[i--]; |
|
ch = chPrev; |
|
} |
|
} else if (isascii(ch) && isalpha(ch)) { |
|
if (chPrev == '#' || chPrev == ' ' || chPrev == '\t') |
|
bufferCount = 0; |
|
buffer[bufferCount++] = static_cast<char>(tolower(ch)); |
|
} |
|
break; |
|
|
|
case SCE_INNO_STRING_DOUBLE: |
|
if (ch == '"' || isEOL) { |
|
state = SCE_INNO_DEFAULT; |
|
styler.ColourTo(i,SCE_INNO_DEFAULT); |
|
} |
|
break; |
|
|
|
case SCE_INNO_STRING_SINGLE: |
|
if (ch == '\'' || isEOL) { |
|
state = SCE_INNO_DEFAULT; |
|
styler.ColourTo(i,SCE_INNO_DEFAULT); |
|
} |
|
break; |
|
|
|
case SCE_INNO_PREPROC_INLINE: |
|
if (ch == '}') { |
|
state = SCE_INNO_DEFAULT; |
|
styler.ColourTo(i,SCE_INNO_PREPROC_INLINE); |
|
} else if (isEOL) { |
|
state = SCE_INNO_DEFAULT; |
|
styler.ColourTo(i,SCE_INNO_DEFAULT); |
|
} |
|
break; |
|
|
|
case SCE_INNO_COMMENT_PASCAL: |
|
if (ch == '}' || (ch == ')' && chPrev == '*')) { |
|
state = SCE_INNO_DEFAULT; |
|
styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL); |
|
} else if (isEOL) { |
|
state = SCE_INNO_DEFAULT; |
|
styler.ColourTo(i,SCE_INNO_DEFAULT); |
|
} |
|
break; |
|
|
|
} |
|
} |
|
delete []buffer; |
|
} |
|
|
|
static const char * const innoWordListDesc[] = { |
|
"Sections", |
|
"Keywords", |
|
"Parameters", |
|
"Preprocessor directives", |
|
"Pascal keywords", |
|
"User defined keywords", |
|
0 |
|
}; |
|
|
|
static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { |
|
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; |
|
|
|
unsigned int endPos = startPos + length; |
|
int visibleChars = 0; |
|
int lineCurrent = styler.GetLine(startPos); |
|
|
|
char chNext = styler[startPos]; |
|
int styleNext = styler.StyleAt(startPos); |
|
bool headerPoint = false; |
|
int lev; |
|
|
|
for (unsigned int i = startPos; i < endPos; i++) { |
|
char ch = chNext; |
|
chNext = styler[i+1]; |
|
|
|
int style = styleNext; |
|
styleNext = styler.StyleAt(i + 1); |
|
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); |
|
|
|
if (style == SCE_INNO_SECTION) |
|
headerPoint = true; |
|
|
|
if (atEOL) { |
|
lev = SC_FOLDLEVELBASE; |
|
|
|
if (lineCurrent > 0) { |
|
int levelPrevious = styler.LevelAt(lineCurrent - 1); |
|
|
|
if (levelPrevious & SC_FOLDLEVELHEADERFLAG) |
|
lev = SC_FOLDLEVELBASE + 1; |
|
else |
|
lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; |
|
} |
|
|
|
if (headerPoint) |
|
lev = SC_FOLDLEVELBASE; |
|
|
|
if (visibleChars == 0 && foldCompact) |
|
lev |= SC_FOLDLEVELWHITEFLAG; |
|
|
|
if (headerPoint) |
|
lev |= SC_FOLDLEVELHEADERFLAG; |
|
|
|
if (lev != styler.LevelAt(lineCurrent)) |
|
styler.SetLevel(lineCurrent, lev); |
|
|
|
lineCurrent++; |
|
visibleChars = 0; |
|
headerPoint = false; |
|
} |
|
if (!isspacechar(ch)) |
|
visibleChars++; |
|
} |
|
|
|
if (lineCurrent > 0) { |
|
int levelPrevious = styler.LevelAt(lineCurrent - 1); |
|
|
|
if (levelPrevious & SC_FOLDLEVELHEADERFLAG) |
|
lev = SC_FOLDLEVELBASE + 1; |
|
else |
|
lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; |
|
} else { |
|
lev = SC_FOLDLEVELBASE; |
|
} |
|
int flagsNext = styler.LevelAt(lineCurrent); |
|
styler.SetLevel(lineCurrent, lev | flagsNext & ~SC_FOLDLEVELNUMBERMASK); |
|
} |
|
|
|
LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc);
|
|
|