// Copyright (c) 1990-2007, Scientific Toolworks, Inc. // @file LexPLM.cxx // Author: Jason Haslam // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include #include #include #include #include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" #include "CharacterSet.h" #include "LexerModule.h" using namespace Lexilla; static void GetRange(Sci_PositionU start, Sci_PositionU end, Accessor &styler, char *s, Sci_PositionU len) { Sci_PositionU i = 0; while ((i < end - start + 1) && (i < len-1)) { s[i] = static_cast(tolower(styler[start + i])); i++; } s[i] = '\0'; } static void ColourisePlmDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], Accessor &styler) { Sci_PositionU endPos = startPos + length; int state = initStyle; styler.StartAt(startPos); styler.StartSegment(startPos); for (Sci_PositionU i = startPos; i < endPos; i++) { char ch = styler.SafeGetCharAt(i); char chNext = styler.SafeGetCharAt(i + 1); if (state == SCE_PLM_DEFAULT) { if (ch == '/' && chNext == '*') { styler.ColourTo(i - 1, state); state = SCE_PLM_COMMENT; } else if (ch == '\'') { styler.ColourTo(i - 1, state); state = SCE_PLM_STRING; } else if (isdigit(ch)) { styler.ColourTo(i - 1, state); state = SCE_PLM_NUMBER; } else if (isalpha(ch)) { styler.ColourTo(i - 1, state); state = SCE_PLM_IDENTIFIER; } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=' || ch == '<' || ch == '>' || ch == ':') { styler.ColourTo(i - 1, state); state = SCE_PLM_OPERATOR; } else if (ch == '$') { styler.ColourTo(i - 1, state); state = SCE_PLM_CONTROL; } } else if (state == SCE_PLM_COMMENT) { if (ch == '*' && chNext == '/') { i++; styler.ColourTo(i, state); state = SCE_PLM_DEFAULT; } } else if (state == SCE_PLM_STRING) { if (ch == '\'') { if (chNext == '\'') { i++; } else { styler.ColourTo(i, state); state = SCE_PLM_DEFAULT; } } } else if (state == SCE_PLM_NUMBER) { if (!isdigit(ch) && !isalpha(ch) && ch != '$') { i--; styler.ColourTo(i, state); state = SCE_PLM_DEFAULT; } } else if (state == SCE_PLM_IDENTIFIER) { if (!isdigit(ch) && !isalpha(ch) && ch != '$') { // Get the entire identifier. char word[1024]; Sci_Position segmentStart = styler.GetStartSegment(); GetRange(segmentStart, i - 1, styler, word, sizeof(word)); i--; if (keywordlists[0]->InList(word)) styler.ColourTo(i, SCE_PLM_KEYWORD); else styler.ColourTo(i, state); state = SCE_PLM_DEFAULT; } } else if (state == SCE_PLM_OPERATOR) { if (ch != '=' && ch != '>') { i--; styler.ColourTo(i, state); state = SCE_PLM_DEFAULT; } } else if (state == SCE_PLM_CONTROL) { if (ch == '\r' || ch == '\n') { styler.ColourTo(i - 1, state); state = SCE_PLM_DEFAULT; } } } styler.ColourTo(endPos - 1, state); } static void FoldPlmDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *[], Accessor &styler) { bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; Sci_PositionU endPos = startPos + length; int visibleChars = 0; Sci_Position lineCurrent = styler.GetLine(startPos); int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; int levelCurrent = levelPrev; char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); int style = initStyle; Sci_Position startKeyword = 0; for (Sci_PositionU i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); int stylePrev = style; style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); if (stylePrev != SCE_PLM_KEYWORD && style == SCE_PLM_KEYWORD) startKeyword = i; if (style == SCE_PLM_KEYWORD && styleNext != SCE_PLM_KEYWORD) { char word[1024]; GetRange(startKeyword, i, styler, word, sizeof(word)); if (strcmp(word, "procedure") == 0 || strcmp(word, "do") == 0) levelCurrent++; else if (strcmp(word, "end") == 0) levelCurrent--; } if (foldComment) { if (stylePrev != SCE_PLM_COMMENT && style == SCE_PLM_COMMENT) levelCurrent++; else if (stylePrev == SCE_PLM_COMMENT && style != SCE_PLM_COMMENT) levelCurrent--; } if (atEOL) { int lev = levelPrev; if (visibleChars == 0 && foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; if ((levelCurrent > levelPrev) && (visibleChars > 0)) lev |= SC_FOLDLEVELHEADERFLAG; if (lev != styler.LevelAt(lineCurrent)) { styler.SetLevel(lineCurrent, lev); } lineCurrent++; levelPrev = levelCurrent; visibleChars = 0; } if (!isspacechar(ch)) visibleChars++; } int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; styler.SetLevel(lineCurrent, levelPrev | flagsNext); } static const char *const plmWordListDesc[] = { "Keywords", 0 }; LexerModule lmPLM(SCLEX_PLM, ColourisePlmDoc, "PL/M", FoldPlmDoc, plmWordListDesc);