diff options
author | kudah <kudahkukarek@gmail.com> | 2013-05-08 14:35:55 +0300 |
---|---|---|
committer | kudah <kudahkukarek@gmail.com> | 2013-05-08 14:35:55 +0300 |
commit | fc45916ab1b338983808e904d6316ffcc9d1be50 (patch) | |
tree | cde8e3f35e99adb5798922311137be28f570ed79 /lexers/LexHaskell.cxx | |
parent | cde5a9660f8313fa734c546d69f27b80020a0fb3 (diff) | |
download | scintilla-mirror-fc45916ab1b338983808e904d6316ffcc9d1be50.tar.gz |
Fixed a bug when --:> was highlighted as a constructor
Fixed a bug when X wasn't highlighted as a module in import {-# SOURCE #-} X
Fixed a bug when preprocessor directives could mess up context keywords
Diffstat (limited to 'lexers/LexHaskell.cxx')
-rw-r--r-- | lexers/LexHaskell.cxx | 137 |
1 files changed, 85 insertions, 52 deletions
diff --git a/lexers/LexHaskell.cxx b/lexers/LexHaskell.cxx index 8a9e5ba08..4e83916e0 100644 --- a/lexers/LexHaskell.cxx +++ b/lexers/LexHaskell.cxx @@ -45,15 +45,6 @@ using namespace Scintilla; #endif -#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 -#define HA_MODE_PRAGMA 7 - #define INDENT_OFFSET 1 static int u_iswalpha(int); @@ -141,9 +132,9 @@ static inline bool IsCommentStyle(int style) { return (style >= SCE_HA_COMMENTLINE && style <= SCE_HA_COMMENTBLOCK3); } -inline int StyleFromNestLevel(const unsigned int nestLevel) { - return SCE_HA_COMMENTBLOCK + (nestLevel % 3); - } +inline int CommentBlockStyleFromNestLevel(const unsigned int nestLevel) { + return SCE_HA_COMMENTBLOCK + (nestLevel % 3); +} struct OptionsHaskell { bool magicHash; @@ -234,6 +225,35 @@ class LexerHaskell : public ILexer { ,unlimitedHashes }; + enum KeywordMode { + HA_MODE_DEFAULT = 0 + ,HA_MODE_IMPORT1 = 1 // after "import", before "qualified" or "safe" or package name or module name. + ,HA_MODE_IMPORT2 = 2 // after module name, before "as" or "hiding". + ,HA_MODE_IMPORT3 = 3 // after "as", before "hiding" + ,HA_MODE_MODULE = 4 // after "module", before module name. + ,HA_MODE_FFI = 5 // after "foreign", before FFI keywords + ,HA_MODE_TYPE = 6 // after "type" or "data", before "family" + }; + + struct HaskellLineInfo { + unsigned int nestLevel; + bool pragma; + KeywordMode mode; + + HaskellLineInfo(int state) : + nestLevel (state >> 4) + , pragma (state & 0x8) + , mode (static_cast<KeywordMode>(state & 0x7)) + {} + + int ToLineState() { + return + (nestLevel << 4) + | pragma + | mode; + } + }; + inline void skipMagicHash(StyleContext &sc, const HashCount hashes) { if (options.magicHash && sc.ch == '#') { sc.Forward(); @@ -274,6 +294,7 @@ class LexerHaskell : public ILexer { return false; } } + public: LexerHaskell() : firstImportLine(-1) {} virtual ~LexerHaskell() {} @@ -363,16 +384,15 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty int lineCurrent = styler.GetLine(startPos); - int state = lineCurrent ? styler.GetLineState(lineCurrent-1) : 0; - int mode = state & 0x7; - int nestLevel = state >> 3; + HaskellLineInfo hs = HaskellLineInfo(lineCurrent ? styler.GetLineState(lineCurrent-1) : 0); int base = 10; bool dot = false; bool inDashes = false; + bool alreadyInTheMiddleOfOperator = false; - assert(!(IsCommentBlockStyle(initStyle) && nestLevel <= 0)); + assert(!(IsCommentBlockStyle(initStyle) && hs.nestLevel == 0)); while (sc.More()) { // Check for state end @@ -386,7 +406,7 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty // that it is not a line end and cease forwarding otherwise. if (sc.atLineEnd) { // Remember the line state for future incremental lexing - styler.SetLineState(lineCurrent, (nestLevel << 3) | mode); + styler.SetLineState(lineCurrent, hs.ToLineState()); lineCurrent++; } @@ -403,7 +423,7 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty sc.Forward(); // Remember the line state for future incremental lexing - styler.SetLineState(lineCurrent, (nestLevel << 3) | mode); + styler.SetLineState(lineCurrent, hs.ToLineState()); lineCurrent++; if (sc.ch == '\r' && sc.chNext == '\n') { @@ -418,12 +438,16 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty if (sc.state == SCE_HA_OPERATOR) { int style = SCE_HA_OPERATOR; - if (sc.ch == ':' && + if ( sc.ch == ':' + && !alreadyInTheMiddleOfOperator // except "::" - !(sc.chNext == ':' && !IsAnHaskellOperatorChar(sc.GetRelative(2)))) { + && !( sc.chNext == ':' + && !IsAnHaskellOperatorChar(sc.GetRelative(2)))) { style = SCE_HA_CAPITAL; } + alreadyInTheMiddleOfOperator = false; + while (IsAnHaskellOperatorChar(sc.ch)) sc.Forward(); @@ -521,39 +545,39 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty char s[100]; sc.GetCurrent(s, sizeof(s)); - int new_mode = HA_MODE_DEFAULT; + KeywordMode new_mode = HA_MODE_DEFAULT; if (keywords.InList(s)) { style = SCE_HA_KEYWORD; } else if (style == SCE_HA_CAPITAL) { - if (mode == HA_MODE_IMPORT1 || mode == HA_MODE_IMPORT3) { + if (hs.mode == HA_MODE_IMPORT1 || hs.mode == HA_MODE_IMPORT3) { style = SCE_HA_MODULE; new_mode = HA_MODE_IMPORT2; - } else if (mode == HA_MODE_MODULE) { + } else if (hs.mode == HA_MODE_MODULE) { style = SCE_HA_MODULE; } - } else if (mode == HA_MODE_IMPORT1 && + } else if (hs.mode == HA_MODE_IMPORT1 && strcmp(s,"qualified") == 0) { style = SCE_HA_KEYWORD; new_mode = HA_MODE_IMPORT1; } else if (options.highlightSafe && - mode == HA_MODE_IMPORT1 && + hs.mode == HA_MODE_IMPORT1 && strcmp(s,"safe") == 0) { style = SCE_HA_KEYWORD; new_mode = HA_MODE_IMPORT1; - } else if (mode == HA_MODE_IMPORT2) { + } else if (hs.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_TYPE) { + } else if (hs.mode == HA_MODE_TYPE) { if (strcmp(s,"family") == 0) style = SCE_HA_KEYWORD; } - if (mode == HA_MODE_FFI) { + if (hs.mode == HA_MODE_FFI) { if (ffi.InList(s)) { style = SCE_HA_KEYWORD; new_mode = HA_MODE_FFI; @@ -563,7 +587,7 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty sc.ChangeState(style); sc.SetState(SCE_HA_DEFAULT); - if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI) + if (strcmp(s,"import") == 0 && hs.mode != HA_MODE_FFI) new_mode = HA_MODE_IMPORT1; else if (strcmp(s,"module") == 0) new_mode = HA_MODE_MODULE; @@ -573,19 +597,21 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty || strcmp(s,"data") == 0) new_mode = HA_MODE_TYPE; - mode = new_mode; + hs.mode = new_mode; } // Comments // Oneliner else if (sc.state == SCE_HA_COMMENTLINE) { if (sc.atLineEnd) { - sc.SetState(mode == HA_MODE_PRAGMA ? SCE_HA_PRAGMA : SCE_HA_DEFAULT); + sc.SetState(hs.pragma ? SCE_HA_PRAGMA : SCE_HA_DEFAULT); sc.Forward(); // prevent double counting a line - } else if (inDashes && sc.ch != '-' && mode != HA_MODE_PRAGMA) { + } else if (inDashes && sc.ch != '-' && !hs.pragma) { inDashes = false; - if (IsAnHaskellOperatorChar(sc.ch)) + if (IsAnHaskellOperatorChar(sc.ch)) { + alreadyInTheMiddleOfOperator = true; sc.ChangeState(SCE_HA_OPERATOR); + } } else { sc.Forward(); } @@ -593,17 +619,18 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty // Nested else if (IsCommentBlockStyle(sc.state)) { if (sc.Match('{','-')) { - sc.SetState(StyleFromNestLevel(nestLevel)); + sc.SetState(CommentBlockStyleFromNestLevel(hs.nestLevel)); sc.Forward(2); - nestLevel++; + hs.nestLevel++; } else if (sc.Match('-','}')) { sc.Forward(2); - nestLevel--; - assert(nestLevel >= 0); + assert(hs.nestLevel > 0); + if (hs.nestLevel > 0) + hs.nestLevel--; sc.SetState( - nestLevel <= 0 - ? (mode == HA_MODE_PRAGMA ? SCE_HA_PRAGMA : SCE_HA_DEFAULT) - : StyleFromNestLevel(nestLevel - 1)); + hs.nestLevel == 0 + ? (hs.pragma ? SCE_HA_PRAGMA : SCE_HA_DEFAULT) + : CommentBlockStyleFromNestLevel(hs.nestLevel - 1)); } else { sc.Forward(); } @@ -611,7 +638,7 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty // Pragma else if (sc.state == SCE_HA_PRAGMA) { if (sc.Match("#-}")) { - mode = HA_MODE_DEFAULT; + hs.pragma = false; sc.Forward(3); sc.SetState(SCE_HA_DEFAULT); } else if (sc.Match('-','-')) { @@ -619,9 +646,9 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty sc.Forward(2); inDashes = false; } else if (sc.Match('{','-')) { - sc.SetState(StyleFromNestLevel(nestLevel)); + sc.SetState(CommentBlockStyleFromNestLevel(hs.nestLevel)); sc.Forward(2); - nestLevel = 1; + hs.nestLevel = 1; } else { sc.Forward(); } @@ -641,6 +668,8 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty else if (sc.state == SCE_HA_DEFAULT) { // Digit if (IsADigit(sc.ch)) { + hs.mode = HA_MODE_DEFAULT; + sc.SetState(SCE_HA_NUMBER); if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { // Match anything starting with "0x" or "0X", too @@ -657,11 +686,10 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty base = 10; dot = true; } - mode = HA_MODE_DEFAULT; } // Pragma else if (sc.Match("{-#")) { - mode = HA_MODE_PRAGMA; + hs.pragma = true; sc.SetState(SCE_HA_PRAGMA); sc.Forward(3); } @@ -673,17 +701,19 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty } // Comment block else if (sc.Match('{','-')) { - sc.SetState(StyleFromNestLevel(nestLevel)); + sc.SetState(CommentBlockStyleFromNestLevel(hs.nestLevel)); sc.Forward(2); - nestLevel = 1; + hs.nestLevel = 1; } // String else if (sc.ch == '\"') { sc.SetState(SCE_HA_STRING); sc.Forward(); } - // Character or quoted name + // Character or quoted name or promoted term else if (sc.ch == '\'') { + hs.mode = HA_MODE_DEFAULT; + sc.SetState(SCE_HA_CHARACTER); sc.Forward(); @@ -693,11 +723,12 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty sc.Forward(); sc.ChangeState(SCE_HA_IDENTIFIER); } else if (sc.chNext != '\'') { - // Quoted value or promoted constructor 'N + // Quoted name 'n or promoted constructor 'N if (IsAHaskellWordStart(sc.ch)) { sc.ChangeState(SCE_HA_IDENTIFIER); // Promoted constructor operator ':~> } else if (sc.ch == ':') { + alreadyInTheMiddleOfOperator = false; sc.ChangeState(SCE_HA_OPERATOR); // Promoted list or tuple '[T] } else if (sc.ch == '[' || sc.ch== '(') { @@ -709,6 +740,8 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty } // Operator starting with '?' or an implicit parameter else if (sc.ch == '?') { + hs.mode = HA_MODE_DEFAULT; + sc.SetState(SCE_HA_OPERATOR); if ( options.implicitParams @@ -720,13 +753,13 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty } // Preprocessor else if (sc.atLineStart && sc.ch == '#') { - mode = HA_MODE_DEFAULT; sc.SetState(SCE_HA_PREPROCESSOR); sc.Forward(); } // Operator else if (IsAnHaskellOperatorChar(sc.ch)) { - mode = HA_MODE_DEFAULT; + hs.mode = HA_MODE_DEFAULT; + sc.SetState(SCE_HA_OPERATOR); } // Braces and punctuation @@ -751,7 +784,7 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty sc.Forward(); } } - styler.SetLineState(lineCurrent, (nestLevel << 3) | mode); + styler.SetLineState(lineCurrent, hs.ToLineState()); sc.Complete(); } |