notepad-plus-plus-legacy/scintilla/src/LexInno.cxx

295 lines
8.2 KiB
C++
Raw Normal View History

// 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"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
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 &sectionKeywords = *keywordLists[0];
WordList &standardKeywords = *keywordLists[1];
WordList &parameterKeywords = *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_STRING_DOUBLE);
}
break;
case SCE_INNO_STRING_SINGLE:
if (ch == '\'' || isEOL) {
state = SCE_INNO_DEFAULT;
styler.ColourTo(i,SCE_INNO_STRING_SINGLE);
}
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);