diff options
author | kudah <kudahkukarek@gmail.com> | 2013-04-19 14:21:28 +0300 |
---|---|---|
committer | kudah <kudahkukarek@gmail.com> | 2013-04-19 14:21:28 +0300 |
commit | 2ed02c61c7309001e6ccee6592adb895cf47b8f5 (patch) | |
tree | 5cede1b88e6048b5831b4b584d891ddc1f30c3f4 | |
parent | 6e6f60b74fd36e674a5f1aea465e9f11ec8e0fa9 (diff) | |
download | scintilla-mirror-2ed02c61c7309001e6ccee6592adb895cf47b8f5.tar.gz |
* Use SCE_HA_COMMENTBLOCK2, SCE_HA_COMMENTBLOCK3
* Implicit params
* «Nice Character-lexing»
-rw-r--r-- | include/SciLexer.h | 1 | ||||
-rw-r--r-- | include/Scintilla.iface | 1 | ||||
-rw-r--r-- | lexers/LexHaskell.cxx | 95 |
3 files changed, 70 insertions, 27 deletions
diff --git a/include/SciLexer.h b/include/SciLexer.h index 81775d606..2bf4239d8 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -1022,6 +1022,7 @@ #define SCE_HA_COMMENTBLOCK3 16 #define SCE_HA_PRAGMA 17 #define SCE_HA_PREPROCESSOR 18 +#define SCE_HA_STRINGEOL 19 #define SCE_T3_DEFAULT 0 #define SCE_T3_X_DEFAULT 1 #define SCE_T3_PREPROCESSOR 2 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 449ef3110..b2e8608ff 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -3584,6 +3584,7 @@ val SCE_HA_COMMENTBLOCK2=15 val SCE_HA_COMMENTBLOCK3=16 val SCE_HA_PRAGMA=17 val SCE_HA_PREPROCESSOR=18 +val SCE_HA_STRINGEOL=19 # Lexical states of SCLEX_TADS3 lex TADS3=SCLEX_TADS3 SCE_T3_ val SCE_T3_DEFAULT=0 diff --git a/lexers/LexHaskell.cxx b/lexers/LexHaskell.cxx index 2d16e6934..8d7b6468d 100644 --- a/lexers/LexHaskell.cxx +++ b/lexers/LexHaskell.cxx @@ -10,13 +10,12 @@ * * Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com * - * Improvements by kudah <kudahkukarek@gmail.com> + * Improved by kudah <kudahkukarek@gmail.com> * * TODO: - * * Fold group declarations, comments, pragmas, #ifdefs, explicit layout, lists, tuples, quasi-quotes, splces, etc, etc, etc. - * * Nice Character-lexing (stuff inside '\''), LexPython has - * this. - * + * * A proper lexical folder to fold group declarations, comments, pragmas, + * #ifdefs, explicit layout, lists, tuples, quasi-quotes, splces, etc, etc, + * etc. * *****************************************************************/ #include <stdlib.h> @@ -56,8 +55,17 @@ using namespace Scintilla; #define INDENT_OFFSET 1 +static inline bool IsAlpha(const int ch) { + return (ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z'); +} + +static inline bool IsAnIdentifierStart(const int ch) { + return (IsLowerCase(ch) || ch == '_'); +} + static inline bool IsAWordStart(const int ch) { - return (IsLowerCase(ch) || IsUpperCase(ch) || ch == '_'); + return (IsAlpha(ch) || ch == '_'); } static inline bool IsAWordChar(const int ch) { @@ -83,9 +91,14 @@ static inline bool IsCommentStyle(int style) { return (style >= SCE_HA_COMMENTLINE && style <= SCE_HA_COMMENTBLOCK3); } +inline int StyleFromNestLevel(const int nestLevel) { + return SCE_HA_COMMENTBLOCK + (nestLevel % 3); + } + struct OptionsHaskell { bool magicHash; bool allowQuotes; + bool implicitParams; bool highlightSafe; bool stylingWithinPreprocessor; bool fold; @@ -94,9 +107,10 @@ struct OptionsHaskell { bool foldImports; bool foldIndentedImports; OptionsHaskell() { - magicHash = true; - allowQuotes = true; - highlightSafe = true; + magicHash = true; // Widespread use, enabled by default. + allowQuotes = true; // Widespread use, enabled by default. + implicitParams = false; // Fell out of favor, seldom used, disabled. + highlightSafe = true; // Moderately used, doesn't hurt to enable. stylingWithinPreprocessor = false; fold = false; foldComment = false; @@ -115,17 +129,23 @@ static const char * const haskellWordListDesc[] = { struct OptionSetHaskell : public OptionSet<OptionsHaskell> { OptionSetHaskell() { DefineProperty("lexer.haskell.allow.hash", &OptionsHaskell::magicHash, - "Set to 1 to allow the '#' character at the end of identifiers and " - "literals with the haskell lexer (GHC -XMagicHash extension)"); + "Set to 0 to disallow the '#' character at the end of identifiers and " + "literals with the haskell lexer " + "(GHC -XMagicHash extension)"); DefineProperty("lexer.haskell.allow.quotes", &OptionsHaskell::allowQuotes, - "Set to 1 to enable highlighting of Template Haskell name quotations " + "Set to 0 to disable highlighting of Template Haskell name quotations " "and promoted constructors " "(GHC -XTemplateHaskell and -XDataKinds extensions)"); + DefineProperty("lexer.haskell.allow.questionmark", &OptionsHaskell::implicitParams, + "Set to 1 to allow the '?' character at the start of identifiers " + "with the haskell lexer " + "(GHC & Hugs -XImplicitParams extension)"); + DefineProperty("lexer.haskell.import.safe", &OptionsHaskell::highlightSafe, - "Set to 1 to allow keyword \"safe\" in imports " - "(GHC SafeHaskell extensions)"); + "Set to 0 to disallow \"safe\" keyword in imports " + "(GHC -XSafe, -XTrustworthy, -XUnsafe extensions)"); DefineProperty("styling.within.preprocessor", &OptionsHaskell::stylingWithinPreprocessor, "For Haskell code, determines whether all preprocessor code is styled in the " @@ -271,6 +291,10 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty ,IDocument *pAccess) { LexAccessor styler(pAccess); + // Do not leak onto next line + if (initStyle == SCE_HA_STRINGEOL) + initStyle = SCE_HA_DEFAULT; + StyleContext sc(startPos, length, initStyle, styler); int lineCurrent = styler.GetLine(startPos); @@ -295,6 +319,11 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty lineCurrent++; } + if (sc.atLineStart && (sc.state == SCE_HA_STRING || sc.state == SCE_HA_CHARACTER)) { + // Prevent SCE_HA_STRINGEOL from leaking back to previous line + sc.SetState(sc.state); + } + // Handle line continuation generically. if (sc.ch == '\\' && ( sc.state == SCE_HA_STRING @@ -338,8 +367,8 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty } else if (sc.ch == '\\') { sc.Forward(2); } else if (sc.atLineEnd) { - sc.SetState(SCE_HA_DEFAULT); - sc.Forward(); // prevent double counting a line + sc.ChangeState(SCE_HA_STRINGEOL); + sc.ForwardSetState(SCE_HA_DEFAULT); } else { sc.Forward(); } @@ -353,8 +382,8 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty } else if (sc.ch == '\\') { sc.Forward(2); } else if (sc.atLineEnd) { - sc.SetState(SCE_HA_DEFAULT); - sc.Forward(); // prevent double counting a line + sc.ChangeState(SCE_HA_STRINGEOL); + sc.ForwardSetState(SCE_HA_DEFAULT); } else { sc.Forward(); } @@ -415,7 +444,7 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty if (keywords.InList(s)) { style = SCE_HA_KEYWORD; - } else if (isupper(s[0])) { + } else if (style == SCE_HA_CAPITAL) { if (mode == HA_MODE_IMPORT1 || mode == HA_MODE_IMPORT3) { style = SCE_HA_MODULE; new_mode = HA_MODE_IMPORT2; @@ -481,17 +510,18 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty } } // Nested - else if (sc.state == SCE_HA_COMMENTBLOCK) { + else if (IsCommentBlockStyle(sc.state)) { if (sc.Match('{','-')) { + sc.SetState(StyleFromNestLevel(nestLevel)); sc.Forward(2); nestLevel++; - } - else if (sc.Match('-','}')) { + } else if (sc.Match('-','}')) { sc.Forward(2); nestLevel--; - if (nestLevel == 0) { - sc.SetState(SCE_HA_DEFAULT); - } + sc.SetState( + nestLevel == 0 + ? SCE_HA_DEFAULT + : StyleFromNestLevel(nestLevel - 1)); } else { sc.Forward(); } @@ -508,7 +538,7 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty } // Preprocessor else if (sc.state == SCE_HA_PREPROCESSOR) { - if (options.stylingWithinPreprocessor && !IsAWordStart(sc.ch)) { + if (options.stylingWithinPreprocessor && !IsAlpha(sc.ch)) { sc.SetState(SCE_HA_DEFAULT); } else if (sc.atLineEnd) { sc.SetState(SCE_HA_DEFAULT); @@ -549,7 +579,7 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty } // Comment block else if (sc.Match('{','-')) { - sc.SetState(SCE_HA_COMMENTBLOCK); + sc.SetState(StyleFromNestLevel(nestLevel)); sc.Forward(2); nestLevel++; } @@ -587,6 +617,17 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty sc.ChangeState(style); } + // Operator starting with '?' or an implicit parameter + else if (sc.ch == '?') { + int style = SCE_HA_OPERATOR; + + if (options.implicitParams && IsAnIdentifierStart(sc.chNext)) { + sc.Forward(); + style = SCE_HA_IDENTIFIER; + } + + sc.ChangeState(style); + } // Preprocessor else if (sc.atLineStart && sc.ch == '#') { mode = HA_MODE_DEFAULT; |