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); |