diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/LexSQL.cxx | 302 | 
1 files changed, 255 insertions, 47 deletions
| diff --git a/src/LexSQL.cxx b/src/LexSQL.cxx index bb8f128da..dc4c7a804 100644 --- a/src/LexSQL.cxx +++ b/src/LexSQL.cxx @@ -19,35 +19,92 @@  #include "Scintilla.h"  #include "SciLexer.h" + +static inline bool IsASpace(unsigned int ch) { +    return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); +} + +static bool MatchIgnoreCaseSubstring(const char *s, Accessor &styler, unsigned int startPos) { +	char ch = styler.SafeGetCharAt(startPos); +	bool isSubword = false; +	if (tolower(ch) != *s) +		return false; +	s++; +	if (*s == '~') +	{ +		isSubword = true; +		s++; +	} +	int n; +	for (n = 1; *s; n++) { +		if (*s == '~') +		{ +			isSubword = true; +			s++; +		} +		if (isSubword && IsASpace(styler.SafeGetCharAt(startPos + n))) +			return true; +		if (*s != tolower((styler.SafeGetCharAt(startPos + n)))) +			return false; +		s++; +	} +	return (IsASpace(styler.SafeGetCharAt(startPos + n))  +		|| styler.SafeGetCharAt(startPos + n) == ';'); +} + +static void getCurrent(unsigned int start, +		unsigned int end, +		Accessor &styler, +		char *s, +		unsigned int len) { +	for (unsigned int i = 0; i < end - start + 1 && i < len; i++) { +		s[i] = static_cast<char>(tolower(styler[start + i])); +		s[i + 1] = '\0'; +	} +} +  static void classifyWordSQL(unsigned int start, unsigned int end, WordList *keywordlists[], Accessor &styler) {  	char s[100];  	bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.'); -	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { +	for (unsigned int i = 0; i < end - start + 1 && i < 80; i++) {  		s[i] = static_cast<char>(tolower(styler[start + i]));  		s[i + 1] = '\0';  	} -	WordList &keywords1 = *keywordlists[0]; -	WordList &keywords2 = *keywordlists[1]; +	WordList &keywords1  = *keywordlists[0]; +	WordList &keywords2  = *keywordlists[1]; +//	WordList &kw_pldoc   = *keywordlists[2]; +	WordList &kw_sqlplus = *keywordlists[3]; +	WordList &kw_user1   = *keywordlists[4]; +	WordList &kw_user2   = *keywordlists[5]; +	WordList &kw_user3   = *keywordlists[6]; +	WordList &kw_user4   = *keywordlists[7]; -	char chAttr = SCE_C_IDENTIFIER; +	char chAttr = SCE_SQL_IDENTIFIER;  	if (wordIsNumber) -		chAttr = SCE_C_NUMBER; -	else { -		if (keywords1.InList(s)) { -			chAttr = SCE_C_WORD; -		} +		chAttr = SCE_SQL_NUMBER; +	else if (keywords1.InList(s)) +			chAttr = SCE_SQL_WORD; +	else if (keywords2.InList(s))  +			chAttr = SCE_SQL_WORD2; +	else if (kw_sqlplus.InListAbbreviated(s, '~')) +		chAttr = SCE_SQL_SQLPLUS; +	else if (kw_user1.InList(s)) +		chAttr = SCE_SQL_USER1; +	else if (kw_user2.InList(s)) +		chAttr = SCE_SQL_USER2; +	else if (kw_user3.InList(s)) +		chAttr = SCE_SQL_USER3; +	else if (kw_user4.InList(s)) +		chAttr = SCE_SQL_USER4; -		if (keywords2.InList(s)) { -			chAttr = SCE_C_WORD2; -		} -	}  	styler.ColourTo(end, chAttr);  }  static void ColouriseSQLDoc(unsigned int startPos, int length,                              int initStyle, WordList *keywordlists[], Accessor &styler) { +	WordList &kw_pldoc = *keywordlists[2];  	styler.StartAt(startPos);  	bool fold = styler.GetPropertyInt("fold") != 0; @@ -86,62 +143,108 @@ static void ColouriseSQLDoc(unsigned int startPos, int length,  			continue;  		} -		if (state == SCE_C_DEFAULT) { -			if (iswordstart(ch)) { +		if (state == SCE_SQL_DEFAULT) { +			if (MatchIgnoreCaseSubstring("rem~ark", styler, i)) { +				styler.ColourTo(i - 1, state); +				state = SCE_SQL_SQLPLUS_COMMENT; +			} else if (MatchIgnoreCaseSubstring("pro~mpt", styler, i)) {  				styler.ColourTo(i - 1, state); -				state = SCE_C_WORD; +				state = SCE_SQL_SQLPLUS_PROMPT; +			} else if (iswordstart(ch)) { +				styler.ColourTo(i - 1, state); +				state = SCE_SQL_WORD;  			} else if (ch == '/' && chNext == '*') {  				styler.ColourTo(i - 1, state); -				state = SCE_C_COMMENT; +				if ((styler.SafeGetCharAt(i + 2)) == '*') {	// Support of Doxygen doc. style +					state = SCE_SQL_COMMENTDOC; +				} else { +					state = SCE_SQL_COMMENT; +				}  			} else if (ch == '-' && chNext == '-') {  				styler.ColourTo(i - 1, state); -				state = SCE_C_COMMENTLINE; +				state = SCE_SQL_COMMENTLINE;  			} else if (ch == '#') {  				styler.ColourTo(i - 1, state); -				state = SCE_C_COMMENTLINEDOC; +				state = SCE_SQL_COMMENTLINEDOC;  			} else if (ch == '\'') {  				styler.ColourTo(i - 1, state); -				state = SCE_C_CHARACTER; +				state = SCE_SQL_CHARACTER;  			} else if (ch == '"') {  				styler.ColourTo(i - 1, state); -				state = SCE_C_STRING; +				state = SCE_SQL_STRING;  			} else if (isoperator(ch)) {  				styler.ColourTo(i - 1, state); -				styler.ColourTo(i, SCE_C_OPERATOR); +				styler.ColourTo(i, SCE_SQL_OPERATOR);  			} -		} else if (state == SCE_C_WORD) { +		} else if (state == SCE_SQL_WORD) {  			if (!iswordchar(ch)) {  				classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler); -				state = SCE_C_DEFAULT; +				state = SCE_SQL_DEFAULT;  				if (ch == '/' && chNext == '*') { -					state = SCE_C_COMMENT; +					if ((styler.SafeGetCharAt(i + 2)) == '*') {	// Support of Doxygen doc. style +						state = SCE_SQL_COMMENTDOC; +					} else { +						state = SCE_SQL_COMMENT; +					}  				} else if (ch == '-' && chNext == '-') { -					state = SCE_C_COMMENTLINE; +					state = SCE_SQL_COMMENTLINE;  				} else if (ch == '#') { -					state = SCE_C_COMMENTLINEDOC; +					state = SCE_SQL_COMMENTLINEDOC;  				} else if (ch == '\'') { -					state = SCE_C_CHARACTER; +					state = SCE_SQL_CHARACTER;  				} else if (ch == '"') { -					state = SCE_C_STRING; +					state = SCE_SQL_STRING;  				} else if (isoperator(ch)) { -					styler.ColourTo(i, SCE_C_OPERATOR); +					styler.ColourTo(i, SCE_SQL_OPERATOR);  				}  			}  		} else { -			if (state == SCE_C_COMMENT) { +			if (state == SCE_SQL_COMMENT) {  				if (ch == '/' && chPrev == '*') {  					if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_C_COMMENT) &&  					    (styler.GetStartSegment() == startPos)))) {  						styler.ColourTo(i, state); -						state = SCE_C_DEFAULT; +						state = SCE_SQL_DEFAULT; +					} +				} +			} else if (state == SCE_SQL_COMMENTDOC) { +				if (ch == '/' && chPrev == '*') { +					if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_SQL_COMMENTDOC) && +					    (styler.GetStartSegment() == startPos)))) { +						styler.ColourTo(i, state); +						state = SCE_SQL_DEFAULT; +					} +				} else if (ch == '@') { +					// Verify that we have the conditions to mark a comment-doc-keyword +					if ((IsASpace(chPrev) || chPrev == '*') && (!IsASpace(chNext))) { +						styler.ColourTo(i - 1, state); +						state = SCE_SQL_COMMENTDOCKEYWORD;  					}  				} -			} else if (state == SCE_C_COMMENTLINE || state == SCE_C_COMMENTLINEDOC) { +			} else if (state == SCE_SQL_COMMENTLINE || state == SCE_SQL_COMMENTLINEDOC || state == SCE_SQL_SQLPLUS_COMMENT) {  				if (ch == '\r' || ch == '\n') {  					styler.ColourTo(i - 1, state); -					state = SCE_C_DEFAULT; +					state = SCE_SQL_DEFAULT;  				} -			} else if (state == SCE_C_CHARACTER) { +			} else if (state == SCE_SQL_COMMENTDOCKEYWORD) { +				if (ch == '/' && chPrev == '*') { +					styler.ColourTo(i - 1, SCE_SQL_COMMENTDOCKEYWORDERROR); +					state = SCE_SQL_DEFAULT; +				} else if (!iswordchar(ch)) { +					char s[100]; +					getCurrent(styler.GetStartSegment(), i - 1, styler, s, 30); +					if (!kw_pldoc.InList(s + 1)) { +						state = SCE_SQL_COMMENTDOCKEYWORDERROR; +					} +					styler.ColourTo(i - 1, state); +					state = SCE_SQL_COMMENTDOC; +				} +			} else if (state == SCE_SQL_SQLPLUS_PROMPT) { +				if (ch == '\r' || ch == '\n') { +					styler.ColourTo(i - 1, state); +					state = SCE_SQL_DEFAULT; +				} +			} else if (state == SCE_SQL_CHARACTER) {  				if (sqlBackslashEscapes && ch == '\\') {  					i++;  					ch = chNext; @@ -151,40 +254,48 @@ static void ColouriseSQLDoc(unsigned int startPos, int length,  						i++;  					} else {  						styler.ColourTo(i, state); -						state = SCE_C_DEFAULT; +						state = SCE_SQL_DEFAULT;  						i++;  					}  					ch = chNext;  					chNext = styler.SafeGetCharAt(i + 1);  				} -			} else if (state == SCE_C_STRING) { +			} else if (state == SCE_SQL_STRING) {  				if (ch == '"') {  					if (chNext == '"') {  						i++;  					} else {  						styler.ColourTo(i, state); -						state = SCE_C_DEFAULT; +						state = SCE_SQL_DEFAULT;  						i++;  					}  					ch = chNext;  					chNext = styler.SafeGetCharAt(i + 1);  				}  			} -			if (state == SCE_C_DEFAULT) {    // One of the above succeeded +			if (state == SCE_SQL_DEFAULT) {    // One of the above succeeded  				if (ch == '/' && chNext == '*') { -					state = SCE_C_COMMENT; +					if ((styler.SafeGetCharAt(i + 2)) == '*') {	// Support of Doxygen doc. style +						state = SCE_SQL_COMMENTDOC; +					} else { +						state = SCE_SQL_COMMENT; +					}  				} else if (ch == '-' && chNext == '-') { -					state = SCE_C_COMMENTLINE; +					state = SCE_SQL_COMMENTLINE;  				} else if (ch == '#') { -					state = SCE_C_COMMENTLINEDOC; +					state = SCE_SQL_COMMENTLINEDOC; +				} else if (MatchIgnoreCaseSubstring("rem~ark", styler, i)) { +					state = SCE_SQL_SQLPLUS_COMMENT; +				} else if (MatchIgnoreCaseSubstring("pro~mpt", styler, i)) { +					state = SCE_SQL_SQLPLUS_PROMPT;  				} else if (ch == '\'') { -					state = SCE_C_CHARACTER; +					state = SCE_SQL_CHARACTER;  				} else if (ch == '"') { -					state = SCE_C_STRING; +					state = SCE_SQL_STRING;  				} else if (iswordstart(ch)) { -					state = SCE_C_WORD; +					state = SCE_SQL_WORD;  				} else if (isoperator(ch)) { -					styler.ColourTo(i, SCE_C_OPERATOR); +					styler.ColourTo(i, SCE_SQL_OPERATOR);  				}  			}  		} @@ -193,10 +304,107 @@ static void ColouriseSQLDoc(unsigned int startPos, int length,  	styler.ColourTo(lengthDoc - 1, state);  } +static bool IsStreamCommentStyle(int style) { +	return style == SCE_SQL_COMMENT || +	       style == SCE_SQL_COMMENTDOC || +	       style == SCE_SQL_COMMENTDOCKEYWORD || +	       style == SCE_SQL_COMMENTDOCKEYWORDERROR; +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". +static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, +                       WordList *[], Accessor &styler) { +	bool foldComment = styler.GetPropertyInt("fold.comment") != 0; +	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; +	unsigned int endPos = startPos + length; +	int visibleChars = 0; +	int lineCurrent = styler.GetLine(startPos); +	int levelCurrent = SC_FOLDLEVELBASE; +	if (lineCurrent > 0) +		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; +	int levelNext = levelCurrent; +	char chNext = styler[startPos]; +	int styleNext = styler.StyleAt(startPos); +	int style = initStyle; +	bool endFound = false; +	for (unsigned int i = startPos; i < endPos; i++) { +		char ch = chNext; +		chNext = styler.SafeGetCharAt(i + 1); +		int stylePrev = style; +		style = styleNext; +		styleNext = styler.StyleAt(i + 1); +		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); +		if (foldComment && IsStreamCommentStyle(style)) { +			if (!IsStreamCommentStyle(stylePrev)) { +				levelNext++; +			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) { +				// Comments don't end at end of line and the next character may be unstyled. +				levelNext--; +			} +		} +		if (foldComment && (style == SCE_SQL_COMMENTLINE)) { +			if ((ch == '-') && (chNext == '-')) { +				char chNext2 = styler.SafeGetCharAt(i + 2); +				if (chNext2 == '{') { +					levelNext++; +				} else if (chNext2 == '}') { +					levelNext--; +				} +			} +		} +		if (style == SCE_SQL_WORD) { +			if (MatchIgnoreCaseSubstring("elsif", styler, i)) { +				// ignore elsif +				i += 4; +			} else if (MatchIgnoreCaseSubstring("if", styler, i) +				|| MatchIgnoreCaseSubstring("loop", styler, i)){ +					if (endFound){ +						// ignore +						endFound = false; +					} else { +						levelNext++; +					} +			} else if (MatchIgnoreCaseSubstring("begin", styler, i)){ +				levelNext++; +			} else if (MatchIgnoreCaseSubstring("end", styler, i)) { +				endFound = true; +				levelNext--; +				if (levelNext < SC_FOLDLEVELBASE) +					levelNext = SC_FOLDLEVELBASE; +			} +		} +		if (atEOL) { +			int levelUse = levelCurrent; +			int lev = levelUse | levelNext << 16; +			if (visibleChars == 0 && foldCompact) +				lev |= SC_FOLDLEVELWHITEFLAG; +			if (levelUse < levelNext) +				lev |= SC_FOLDLEVELHEADERFLAG; +			if (lev != styler.LevelAt(lineCurrent)) { +				styler.SetLevel(lineCurrent, lev); +			} +			lineCurrent++; +			levelCurrent = levelNext; +			visibleChars = 0; +			endFound = false; +		} +		if (!isspacechar(ch)) +			visibleChars++; +	} +} +  static const char * const sqlWordListDesc[] = {  	"Keywords",  	"Database Objects", +	"PLDoc", +	"SQL*Plus", +	"User Keywords 1", +	"User Keywords 2", +	"User Keywords 3", +	"User Keywords 4",  	0  }; -LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", 0, sqlWordListDesc); +LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", FoldSQLDoc, sqlWordListDesc); | 
