diff options
| author | Neil <nyamatongwe@gmail.com> | 2016-09-22 14:15:35 +1000 | 
|---|---|---|
| committer | Neil <nyamatongwe@gmail.com> | 2016-09-22 14:15:35 +1000 | 
| commit | e0900d15800a7ab023a107b8f4dd612f9164e3a8 (patch) | |
| tree | 27b24934dd2ce530f91ce5247c96ec4091786ba0 | |
| parent | 4dff76d6ab5c2f08c128ee157bdefda9b2894fa4 (diff) | |
| download | scintilla-mirror-e0900d15800a7ab023a107b8f4dd612f9164e3a8.tar.gz | |
Baan lexer changed significantly with more lexical states, keyword sets, and
support for abridged keywords.
| -rw-r--r-- | doc/ScintillaHistory.html | 4 | ||||
| -rw-r--r-- | include/SciLexer.h | 14 | ||||
| -rw-r--r-- | include/Scintilla.iface | 14 | ||||
| -rw-r--r-- | lexers/LexBaan.cxx | 602 | 
4 files changed, 578 insertions, 56 deletions
| diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 995fed33c..072de2c70 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -530,6 +530,10 @@  	matching keywords that have particular prefixes and/or suffixes.  	</li>  	<li> +	The Baan lexer was changed significantly with more lexical states, keyword sets, +	and support for abridged keywords. +	</li> +	<li>  	The Progress lexer "progress" has been replaced with a new lexer "abl"  	(Advanced Business Language)  	with a different set of lexical states and more functionality. diff --git a/include/SciLexer.h b/include/SciLexer.h index cb38fff99..0eb0b2956 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -599,6 +599,20 @@  #define SCE_BAAN_IDENTIFIER 8  #define SCE_BAAN_STRINGEOL 9  #define SCE_BAAN_WORD2 10 +#define SCE_BAAN_WORD3 11 +#define SCE_BAAN_WORD4 12 +#define SCE_BAAN_WORD5 13 +#define SCE_BAAN_WORD6 14 +#define SCE_BAAN_WORD7 15 +#define SCE_BAAN_WORD8 16 +#define SCE_BAAN_WORD9 17 +#define SCE_BAAN_TABLEDEF 18 +#define SCE_BAAN_TABLESQL 19 +#define SCE_BAAN_FUNCTION 20 +#define SCE_BAAN_DOMDEF 21 +#define SCE_BAAN_FUNCDEF 22 +#define SCE_BAAN_OBJECTDEF 23 +#define SCE_BAAN_DEFINEDEF 24  #define SCE_LISP_DEFAULT 0  #define SCE_LISP_COMMENT 1  #define SCE_LISP_NUMBER 2 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 072173bc8..27d1d7513 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -3366,6 +3366,20 @@ val SCE_BAAN_OPERATOR=7  val SCE_BAAN_IDENTIFIER=8  val SCE_BAAN_STRINGEOL=9  val SCE_BAAN_WORD2=10 +val SCE_BAAN_WORD3=11 +val SCE_BAAN_WORD4=12 +val SCE_BAAN_WORD5=13 +val SCE_BAAN_WORD6=14 +val SCE_BAAN_WORD7=15 +val SCE_BAAN_WORD8=16 +val SCE_BAAN_WORD9=17 +val SCE_BAAN_TABLEDEF=18 +val SCE_BAAN_TABLESQL=19 +val SCE_BAAN_FUNCTION=20 +val SCE_BAAN_DOMDEF=21 +val SCE_BAAN_FUNCDEF=22 +val SCE_BAAN_OBJECTDEF=23 +val SCE_BAAN_DEFINEDEF=24  # Lexical states for SCLEX_LISP  lex Lisp=SCLEX_LISP SCE_LISP_  val SCE_LISP_DEFAULT=0 diff --git a/lexers/LexBaan.cxx b/lexers/LexBaan.cxx index 8da2f3a3e..99141c2d0 100644 --- a/lexers/LexBaan.cxx +++ b/lexers/LexBaan.cxx @@ -1,134 +1,568 @@  // Scintilla source code edit control  /** @file LexBaan.cxx - ** Lexer for Baan. - ** Based heavily on LexCPP.cxx - **/ +** Lexer for Baan. +** Based heavily on LexCPP.cxx +**/  // Copyright 2001- by Vamsi Potluru <vamsi@who.net> & Praveen Ambekar <ambekarpraveen@yahoo.com>  // The License.txt file describes the conditions under which this software may be distributed. +// C standard library  #include <stdlib.h>  #include <string.h> -#include <stdio.h> -#include <stdarg.h> -#include <assert.h> -#include <ctype.h> +// C++ wrappers of C standard library +#include <cassert> + +// C++ standard library +#include <string> +#include <map> + +// Scintilla headers + +// Non-platform-specific headers + +// include  #include "ILexer.h"  #include "Scintilla.h"  #include "SciLexer.h" +// lexlib  #include "WordList.h"  #include "LexAccessor.h" -#include "Accessor.h"  #include "StyleContext.h"  #include "CharacterSet.h"  #include "LexerModule.h" +#include "OptionSet.h" -#ifdef SCI_NAMESPACE +# ifdef SCI_NAMESPACE  using namespace Scintilla; -#endif +# endif + +namespace { +	// Use an unnamed namespace to protect the functions and classes from name conflicts + +// Options used for LexerBaan +struct OptionsBaan { +	bool fold; +	bool foldComment; +	bool foldPreprocessor; +	bool foldCompact; +	bool baanFoldSyntaxBased; +	bool baanFoldKeywordsBased; +	bool baanStylingWithinPreprocessor; +	OptionsBaan() { +		fold = false; +		foldComment = false; +		foldPreprocessor = false; +		foldCompact = false; +		baanFoldSyntaxBased = false; +		baanFoldKeywordsBased = false; +		baanStylingWithinPreprocessor = false; +	} +}; + +const char *const baanWordLists[] = { +	"Baan & BaanSQL Reserved Keywords ", +	"Baan Standard functions", +	"Baan Functions Abridged", +	"Baan Main Sections ", +	"Baan Sub Sections", +	"PreDefined Variables", +	"PreDefined Attributes", +	"Enumerates", +	0, +}; + +struct OptionSetBaan : public OptionSet<OptionsBaan> { +	OptionSetBaan() { +		DefineProperty("fold", &OptionsBaan::fold); + +		DefineProperty("fold.comment", &OptionsBaan::foldComment); + +		DefineProperty("fold.preprocessor", &OptionsBaan::foldPreprocessor); + +		DefineProperty("fold.compact", &OptionsBaan::foldCompact); + +		DefineProperty("fold.baan.syntax.based", &OptionsBaan::baanFoldSyntaxBased, +			"Set this property to 0 to disable syntax based folding, which is folding based on '{' & '('."); +		 +		DefineProperty("fold.baan.keywords.based", &OptionsBaan::baanFoldKeywordsBased, +			"Set this property to 0 to disable keywords based folding, which is folding based on " +			" for, if, on (case), repeat, select, while and fold ends based on endfor, endif, endcase, until, endselect, endwhile respectively."); + +		DefineProperty("lexer.baan.styling.within.preprocessor", &OptionsBaan::baanStylingWithinPreprocessor, +			"For Baan code, determines whether all preprocessor code is styled in the " +			"preprocessor style (0, the default) or only from the initial # to the end " +			"of the command word(1)."); + +		DefineWordListSets(baanWordLists); +	} +};  static inline bool IsAWordChar(const int  ch) { -	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':'); +	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$');  }  static inline bool IsAWordStart(const int ch) {  	return (ch < 0x80) && (isalnum(ch) || ch == '_');  } -static void ColouriseBaanDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], -                            Accessor &styler) { +static inline bool IsAnOperator(int ch) { +	if (IsAlphaNumeric(ch)) +		return false; +	if (ch == '#' || ch == '^' || ch == '&' || ch == '*' || +		ch == '(' || ch == ')' || ch == '-' || ch == '+' || +		ch == '=' || ch == '|' || ch == '{' || ch == '}' || +		ch == '[' || ch == ']' || ch == ':' || ch == ';' || +		ch == '<' || ch == '>' || ch == ',' || ch == '/' || +		ch == '?' || ch == '!' || ch == '"' || ch == '~' || +		ch == '\\') +		return true; +	return false; +} + +static inline int IsAnyOtherIdentifier(char *s, int sLength) { + +	/*	IsAnyOtherIdentifier uses standard templates used in baan. +	The matching template is shown as comments just above the return condition. +	^ - refers to any character [a-z]. +	# - refers to any number [0-9]. +	Other characters shown are compared as is. +	Tried implementing with Regex... it was too complicated for me. +	Any other implementation suggestion welcome. +	*/ +	switch (sLength) { +	case 8: +		if (isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { +			//^^^^^###  +			return(SCE_BAAN_TABLEDEF); +		} +		break; +	case 9: +		if (s[0] == 't' && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && isalpha(s[5]) && IsADigit(s[6]) && IsADigit(s[7]) && IsADigit(s[8])) { +			//t^^^^^### +			return(SCE_BAAN_TABLEDEF); +		} +		else if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { +			//^^^^^###. +			return(SCE_BAAN_TABLESQL); +		} +		break; +	case 13: +		if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { +			//^^^^^###.**** +			return(SCE_BAAN_TABLESQL); +		} +		else if (s[0] == 'r' && s[1] == 'c' && s[2] == 'd' && s[3] == '.' && s[4] == 't' && isalpha(s[5]) && isalpha(s[6]) && isalpha(s[7]) && isalpha(s[8]) && isalpha(s[9]) && IsADigit(s[10]) && IsADigit(s[11]) && IsADigit(s[12])) { +			//rcd.t^^^^^### +			return(SCE_BAAN_TABLEDEF); +		} +		break; +	case 14: +	case 15: +		if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { +			if (s[13] != ':') { +				//^^^^^###.****** +				return(SCE_BAAN_TABLESQL); +			} +		} +		break; +	case 16: +	case 17: +		if (s[8] == '.' && s[9] == '_' && s[10] == 'i' && s[11] == 'n' && s[12] == 'd' && s[13] == 'e' && s[14] == 'x' && IsADigit(s[15]) && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { +			//^^^^^###._index## +			return(SCE_BAAN_TABLEDEF); +		} +		else if (s[8] == '.' && s[9] == '_' && s[10] == 'c' && s[11] == 'o' && s[12] == 'm' && s[13] == 'p' && s[14] == 'n' && s[15] == 'r' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { +			//^^^^^###._compnr +			return(SCE_BAAN_TABLEDEF); +		} +		break; +	default: +		break; +	} +	if (sLength > 14 && s[5] == '.' && s[6] == 'd' && s[7] == 'l' && s[8] == 'l' && s[13] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[9]) && IsADigit(s[10]) && IsADigit(s[11]) && IsADigit(s[12])) { +		//^^^^^.dll####. +		return(SCE_BAAN_FUNCTION); +	} +	else if (sLength > 15 && s[2] == 'i' && s[3] == 'n' && s[4] == 't' && s[5] == '.' && s[6] == 'd' && s[7] == 'l' && s[8] == 'l' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[9]) && isalpha(s[10]) && isalpha(s[11]) && isalpha(s[12]) && isalpha(s[13])) { +		//^^int.dll^^^^^. +		return(SCE_BAAN_FUNCTION); +	} +	else if (sLength > 11 && s[0] == 'i' && s[10] == '.' && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && isalpha(s[5]) && IsADigit(s[6]) && IsADigit(s[7]) && IsADigit(s[8]) && IsADigit(s[9])) { +		//i^^^^^####. +		return(SCE_BAAN_FUNCTION); +	} + +	return(SCE_BAAN_DEFAULT); +} + +static inline bool IsCommentLine(Sci_Position line, IDocument *pAccess) { +	LexAccessor styler(pAccess); +	Sci_Position pos = styler.LineStart(line); +	Sci_Position eol_pos = styler.LineStart(line + 1) - 1; +	for (Sci_Position i = pos; i < eol_pos; i++) { +		char ch = styler[i]; +		if (ch == '|') +			return true; +		else if (ch != ' ' && ch != '\t') +			return false; +	} +	return false; +} + +static inline bool IsPreProcLine(Sci_Position line, IDocument *pAccess) { +	LexAccessor styler(pAccess); +	Sci_Position pos = styler.LineStart(line); +	Sci_Position eol_pos = styler.LineStart(line + 1) - 1; +	for (Sci_Position i = pos; i < eol_pos; i++) { +		char ch = styler[i]; +		if (ch == '#') +			return true; +		else if (ch != ' ' && ch != '\t') +			return false; +	} +	return false; +} + +static inline int ToLowerCase(int c) { +	if (c >= 'A' && c <= 'Z') +		return 'a' + c - 'A'; +	return c; +} + +static inline bool wordInArray(const std::string& value, std::string *array, int length) +{ +	for (int i = 0; i < length; i++) +	{ +		if (value == array[i]) +		{ +			return true; +		} +	} + +	return false; +} + +class WordListAbridged : public WordList { +public: +	WordListAbridged() { +		kwAbridged = false; +		kwHasSection = false; +	}; +	~WordListAbridged() { +		Clear(); +	}; +	bool kwAbridged; +	bool kwHasSection; +	bool Contains(const char *s) { +		return kwAbridged ? InListAbridged(s, '~') : InList(s); +	}; +}; + +} + +class LexerBaan : public ILexer { +	WordListAbridged keywords; +	WordListAbridged keywords2; +	WordListAbridged keywords3; +	WordListAbridged keywords4; +	WordListAbridged keywords5; +	WordListAbridged keywords6; +	WordListAbridged keywords7; +	WordListAbridged keywords8; +	WordListAbridged keywords9; +	OptionsBaan options; +	OptionSetBaan osBaan; +public: +	LexerBaan() { +	} + +	virtual ~LexerBaan() { +	} + +	int SCI_METHOD Version() const { +		return lvOriginal; +	} + +	void SCI_METHOD Release() { +		delete this; +	} + +	const char * SCI_METHOD PropertyNames() { +		return osBaan.PropertyNames(); +	} + +	int SCI_METHOD PropertyType(const char * name) { +		return osBaan.PropertyType(name); +	} + +	const char * SCI_METHOD DescribeProperty(const char * name) { +		return osBaan.DescribeProperty(name); +	} + +	int SCI_METHOD PropertySet(const char *key, const char *val); + +	const char * SCI_METHOD DescribeWordListSets() { +		return osBaan.DescribeWordListSets(); +	} -	WordList &keywords = *keywordlists[0]; -	WordList &keywords2 = *keywordlists[1]; -	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; +	Sci_Position SCI_METHOD WordListSet(int n, const char *wl); + +	void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess); + +	void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess); + +	void * SCI_METHOD PrivateCall(int, void *) { +		return NULL; +	} + +	static ILexer * LexerFactoryBaan() { +		return new LexerBaan(); +	} +}; + +Sci_Position SCI_METHOD LexerBaan::PropertySet(const char *key, const char *val) { +	if (osBaan.PropertySet(&options, key, val)) { +		return 0; +	} +	return -1; +} + +Sci_Position SCI_METHOD LexerBaan::WordListSet(int n, const char *wl) { +	WordListAbridged *WordListAbridgedN = 0; +	switch (n) { +	case 0: +		WordListAbridgedN = &keywords; +		break; +	case 1: +		WordListAbridgedN = &keywords2; +		break; +	case 2: +		WordListAbridgedN = &keywords3; +		break; +	case 3: +		WordListAbridgedN = &keywords4; +		break; +	case 4: +		WordListAbridgedN = &keywords5; +		break; +	case 5: +		WordListAbridgedN = &keywords6; +		break; +	case 6: +		WordListAbridgedN = &keywords7; +		break; +	case 7: +		WordListAbridgedN = &keywords8; +		break; +	case 8: +		WordListAbridgedN = &keywords9; +		break; +	} +	Sci_Position firstModification = -1; +	if (WordListAbridgedN) { +		WordListAbridged wlNew; +		wlNew.Set(wl); +		if (*WordListAbridgedN != wlNew) { +			WordListAbridgedN->Set(wl); +			WordListAbridgedN->kwAbridged = strchr(wl, '~') != NULL; +			WordListAbridgedN->kwHasSection = strchr(wl, ':') != NULL; + +			firstModification = 0; +		} +	} +	return firstModification; +} + +void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {  	if (initStyle == SCE_BAAN_STRINGEOL)	// Does not leak onto next line  		initStyle = SCE_BAAN_DEFAULT;  	int visibleChars = 0; +	bool lineHasDomain = false; +	bool lineHasFunction = false; +	bool lineHasPreProc = false; +	bool lineIgnoreString = false; +	bool lineHasDefines = false; +	LexAccessor styler(pAccess);  	StyleContext sc(startPos, length, initStyle, styler);  	for (; sc.More(); sc.Forward()) { -		if (sc.state == SCE_BAAN_OPERATOR) { +		// Determine if the current state should terminate. +		switch (sc.state) { +		case SCE_BAAN_OPERATOR:  			sc.SetState(SCE_BAAN_DEFAULT); -		} else if (sc.state == SCE_BAAN_NUMBER) { +			break; +		case SCE_BAAN_NUMBER:  			if (!IsAWordChar(sc.ch)) {  				sc.SetState(SCE_BAAN_DEFAULT);  			} -		} else if (sc.state == SCE_BAAN_IDENTIFIER) { +			break; +		case SCE_BAAN_IDENTIFIER:  			if (!IsAWordChar(sc.ch)) { -				char s[100]; +				char s[1000]; +				char s1[1000];  				sc.GetCurrentLowered(s, sizeof(s)); -				if (keywords.InList(s)) { +				if (sc.ch == ':') { +					memcpy(s1, s, sizeof(s)); +					s1[sc.LengthCurrent()] = sc.ch; +					s1[sc.LengthCurrent() + 1] = '\0'; +				} +				if ((keywords.kwHasSection && (sc.ch == ':')) ? keywords.Contains(s1) : keywords.Contains(s)) {  					sc.ChangeState(SCE_BAAN_WORD); -				} else if (keywords2.InList(s)) { +					if (0 == strcmp(s, "domain")) { +						lineHasDomain = true; +					} +					else if (0 == strcmp(s, "function")) { +						lineHasFunction = true; +					} +				} +				else if ((keywords2.kwHasSection && (sc.ch == ':')) ? keywords2.Contains(s1) : keywords2.Contains(s)) {  					sc.ChangeState(SCE_BAAN_WORD2);  				} +				else if ((keywords3.kwHasSection && (sc.ch == ':')) ? keywords3.Contains(s1) : keywords3.Contains(s)) { +					sc.ChangeState(SCE_BAAN_WORD3); +				} +				else if ((keywords4.kwHasSection && (sc.ch == ':')) ? keywords4.Contains(s1) : keywords4.Contains(s)) { +					sc.ChangeState(SCE_BAAN_WORD4); +				} +				else if ((keywords5.kwHasSection && (sc.ch == ':')) ? keywords5.Contains(s1) : keywords5.Contains(s)) { +					sc.ChangeState(SCE_BAAN_WORD5); +				} +				else if ((keywords6.kwHasSection && (sc.ch == ':')) ? keywords6.Contains(s1) : keywords6.Contains(s)) { +					sc.ChangeState(SCE_BAAN_WORD6); +				} +				else if ((keywords7.kwHasSection && (sc.ch == ':')) ? keywords7.Contains(s1) : keywords7.Contains(s)) { +					sc.ChangeState(SCE_BAAN_WORD7); +				} +				else if ((keywords8.kwHasSection && (sc.ch == ':')) ? keywords8.Contains(s1) : keywords8.Contains(s)) { +					sc.ChangeState(SCE_BAAN_WORD8); +				} +				else if ((keywords9.kwHasSection && (sc.ch == ':')) ? keywords9.Contains(s1) : keywords9.Contains(s)) { +					sc.ChangeState(SCE_BAAN_WORD9); +				} +				else if (lineHasDomain) { +					sc.ChangeState(SCE_BAAN_DOMDEF); +					lineHasDomain = false; +				} +				else if (lineHasFunction) { +					sc.ChangeState(SCE_BAAN_FUNCDEF); +					lineHasFunction = false; +				} +				else if (lineHasPreProc) { +					sc.ChangeState(SCE_BAAN_OBJECTDEF); +					lineHasPreProc = false; +				} +				else if (lineHasDefines) { +					sc.ChangeState(SCE_BAAN_DEFINEDEF); +					lineHasDefines = false; +				} +				else { +					int state = IsAnyOtherIdentifier(s, sc.LengthCurrent()); +					if (state > 0) { +						sc.ChangeState(state); +					} +				}  				sc.SetState(SCE_BAAN_DEFAULT);  			} -		} else if (sc.state == SCE_BAAN_PREPROCESSOR) { -			if (stylingWithinPreprocessor) { -				if (IsASpace(sc.ch)) { +			break; +		case SCE_BAAN_PREPROCESSOR: +			if (options.baanStylingWithinPreprocessor) { +				if (IsASpace(sc.ch) || IsAnOperator(sc.ch)) {  					sc.SetState(SCE_BAAN_DEFAULT);  				} -			} else { +			} +			else {  				if (sc.atLineEnd && (sc.chNext != '^')) {  					sc.SetState(SCE_BAAN_DEFAULT);  				}  			} -		} else if (sc.state == SCE_BAAN_COMMENT) { +			break; +		case SCE_BAAN_COMMENT:  			if (sc.atLineEnd) {  				sc.SetState(SCE_BAAN_DEFAULT);  			} -		} else if (sc.state == SCE_BAAN_COMMENTDOC) { +			break; +		case SCE_BAAN_COMMENTDOC:  			if (sc.MatchIgnoreCase("enddllusage")) { -				for (unsigned int i = 0; i < 10; i++){ +				for (unsigned int i = 0; i < 10; i++) { +					sc.Forward(); +				} +				sc.ForwardSetState(SCE_BAAN_DEFAULT); +			} +			else if (sc.MatchIgnoreCase("endfunctionusage")) { +				for (unsigned int i = 0; i < 15; i++) {  					sc.Forward();  				}  				sc.ForwardSetState(SCE_BAAN_DEFAULT);  			} -		} else if (sc.state == SCE_BAAN_STRING) { +			break; +		case SCE_BAAN_STRING:  			if (sc.ch == '\"') {  				sc.ForwardSetState(SCE_BAAN_DEFAULT); -			} else if ((sc.atLineEnd) && (sc.chNext != '^')) { +			} +			else if ((sc.atLineEnd) && (sc.chNext != '^')) {  				sc.ChangeState(SCE_BAAN_STRINGEOL); -				sc.ForwardSetState(SCE_C_DEFAULT); +				sc.ForwardSetState(SCE_BAAN_DEFAULT);  				visibleChars = 0;  			} +			break;  		} +		// Determine if a new state should be entered.  		if (sc.state == SCE_BAAN_DEFAULT) {  			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {  				sc.SetState(SCE_BAAN_NUMBER); -			} else if (sc.MatchIgnoreCase("dllusage")){ -					sc.SetState(SCE_BAAN_COMMENTDOC); -					do { -						sc.Forward(); -					} while ((!sc.atLineEnd) && sc.More()); -			} else if (IsAWordStart(sc.ch)) { -					sc.SetState(SCE_BAAN_IDENTIFIER); -			} else if (sc.Match('|')){ -					sc.SetState(SCE_BAAN_COMMENT); -			} else if (sc.ch == '\"') { +			} +			else if (sc.MatchIgnoreCase("dllusage") || sc.MatchIgnoreCase("functionusage")) { +				sc.SetState(SCE_BAAN_COMMENTDOC); +				do { +					sc.Forward(); +				} while ((!sc.atLineEnd) && sc.More()); +			} +			else if (IsAWordStart(sc.ch)) { +				sc.SetState(SCE_BAAN_IDENTIFIER); +			} +			else if (sc.Match('|')) { +				sc.SetState(SCE_BAAN_COMMENT); +			} +			else if (sc.ch == '\"' && !(lineIgnoreString)) {  				sc.SetState(SCE_BAAN_STRING); -			} else if (sc.ch == '#' && visibleChars == 0) { +			} +			else if (sc.ch == '#' && visibleChars == 0) {  				// Preprocessor commands are alone on their line  				sc.SetState(SCE_BAAN_PREPROCESSOR);  				// Skip whitespace between # and preprocessor word  				do {  					sc.Forward();  				} while (IsASpace(sc.ch) && sc.More()); -			} else if (isoperator(static_cast<char>(sc.ch))) { +				if (sc.MatchIgnoreCase("pragma") || sc.MatchIgnoreCase("include")) { +					lineHasPreProc = true; +					lineIgnoreString = true; +				} +				else if (sc.MatchIgnoreCase("define") || sc.MatchIgnoreCase("undef")) { +					lineHasDefines = true; +					lineIgnoreString = false; +				} +			} +			else if (IsAnOperator(static_cast<char>(sc.ch))) {  				sc.SetState(SCE_BAAN_OPERATOR);  			}  		} +  		if (sc.atLineEnd) {  			// Reset states to begining of colourise so no surprises  			// if different sets of lines lexed.  			visibleChars = 0; +			lineHasDomain = false; +			lineHasFunction = false; +			lineHasPreProc = false; +			lineIgnoreString = false; +			lineHasDefines = false;  		}  		if (!IsASpace(sc.ch)) {  			visibleChars++; @@ -137,10 +571,16 @@ static void ColouriseBaanDoc(Sci_PositionU startPos, Sci_Position length, int in  	sc.Complete();  } -static void FoldBaanDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *[], -                            Accessor &styler) { -	bool foldComment = styler.GetPropertyInt("fold.comment") != 0; -	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; +void SCI_METHOD LexerBaan::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + +	char word[100]; +	bool notForLoop = false; +	int wordlen = 0; + +	std::string startTags[6] = { "for", "if", "on", "repeat", "select", "while" }; +	std::string endTags[6] = { "endcase", "endfor", "endif", "endselect", "endwhile", "until" }; + +	LexAccessor styler(pAccess);  	Sci_PositionU endPos = startPos + length;  	int visibleChars = 0;  	Sci_Position lineCurrent = styler.GetLine(startPos); @@ -149,6 +589,7 @@ static void FoldBaanDoc(Sci_PositionU startPos, Sci_Position length, int initSty  	char chNext = styler[startPos];  	int styleNext = styler.StyleAt(startPos);  	int style = initStyle; +  	for (Sci_PositionU i = startPos; i < endPos; i++) {  		char ch = chNext;  		chNext = styler.SafeGetCharAt(i + 1); @@ -156,25 +597,74 @@ static void FoldBaanDoc(Sci_PositionU startPos, Sci_Position length, int initSty  		style = styleNext;  		styleNext = styler.StyleAt(i + 1);  		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); -		if (foldComment && -			(style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) { +		if (options.foldComment && style == SCE_BAAN_COMMENTDOC) {  			if (style != stylePrev) {  				levelCurrent++; -			} else if ((style != styleNext) && !atEOL) { +			} +			else if ((style != styleNext) && !atEOL) {  				// Comments don't end at end of line and the next character may be unstyled.  				levelCurrent--;  			}  		} -		if (style == SCE_BAAN_OPERATOR) { -			if (ch == '{') { +		if (options.foldComment && atEOL && IsCommentLine(lineCurrent, pAccess)) { +			if (!IsCommentLine(lineCurrent - 1, pAccess) +				&& IsCommentLine(lineCurrent + 1, pAccess)) +				levelCurrent++; +			else if (IsCommentLine(lineCurrent - 1, pAccess) +				&& !IsCommentLine(lineCurrent + 1, pAccess)) +				levelCurrent--; +		} +		if (options.foldPreprocessor && atEOL && IsPreProcLine(lineCurrent, pAccess)) { +			if (!IsPreProcLine(lineCurrent - 1, pAccess) +				&& IsPreProcLine(lineCurrent + 1, pAccess)) +				levelCurrent++; +			else if (IsPreProcLine(lineCurrent - 1, pAccess) +				&& !IsPreProcLine(lineCurrent + 1, pAccess)) +				levelCurrent--; +		} +		if (options.baanFoldSyntaxBased && (style == SCE_BAAN_OPERATOR)) { +			if (ch == '{' || ch == '(') {  				levelCurrent++; -			} else if (ch == '}') { +			} +			else if (ch == '}' || ch == ')') {  				levelCurrent--;  			}  		} +		if (options.baanFoldKeywordsBased && style == SCE_BAAN_WORD) { +			word[wordlen++] = static_cast<char>(ToLowerCase(ch)); +			if (wordlen == 100) {                   // prevent overflow +				word[0] = '\0'; +				wordlen = 1; +			} +			if (styleNext != SCE_BAAN_WORD) { +				word[wordlen] = '\0'; +				wordlen = 0; +				if (strcmp(word, "for") == 0) { +					Sci_PositionU j = i + 1; +					while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { +						j++; +					} +					if (styler.Match(j, "update")) { +						// Means this is a "for update" used by Select which is already folded. +						notForLoop = true; +					} +				} +				else { +					notForLoop = false; +				} +				if (!notForLoop) { +					if (wordInArray(word, startTags, 6)) { +						levelCurrent++; +					} +					else if (wordInArray(word, endTags, 6)) { +						levelCurrent--; +					} +				} +			} +		}  		if (atEOL) {  			int lev = levelPrev; -			if (visibleChars == 0 && foldCompact) +			if (visibleChars == 0 && options.foldCompact)  				lev |= SC_FOLDLEVELWHITEFLAG;  			if ((levelCurrent > levelPrev) && (visibleChars > 0))  				lev |= SC_FOLDLEVELHEADERFLAG; @@ -193,4 +683,4 @@ static void FoldBaanDoc(Sci_PositionU startPos, Sci_Position length, int initSty  	styler.SetLevel(lineCurrent, levelPrev | flagsNext);  } -LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc); +LexerModule lmBaan(SCLEX_BAAN, LexerBaan::LexerFactoryBaan, "baan", baanWordLists); | 
