diff options
| author | nyamatongwe <devnull@localhost> | 2001-05-18 22:57:46 +0000 | 
|---|---|---|
| committer | nyamatongwe <devnull@localhost> | 2001-05-18 22:57:46 +0000 | 
| commit | 006684c8ed092bff53e4f249481824eacc3b51e0 (patch) | |
| tree | 9579654fc113eca13c613d3d67a7ab861461b231 /src/LexEiffel.cxx | |
| parent | 4170ad72152b2ac829afc2e29dd86c8dbecda17e (diff) | |
| download | scintilla-mirror-006684c8ed092bff53e4f249481824eacc3b51e0.tar.gz | |
Initial version.
Diffstat (limited to 'src/LexEiffel.cxx')
| -rw-r--r-- | src/LexEiffel.cxx | 286 | 
1 files changed, 286 insertions, 0 deletions
| diff --git a/src/LexEiffel.cxx b/src/LexEiffel.cxx new file mode 100644 index 000000000..27c63a7bc --- /dev/null +++ b/src/LexEiffel.cxx @@ -0,0 +1,286 @@ +// Scintilla source code edit control +/** @file LexEiffel.cxx + ** Lexer for Eiffel. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <fcntl.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +inline bool isEiffelOperator(char ch) { +	// '.' left out as it is used to make up numbers +	return ch == '*' || ch == '/' || ch == '\\' || ch == '-' || ch == '+' || +	        ch == '(' || ch == ')' || ch == '=' || +	        ch == '{' || ch == '}' || ch == '~' || +	        ch == '[' || ch == ']' || ch == ';' || +	        ch == '<' || ch == '>' || ch == ',' || +	        ch == '.' || ch == '^' || ch == '%' || ch == ':' ||  +		ch == '!' || ch == '@' || ch == '?'; +} + +static void getRangeLowered(unsigned int start, +		unsigned int end, +		Accessor &styler, +		char *s, +		unsigned int len) { +	unsigned int i = 0; +	while ((i < end - start + 1) && (i < len-1)) { +		s[i] = static_cast<char>(tolower(styler[start + i])); +		i++; +	} +	s[i] = '\0'; +} + +static void classifyWordEiffel(unsigned int start, +                            unsigned int end, +                            WordList	&keywords, +                            Accessor &styler) { +	char chAttr = SCE_EIFFEL_IDENTIFIER; +	if (isdigit(styler[start]) || (styler[start] == '.')) { +		chAttr = SCE_EIFFEL_NUMBER; +	} else { +		char s[100]; +		getRangeLowered(start, end, styler, s, sizeof(s)); +		if (keywords.InList(s)) { +			chAttr = SCE_EIFFEL_WORD; +		} +	} +	styler.ColourTo(end, chAttr); +} + +static void ColouriseEiffelDoc(unsigned int startPos, +                            int length, +                            int initStyle, +                            WordList *keywordlists[], +                            Accessor &styler) { + +	WordList &keywords = *keywordlists[0]; + +	styler.StartAt(startPos); + +	int state = initStyle; +	char chNext = styler[startPos]; +	unsigned int lengthDoc = startPos + length; + +	styler.StartSegment(startPos); +	for (unsigned int i = startPos; i <= lengthDoc; i++) { +		char ch = chNext; +		chNext = styler.SafeGetCharAt(i + 1); + +		if (styler.IsLeadByte(ch)) { +			chNext = styler.SafeGetCharAt(i + 2); +			i += 1; +			continue; +		} + +		if (state == SCE_EIFFEL_STRINGEOL) { +			if (ch != '\r' && ch != '\n') { +				styler.ColourTo(i - 1, state); +				state = SCE_EIFFEL_DEFAULT; +			} +		} + +		if (state == SCE_EIFFEL_DEFAULT) { +			if (ch == '-' && chNext == '-') { +				styler.ColourTo(i - 1, state); +				state = SCE_EIFFEL_COMMENTLINE; +			} else if (ch == '\"') { +				styler.ColourTo(i - 1, state); +				state = SCE_EIFFEL_STRING; +			} else if (ch == '\'') { +				styler.ColourTo(i - 1, state); +				state = SCE_EIFFEL_CHARACTER; +			} else if (isEiffelOperator(ch)) { +				styler.ColourTo(i - 1, state); +				styler.ColourTo(i, SCE_EIFFEL_OPERATOR); +			} else if (iswordstart(ch)) { +				styler.ColourTo(i - 1, state); +				state = SCE_EIFFEL_WORD; +			} +		} else { +			if (state == SCE_EIFFEL_WORD) { +				if (!iswordchar(ch)) { +					classifyWordEiffel(styler.GetStartSegment(), i - 1, keywords, styler); +					state = SCE_EIFFEL_DEFAULT; +				} +			} else if (state == SCE_EIFFEL_COMMENTLINE) { +				if (ch == '\r' || ch == '\n') { +					styler.ColourTo(i - 1, state); +					state = SCE_EIFFEL_DEFAULT; +				} +			} else if (state == SCE_EIFFEL_STRING) { +				if (ch == '%') { +					i++; +					ch = chNext; +					chNext = styler.SafeGetCharAt(i + 1); +				} else if (ch == '\"') { +					styler.ColourTo(i, state); +					state = SCE_EIFFEL_DEFAULT; +					i++; +					ch = chNext; +					chNext = styler.SafeGetCharAt(i + 1); +				} +			} else if (state == SCE_EIFFEL_CHARACTER) { +				if (ch == '\r' || ch == '\n') { +					styler.ColourTo(i - 1, state); +					state = SCE_EIFFEL_STRINGEOL; +				} else if (ch == '%') { +					i++; +					ch = chNext; +					chNext = styler.SafeGetCharAt(i + 1); +				} else if (ch == '\'') { +					styler.ColourTo(i, state); +					state = SCE_EIFFEL_DEFAULT; +					i++; +					ch = chNext; +					chNext = styler.SafeGetCharAt(i + 1); +				} +			} + +			if (state == SCE_EIFFEL_DEFAULT) { +				if (ch == '-' && chNext == '-') { +					state = SCE_EIFFEL_COMMENTLINE; +				} else if (ch == '\"') { +					state = SCE_EIFFEL_STRING; +				} else if (ch == '\'') { +					state = SCE_EIFFEL_CHARACTER; +				} else if (iswordstart(ch)) { +					state = SCE_EIFFEL_WORD; +				} else if (isEiffelOperator(ch)) { +					styler.ColourTo(i, SCE_EIFFEL_OPERATOR); +				} +			} +		} +	} +	styler.ColourTo(lengthDoc - 1, state); +} + +static bool IsEiffelComment(Accessor &styler, int pos, int len) { +	return len>1 && styler[pos]=='-' && styler[pos+1]=='-'; +} + +static void FoldEiffelDocIndent(unsigned int startPos, int length, int, +						   WordList *[], Accessor &styler) { +	int lengthDoc = startPos + length; + +	// Backtrack to previous line in case need to fix its fold status +	int lineCurrent = styler.GetLine(startPos); +	if (startPos > 0) { +		if (lineCurrent > 0) { +			lineCurrent--; +			startPos = styler.LineStart(lineCurrent); +		} +	} +	int spaceFlags = 0; +	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsEiffelComment); +	char chNext = styler[startPos]; +	for (int i = startPos; i < lengthDoc; i++) { +		char ch = chNext; +		chNext = styler.SafeGetCharAt(i + 1); + +		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) { +			int lev = indentCurrent; +			int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsEiffelComment); +			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { +				// Only non whitespace lines can be headers +				if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { +					lev |= SC_FOLDLEVELHEADERFLAG; +				} else if (indentNext & SC_FOLDLEVELWHITEFLAG) { +					// Line after is blank so check the next - maybe should continue further? +					int spaceFlags2 = 0; +					int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsEiffelComment); +					if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { +						lev |= SC_FOLDLEVELHEADERFLAG; +					} +				} +			} +			indentCurrent = indentNext; +			styler.SetLevel(lineCurrent, lev); +			lineCurrent++; +		} +	} +} + +static void FoldEiffelDocKeyWords(unsigned int startPos, int length, int /* initStyle */, WordList *[], +                       Accessor &styler) { +	unsigned int lengthDoc = startPos + length; +	int visibleChars = 0; +	int lineCurrent = styler.GetLine(startPos); +	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; +	int levelCurrent = levelPrev; +	char chNext = styler[startPos]; +	int stylePrev = 0; +	int styleNext = styler.StyleAt(startPos); +	// lastDeferred should be determined by looking back to last keyword in case +	// the "deferred" is on a line before "class" +	bool lastDeferred = false; +	for (unsigned int i = startPos; i < lengthDoc; i++) { +		char ch = chNext; +		chNext = styler.SafeGetCharAt(i + 1); +		int style = styleNext; +		styleNext = styler.StyleAt(i + 1); +		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); +		if ((stylePrev != SCE_EIFFEL_WORD) && (style == SCE_EIFFEL_WORD)) { +			char s[20]; +			unsigned int j = 0; +			while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { +				s[j] = styler[i + j]; +				j++; +			} +			s[j] = '\0'; + +			if ( +				(strcmp(s, "check") == 0) ||  +				(strcmp(s, "debug") == 0) ||  +				(strcmp(s, "deferred") == 0) ||  +				(strcmp(s, "do") == 0) ||  +				(strcmp(s, "from") == 0) || +				(strcmp(s, "if") == 0) || +				(strcmp(s, "inspect") == 0) ||  +				(strcmp(s, "once") == 0) +			) +				levelCurrent++; +			if (!lastDeferred && (strcmp(s, "class") == 0)) +				levelCurrent++; +			if (strcmp(s, "end") == 0)  +				levelCurrent--; +			lastDeferred = strcmp(s, "deferred") == 0; +		} + +		if (atEOL) { +			int lev = levelPrev; +			if (visibleChars == 0) +				lev |= SC_FOLDLEVELWHITEFLAG; +			if ((levelCurrent > levelPrev) && (visibleChars > 0)) +				lev |= SC_FOLDLEVELHEADERFLAG; +			if (lev != styler.LevelAt(lineCurrent)) { +				styler.SetLevel(lineCurrent, lev); +			} +			lineCurrent++; +			levelPrev = levelCurrent; +			visibleChars = 0; +		} +		if (!isspacechar(ch)) +			visibleChars++; +		stylePrev = style; +	} +	// Fill in the real level of the next line, keeping the current flags as they will be filled in later +	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; +	styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +LexerModule lmEiffel(SCLEX_EIFFEL, ColouriseEiffelDoc, "eiffel", FoldEiffelDocIndent); +LexerModule lmEiffelkw(SCLEX_EIFFELKW, ColouriseEiffelDoc, "eiffelkw", FoldEiffelDocKeyWords); | 
