diff options
| -rw-r--r-- | lexers/LexHaskell.cxx | 252 | 
1 files changed, 171 insertions, 81 deletions
| diff --git a/lexers/LexHaskell.cxx b/lexers/LexHaskell.cxx index 2f34c66aa..37d85d0cf 100644 --- a/lexers/LexHaskell.cxx +++ b/lexers/LexHaskell.cxx @@ -7,6 +7,7 @@   *   *    Written by Tobias Engvall - tumm at dtek dot chalmers dot se   * + *    Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com   *   *    TODO:   *    * Implement a folder :) @@ -48,11 +49,13 @@ using namespace Scintilla;  #endif -// Max level of nested comments -#define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3 - - -enum kwType { kwOther, kwClass, kwData, kwInstance, kwImport, kwModule, kwType}; +#define HA_MODE_DEFAULT     0 +#define HA_MODE_IMPORT1     1 +#define HA_MODE_IMPORT2     2 +#define HA_MODE_IMPORT3     3 +#define HA_MODE_MODULE      4 +#define HA_MODE_FFI         5 +#define HA_MODE_TYPE        6  static inline bool IsNewline(const int ch) {     return (ch == '\n' || ch == '\r'); @@ -76,146 +79,234 @@ static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,                                 WordList *keywordlists[], Accessor &styler) {     WordList &keywords = *keywordlists[0]; - -   int kwLast = kwOther; +   WordList &ffi      = *keywordlists[1];     StyleContext sc(startPos, length, initStyle, styler); -   for (; sc.More(); sc.Forward()) { +   int lineCurrent = styler.GetLine(startPos); +   int state = lineCurrent ? styler.GetLineState(lineCurrent-1) +                           : HA_MODE_DEFAULT; +   int mode  = state & 0xF; +   int xmode = state >> 4; +   while (sc.More()) {        // Check for state end +           // Operator        if (sc.state == SCE_HA_OPERATOR) { -         kwLast = kwOther; -         sc.SetState(SCE_HA_DEFAULT); +         if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) { +            sc.Forward(); +         } else { +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.ChangeState(SCE_HA_DEFAULT); +         }        }           // String        else if (sc.state == SCE_HA_STRING) {           if (sc.ch == '\"') { -            sc.ForwardSetState(SCE_HA_DEFAULT); +			sc.Forward(); +            styler.ColourTo(sc.currentPos-1, sc.state); +            sc.ChangeState(SCE_HA_DEFAULT);           } else if (sc.ch == '\\') { -            sc.Forward(); -         } +            sc.Forward(2); +         } else if (sc.atLineEnd) { +			styler.ColourTo(sc.currentPos-1, sc.state); +			sc.ChangeState(SCE_HA_DEFAULT); +		 } else { +			sc.Forward(); +		 }        }           // Char        else if (sc.state == SCE_HA_CHARACTER) {           if (sc.ch == '\'') { -            sc.ForwardSetState(SCE_HA_DEFAULT); +			sc.Forward(); +            styler.ColourTo(sc.currentPos-1, sc.state); +            sc.ChangeState(SCE_HA_DEFAULT);           } else if (sc.ch == '\\') { -            sc.Forward(); -         } +            sc.Forward(2); +         } else if (sc.atLineEnd) { +			styler.ColourTo(sc.currentPos-1, sc.state); +			sc.ChangeState(SCE_HA_DEFAULT); +		 } else { +			sc.Forward(); +		 }        }           // Number        else if (sc.state == SCE_HA_NUMBER) { -         if (!IsADigit(sc.ch)) { -            sc.SetState(SCE_HA_DEFAULT); -         } -      } -         // Types, constructors, etc. -      else if (sc.state == SCE_HA_CAPITAL) { -         if (!IsAWordChar(sc.ch) || sc.ch == '.') { -            sc.SetState(SCE_HA_DEFAULT); +         if (IsADigit(sc.ch, xmode)) { +            sc.Forward(); +         } else if ((xmode == 10) && +                    (sc.ch == 'e' || sc.ch == 'E') && +                    (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) { +			sc.Forward(); +			if (sc.ch == '+' || sc.ch == '-') +				sc.Forward(); +         } else { +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.ChangeState(SCE_HA_DEFAULT);           }        }           // Identifier        else if (sc.state == SCE_HA_IDENTIFIER) { -         if (!IsAWordChar(sc.ch)) { +         if (IsAWordChar(sc.ch)) { +            sc.Forward(); +         } else {              char s[100];              sc.GetCurrent(s, sizeof(s)); -            int style = SCE_HA_IDENTIFIER; -            if ((kwLast == kwImport) || (strcmp(s,"qualified") == 0) || (strcmp(s,"as") == 0)) { -               style = SCE_HA_IMPORT; -            } else if (keywords.InList(s)) { +            int style = sc.state; +            int new_mode = 0; +            if (keywords.InList(s)) {                 style = SCE_HA_KEYWORD; -            } else if (kwLast == kwData) { -               style = SCE_HA_DATA; -            } else if (kwLast == kwClass) { -               style = SCE_HA_CLASS; -            } else if (kwLast == kwModule) { -               style = SCE_HA_MODULE;              } else if (isupper(s[0])) { -               style = SCE_HA_CAPITAL; -            } -            sc.ChangeState(style); -            sc.SetState(SCE_HA_DEFAULT); -            if (style == SCE_HA_KEYWORD) { -               if (0 == strcmp(s, "class")) -                  kwLast = kwClass; -               else if (0 == strcmp(s, "data")) -                  kwLast = kwData; -               else if (0 == strcmp(s, "instance")) -                  kwLast = kwInstance; -               else if (0 == strcmp(s, "import")) -                  kwLast = kwImport; -               else if (0 == strcmp(s, "module")) -                  kwLast = kwModule; +               if (mode >= HA_MODE_IMPORT1 && mode <= HA_MODE_IMPORT3) { +                  style    = SCE_HA_MODULE; +                  new_mode = HA_MODE_IMPORT2; +               } else if (mode == HA_MODE_MODULE) +                  style = SCE_HA_MODULE;                 else -                  kwLast = kwOther; -            } else if (style == SCE_HA_CLASS || style == SCE_HA_IMPORT || -                       style == SCE_HA_MODULE || style == SCE_HA_CAPITAL || -                       style == SCE_HA_DATA || style == SCE_HA_INSTANCE) { -               kwLast = kwOther; +                  style = SCE_HA_CAPITAL; +            } else if (mode == HA_MODE_IMPORT1 && +                       strcmp(s,"qualified") == 0) { +                style    = SCE_HA_KEYWORD; +                new_mode = HA_MODE_IMPORT1; +            } else if (mode == HA_MODE_IMPORT2) { +                if (strcmp(s,"as") == 0) { +                   style    = SCE_HA_KEYWORD; +                   new_mode = HA_MODE_IMPORT3; +               } else if (strcmp(s,"hiding") == 0) { +                   style     = SCE_HA_KEYWORD; +               } +            } else if (mode == HA_MODE_FFI) { +			   if (ffi.InList(s)) { +                  style = SCE_HA_KEYWORD; +                  new_mode = HA_MODE_FFI; +               }              } +            else if (mode == HA_MODE_TYPE) { +               if (strcmp(s,"family") == 0) +                  style    = SCE_HA_KEYWORD; +			} +            styler.ColourTo(sc.currentPos - 1, style); +            if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI) +               new_mode = HA_MODE_IMPORT1; +            else if (strcmp(s,"module") == 0) +               new_mode = HA_MODE_MODULE; +            else if (strcmp(s,"foreign") == 0) +               new_mode = HA_MODE_FFI; +            else if (strcmp(s,"type") == 0) +               new_mode = HA_MODE_TYPE; +            sc.ChangeState(SCE_HA_DEFAULT); +            mode = new_mode;           }        } +           // Comments              // Oneliner        else if (sc.state == SCE_HA_COMMENTLINE) { -         if (IsNewline(sc.ch)) -            sc.SetState(SCE_HA_DEFAULT); +         if (sc.atLineEnd) { +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.ChangeState(SCE_HA_DEFAULT); +         } else { +            sc.Forward(); +         }        }              // Nested -      else if (sc.state >= SCE_HA_COMMENTBLOCK) { +      else if (sc.state == SCE_HA_COMMENTBLOCK) {           if (sc.Match("{-")) { -            if (sc.state < SCE_HA_COMMENTMAX) -               sc.SetState(sc.state + 1); +            sc.Forward(2); +            xmode++;           }           else if (sc.Match("-}")) { +            sc.Forward(2); +            xmode--; +            if (xmode == 0) { +               styler.ColourTo(sc.currentPos - 1, sc.state); +               sc.ChangeState(SCE_HA_DEFAULT); +            } +         } else { +            if (sc.atLineEnd) { +				// Remember the line state for future incremental lexing +				styler.SetLineState(lineCurrent, (xmode << 4) | mode); +				lineCurrent++; +			}              sc.Forward(); -            if (sc.state == SCE_HA_COMMENTBLOCK) -               sc.ForwardSetState(SCE_HA_DEFAULT); -            else -               sc.ForwardSetState(sc.state - 1);           }        }        // New state?        if (sc.state == SCE_HA_DEFAULT) {           // Digit -         if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { -            sc.SetState(SCE_HA_NUMBER); -            if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { // Match anything starting with "0x" or "0X", too -               sc.Forward(1); -            } +         if (IsADigit(sc.ch) || +             (sc.ch == '.' && IsADigit(sc.chNext)) || +             (sc.ch == '-' && IsADigit(sc.chNext))) { +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.ChangeState(SCE_HA_NUMBER); +            if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { +				// Match anything starting with "0x" or "0X", too +				sc.Forward(2); +				xmode = 16; +            } else if (sc.ch == '0' && (sc.chNext == 'O' || sc.chNext == 'o')) { +				// Match anything starting with "0x" or "0X", too +				sc.Forward(2); +				xmode = 8; +            } else { +				sc.Forward(); +				xmode = 10; +			} +            mode = HA_MODE_DEFAULT;           }           // Comment line           else if (sc.Match("--")) { -            sc.SetState(SCE_HA_COMMENTLINE); +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.Forward(2); +            sc.ChangeState(SCE_HA_COMMENTLINE);           // Comment block           }           else if (sc.Match("{-")) { -            sc.SetState(SCE_HA_COMMENTBLOCK); +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.Forward(2); +            sc.ChangeState(SCE_HA_COMMENTBLOCK); +            xmode = 1;           }           // String           else if (sc.Match('\"')) { -            sc.SetState(SCE_HA_STRING); +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.Forward(); +            sc.ChangeState(SCE_HA_STRING);           }           // Character           else if (sc.Match('\'')) { -            sc.SetState(SCE_HA_CHARACTER); -         } -         // Stringstart -         else if (sc.Match('\"')) { -            sc.SetState(SCE_HA_STRING); +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.Forward(); +            sc.ChangeState(SCE_HA_CHARACTER);           } +         else if (sc.ch == '(' || sc.ch == ')' || +                  sc.ch == '{' || sc.ch == '}' || +                  sc.ch == '[' || sc.ch == ']') { +			styler.ColourTo(sc.currentPos - 1, sc.state); +			sc.Forward(); +			styler.ColourTo(sc.currentPos - 1, SCE_HA_OPERATOR); +			mode = HA_MODE_DEFAULT; +		 }           // Operator           else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) { -            sc.SetState(SCE_HA_OPERATOR); +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.Forward(); +            sc.ChangeState(SCE_HA_OPERATOR); +            mode = HA_MODE_DEFAULT;           }           // Keyword           else if (IsAWordStart(sc.ch)) { -               sc.SetState(SCE_HA_IDENTIFIER); +            styler.ColourTo(sc.currentPos - 1, sc.state); +            sc.Forward(); +            sc.ChangeState(SCE_HA_IDENTIFIER); +         } else { +            if (sc.atLineEnd) { +				// Remember the line state for future incremental lexing +				styler.SetLineState(lineCurrent, (xmode << 4) | mode); +				lineCurrent++; +			} +            sc.Forward();           } -        }     }     sc.Complete(); @@ -275,4 +366,3 @@ void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)  #endif  LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell"); - | 
