aboutsummaryrefslogtreecommitdiffhomepage
path: root/lexers/LexHaskell.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'lexers/LexHaskell.cxx')
-rw-r--r--lexers/LexHaskell.cxx252
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");
-