diff options
author | nyamatongwe <unknown> | 2010-08-10 23:39:41 +1000 |
---|---|---|
committer | nyamatongwe <unknown> | 2010-08-10 23:39:41 +1000 |
commit | 13654c825d2a8e6caee0d5a9123922b69d89515e (patch) | |
tree | 2b5a8dfb90a3e3a4d3621d39f7156af6f63f7be4 /lexers/LexHaskell.cxx | |
parent | 3b6029becd9199f5556eedf88914e5ef702aedb2 (diff) | |
download | scintilla-mirror-13654c825d2a8e6caee0d5a9123922b69d89515e.tar.gz |
Feature Request #3039490 Improved syntactic highlighting for Haskell
'as' is a keyword but in all other contexts it is a normal identifier.
The highligthting was failing if the operators are not separated by spaces: 10+20
There was highlighting for data types, classes and instances but it didn't
work correctly. This was removed.
Diffstat (limited to 'lexers/LexHaskell.cxx')
-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"); - |