diff options
author | nyamatongwe <unknown> | 2008-10-22 07:25:28 +0000 |
---|---|---|
committer | nyamatongwe <unknown> | 2008-10-22 07:25:28 +0000 |
commit | dd79dcebb055358345a97c1c4482a8a5143b48b5 (patch) | |
tree | 400aecaa85e0260c58f8c3465cf1a3994155abe4 /src | |
parent | 76402e71b6bb122be4a5f57495f1eaefa822c7e8 (diff) | |
download | scintilla-mirror-dd79dcebb055358345a97c1c4482a8a5143b48b5.tar.gz |
Addition of lexers for TAL, TACL, and COBOL from ozlooper. FR #2127406
Diffstat (limited to 'src')
-rw-r--r-- | src/KeyWords.cxx | 3 | ||||
-rw-r--r-- | src/LexCOBOL.cxx | 364 | ||||
-rw-r--r-- | src/LexTACL.cxx | 393 | ||||
-rw-r--r-- | src/LexTAL.cxx | 392 |
4 files changed, 1152 insertions, 0 deletions
diff --git a/src/KeyWords.cxx b/src/KeyWords.cxx index b38e515a0..4907571cf 100644 --- a/src/KeyWords.cxx +++ b/src/KeyWords.cxx @@ -159,6 +159,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmClw); LINK_LEXER(lmClwNoCase); LINK_LEXER(lmCmake); + LINK_LEXER(lmCOBOL); LINK_LEXER(lmConf); LINK_LEXER(lmCPP); LINK_LEXER(lmCPPNoCase); @@ -221,7 +222,9 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmSpecman); LINK_LEXER(lmSpice); LINK_LEXER(lmSQL); + LINK_LEXER(lmTACL); LINK_LEXER(lmTADS3); + LINK_LEXER(lmTAL); LINK_LEXER(lmTCL); LINK_LEXER(lmTeX); LINK_LEXER(lmVB); diff --git a/src/LexCOBOL.cxx b/src/LexCOBOL.cxx new file mode 100644 index 000000000..4ad8e9fc1 --- /dev/null +++ b/src/LexCOBOL.cxx @@ -0,0 +1,364 @@ +// Scintilla source code edit control +/** @file LexCOBOL.cxx + ** Lexer for COBOL + ** Based on LexPascal.cxx + ** Written by Laurent le Tynevez + ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002 + ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments) + ** Updated by Rod Falck, Aug 2006 Converted to COBOL + **/ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#define IN_DIVISION 0x01 +#define IN_DECLARATIVES 0x02 +#define IN_SECTION 0x04 +#define IN_PARAGRAPH 0x08 +#define IN_FLAGS 0xF +#define NOT_HEADER 0x10 + +inline bool isCOBOLoperator(char ch) + { + return isoperator(ch); + } + +inline bool isCOBOLwordchar(char ch) + { + return isascii(ch) && (isalnum(ch) || ch == '-'); + + } + +inline bool isCOBOLwordstart(char ch) + { + return isascii(ch) && isalnum(ch); + } + +static int CountBits(int nBits) + { + int count = 0; + for (int i = 0; i < 32; ++i) + { + count += nBits & 1; + nBits >>= 1; + } + return count; + } + +static void getRange(unsigned int start, + unsigned int end, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast<char>(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr) { + styler.ColourTo(end, attr); +} + + +static int classifyWordCOBOL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, int nContainment, bool *bAarea) { + int ret = 0; + + WordList& a_keywords = *keywordlists[0]; + WordList& b_keywords = *keywordlists[1]; + WordList& c_keywords = *keywordlists[2]; + + char s[100]; + getRange(start, end, styler, s, sizeof(s)); + + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.')) { + chAttr = SCE_C_NUMBER; + char *p = s + 1; + while (*p) { + if (!isdigit(*p) && isCOBOLwordchar(*p)) { + chAttr = SCE_C_IDENTIFIER; + break; + } + ++p; + } + } + else { + if (a_keywords.InList(s)) { + chAttr = SCE_C_WORD; + } + else if (b_keywords.InList(s)) { + chAttr = SCE_C_WORD2; + } + else if (c_keywords.InList(s)) { + chAttr = SCE_C_UUID; + } + } + if (*bAarea) { + if (strcmp(s, "division") == 0) { + ret = IN_DIVISION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "declaratives") == 0) { + ret = IN_DIVISION | IN_DECLARATIVES; + if (nContainment & IN_DECLARATIVES) + ret |= NOT_HEADER | IN_SECTION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "section") == 0) { + ret = (nContainment &~ IN_PARAGRAPH) | IN_SECTION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "end") == 0 && (nContainment & IN_DECLARATIVES)) { + ret = IN_DIVISION | IN_DECLARATIVES | IN_SECTION | NOT_HEADER; + } else { + ret = nContainment | IN_PARAGRAPH; + } + } + ColourTo(styler, end, chAttr); + return ret; +} + +static void ColouriseCOBOLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos); + + int state = initStyle; + if (state == SCE_C_CHARACTER) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + + int nContainment; + + int currentLine = styler.GetLine(startPos); + if (currentLine > 0) { + styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); + nContainment = styler.GetLineState(currentLine); + nContainment &= ~NOT_HEADER; + } else { + styler.SetLineState(currentLine, 0); + nContainment = 0; + } + + styler.StartSegment(startPos); + bool bNewLine = true; + bool bAarea = !isspacechar(chNext); + int column = 0; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + + chNext = styler.SafeGetCharAt(i + 1); + + ++column; + + if (bNewLine) { + column = 0; + } + if (column <= 1 && !bAarea) { + bAarea = !isspacechar(ch); + } + bool bSetNewLine = false; + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + if (state == SCE_C_CHARACTER) { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + styler.SetLineState(currentLine, nContainment); + currentLine++; + bSetNewLine = true; + if (nContainment & NOT_HEADER) + nContainment &= ~(NOT_HEADER | IN_DECLARATIVES | IN_SECTION); + } + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (isCOBOLwordstart(ch) || (ch == '$' && isalpha(chNext))) { + ColourTo(styler, i-1, state); + state = SCE_C_IDENTIFIER; + } else if (column == 0 && ch == '*' && chNext != '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '/' && chNext != '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '*' && chNext == '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTDOC; + } else if (column == 0 && ch == '/' && chNext == '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTDOC; + } else if (ch == '"') { + ColourTo(styler, i-1, state); + state = SCE_C_STRING; + } else if (ch == '\'') { + ColourTo(styler, i-1, state); + state = SCE_C_CHARACTER; + } else if (ch == '?' && column == 0) { + ColourTo(styler, i-1, state); + state = SCE_C_PREPROCESSOR; + } else if (isCOBOLoperator(ch)) { + ColourTo(styler, i-1, state); + ColourTo(styler, i, SCE_C_OPERATOR); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!isCOBOLwordchar(ch)) { + int lStateChange = classifyWordCOBOL(styler.GetStartSegment(), i - 1, keywordlists, styler, nContainment, &bAarea); + + if(lStateChange != 0) { + styler.SetLineState(currentLine, lStateChange); + nContainment = lStateChange; + } + + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '"') { + state = SCE_C_STRING; + } else if (ch == '\'') { + state = SCE_C_CHARACTER; + } else if (isCOBOLoperator(ch)) { + ColourTo(styler, i, SCE_C_OPERATOR); + } + } + } else { + if (state == SCE_C_PREPROCESSOR) { + if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENTDOC) { + if (ch == '\r' || ch == '\n') { + if (((i > styler.GetStartSegment() + 2) || ( + (initStyle == SCE_C_COMMENTDOC) && + (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '"') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_CHARACTER) { + if (ch == '\'') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } + } + chPrev = ch; + bNewLine = bSetNewLine; + if (bNewLine) + { + bAarea = false; + } + } + ColourTo(styler, lengthDoc - 1, state); +} + +static void FoldCOBOLDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK : 0xFFF; + char chNext = styler[startPos]; + + bool bNewLine = true; + bool bAarea = !isspacechar(chNext); + int column = 0; + bool bComment = false; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + ++column; + + if (bNewLine) { + column = 0; + bComment = (ch == '*' || ch == '/' || ch == '?'); + } + if (column <= 1 && !bAarea) { + bAarea = !isspacechar(ch); + } + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (atEOL) { + int nContainment = styler.GetLineState(lineCurrent); + int lev = CountBits(nContainment & IN_FLAGS) | SC_FOLDLEVELBASE; + if (bAarea && !bComment) + --lev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((bAarea) && (visibleChars > 0) && !(nContainment & NOT_HEADER) && !bComment) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + if ((lev & SC_FOLDLEVELNUMBERMASK) <= (levelPrev & SC_FOLDLEVELNUMBERMASK)) { + // this level is at the same level or less than the previous line + // therefore these is nothing for the previous header to collapse, so remove the header + styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); + } + levelPrev = lev; + visibleChars = 0; + bAarea = false; + bNewLine = true; + lineCurrent++; + } else { + bNewLine = false; + } + + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const COBOLWordListDesc[] = { + "A Keywords", + "B Keywords", + "Extended Keywords", + 0 +}; + +LexerModule lmCOBOL(SCLEX_COBOL, ColouriseCOBOLDoc, "COBOL", FoldCOBOLDoc, COBOLWordListDesc); diff --git a/src/LexTACL.cxx b/src/LexTACL.cxx new file mode 100644 index 000000000..9259e770c --- /dev/null +++ b/src/LexTACL.cxx @@ -0,0 +1,393 @@ +// Scintilla source code edit control +/** @file LexTAL.cxx + ** Lexer for TAL + ** Based on LexPascal.cxx + ** Written by Laurent le Tynevez + ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002 + ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments) + ** Updated by Rod Falck, Aug 2006 Converted to TACL + **/ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +inline bool isTACLoperator(char ch) + { + return ch == '\'' || isoperator(ch); + } + +inline bool isTACLwordchar(char ch) + { + return ch == '#' || ch == '^' || ch == '|' || ch == '_' || iswordchar(ch); + } + +inline bool isTACLwordstart(char ch) + { + return ch == '#' || ch == '|' || ch == '_' || iswordstart(ch); + } + +static void getRange(unsigned int start, + unsigned int end, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast<char>(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_C_COMMENT || + style == SCE_C_COMMENTDOC || + style == SCE_C_COMMENTDOCKEYWORD || + style == SCE_C_COMMENTDOCKEYWORDERROR; +} + +static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) { + if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) { + styler.ColourTo(end, SCE_C_REGEX); + } else + styler.ColourTo(end, attr); +} + +// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm" +static int classifyWordTACL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) { + int ret = 0; + + WordList& keywords = *keywordlists[0]; + WordList& builtins = *keywordlists[1]; + WordList& commands = *keywordlists[2]; + + char s[100]; + getRange(start, end, styler, s, sizeof(s)); + + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.')) { + chAttr = SCE_C_NUMBER; + } + else { + if (s[0] == '#' || keywords.InList(s)) { + chAttr = SCE_C_WORD; + + if (strcmp(s, "asm") == 0) { + ret = 2; + } + else if (strcmp(s, "end") == 0) { + ret = -1; + } + } + else if (s[0] == '|' || builtins.InList(s)) { + chAttr = SCE_C_WORD2; + } + else if (commands.InList(s)) { + chAttr = SCE_C_UUID; + } + else if (strcmp(s, "comment") == 0) { + chAttr = SCE_C_COMMENTLINE; + ret = 3; + } + } + ColourTo(styler, end, chAttr, (bInAsm && ret != -1)); + return ret; +} + +static int classifyFoldPointTACL(const char* s) { + int lev = 0; + if (s[0] == '[') + lev=1; + else if (s[0] == ']') + lev=-1; + return lev; +} + +static void ColouriseTACLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos); + + int state = initStyle; + if (state == SCE_C_CHARACTER) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + + bool bInClassDefinition; + + int currentLine = styler.GetLine(startPos); + if (currentLine > 0) { + styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); + bInClassDefinition = (styler.GetLineState(currentLine) == 1); + } else { + styler.SetLineState(currentLine, 0); + bInClassDefinition = false; + } + + bool bInAsm = (state == SCE_C_REGEX); + if (bInAsm) + state = SCE_C_DEFAULT; + + styler.StartSegment(startPos); + int visibleChars = 0; + unsigned int i; + for (i = startPos; i < lengthDoc; i++) { + char ch = chNext; + + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + if (state == SCE_C_CHARACTER) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + visibleChars = 0; + currentLine++; + styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0)); + } + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (isTACLwordstart(ch)) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_IDENTIFIER; + } else if (ch == '{') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENT; + } else if (ch == '{' && chNext == '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTDOC; + } else if (ch == '=' && chNext == '=') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTLINE; + } else if (ch == '"') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_STRING; + } else if (ch == '?' && visibleChars == 0) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_PREPROCESSOR; + } else if (isTACLoperator(ch)) { + ColourTo(styler, i-1, state, bInAsm); + ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!isTACLwordchar(ch)) { + int lStateChange = classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); + + if(lStateChange == 1) { + styler.SetLineState(currentLine, 1); + bInClassDefinition = true; + } else if(lStateChange == 2) { + bInAsm = true; + } else if(lStateChange == -1) { + styler.SetLineState(currentLine, 0); + bInClassDefinition = false; + bInAsm = false; + } + + if (lStateChange == 3) { + state = SCE_C_COMMENTLINE; + } + else { + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '{') { + state = SCE_C_COMMENT; + } else if (ch == '{' && chNext == '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTDOC; + } else if (ch == '=' && chNext == '=') { + state = SCE_C_COMMENTLINE; + } else if (ch == '"') { + state = SCE_C_STRING; + } else if (isTACLoperator(ch)) { + ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); + } + } + } + } else { + if (state == SCE_C_PREPROCESSOR) { + if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '}' || (ch == '\r' || ch == '\n') ) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENTDOC) { + if (ch == '}' || (ch == '\r' || ch == '\n')) { + if (((i > styler.GetStartSegment() + 2) || ( + (initStyle == SCE_C_COMMENTDOC) && + (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '"' || ch == '\r' || ch == '\n') { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } + } + if (!isspacechar(ch)) + visibleChars++; + chPrev = ch; + } + + // Process to end of document + if (state == SCE_C_IDENTIFIER) { + classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); + } + else + ColourTo(styler, lengthDoc - 1, state, bInAsm); +} + +static void FoldTACLDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int 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; + bool section = false; + + int lastStart = 0; + + for (unsigned int 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_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_PREPROCESSOR)) + { + // Store last word start point. + lastStart = i; + } + + if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_PREPROCESSOR) { + if(isTACLwordchar(ch) && !isTACLwordchar(chNext)) { + char s[100]; + getRange(lastStart, i, styler, s, sizeof(s)); + if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0) + { + section = true; + levelCurrent = 1; + levelPrev = 0; + } + else if (stylePrev == SCE_C_WORD) + levelCurrent += classifyFoldPointTACL(s); + } + } + + if (style == SCE_C_OPERATOR) { + if (ch == '[') { + levelCurrent++; + } else if (ch == ']') { + levelCurrent--; + } + } + if (foldComment && (style == SCE_C_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelCurrent++; + } else if (chNext2 == '}') { + levelCurrent--; + } + } + } + + if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { + if (ch == '{' && chNext == '$') { + unsigned int j=i+2; // skip {$ + while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelCurrent++; + } else if (styler.Match(j, "end")) { + levelCurrent--; + } + } + } + + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelCurrent++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev | SC_FOLDLEVELBASE; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev || section) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + section = false; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const TACLWordListDesc[] = { + "Builtins", + "Labels", + "Commands", + 0 +}; + +LexerModule lmTACL(SCLEX_TACL, ColouriseTACLDoc, "TACL", FoldTACLDoc, TACLWordListDesc); diff --git a/src/LexTAL.cxx b/src/LexTAL.cxx new file mode 100644 index 000000000..a856dc5f6 --- /dev/null +++ b/src/LexTAL.cxx @@ -0,0 +1,392 @@ +// Scintilla source code edit control +/** @file LexTAL.cxx + ** Lexer for TAL + ** Based on LexPascal.cxx + ** Written by Laurent le Tynevez + ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002 + ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments) + ** Updated by Rod Falck, Aug 2006 Converted to TAL + **/ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +inline bool isTALoperator(char ch) + { + return ch == '\'' || ch == '@' || ch == '#' || isoperator(ch); + } + +inline bool isTALwordchar(char ch) + { + return ch == '$' || ch == '^' || iswordchar(ch); + } + +inline bool isTALwordstart(char ch) + { + return ch == '$' || ch == '^' || iswordstart(ch); + } + +static void getRange(unsigned int start, + unsigned int end, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast<char>(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_C_COMMENT || + style == SCE_C_COMMENTDOC || + style == SCE_C_COMMENTDOCKEYWORD || + style == SCE_C_COMMENTDOCKEYWORDERROR; +} + +static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) { + if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) { + styler.ColourTo(end, SCE_C_REGEX); + } else + styler.ColourTo(end, attr); +} + +// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm" +static int classifyWordTAL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) { + int ret = 0; + + WordList& keywords = *keywordlists[0]; + WordList& builtins = *keywordlists[1]; + WordList& nonreserved_keywords = *keywordlists[2]; + + char s[100]; + getRange(start, end, styler, s, sizeof(s)); + + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.')) { + chAttr = SCE_C_NUMBER; + } + else { + if (keywords.InList(s)) { + chAttr = SCE_C_WORD; + + if (strcmp(s, "asm") == 0) { + ret = 2; + } + else if (strcmp(s, "end") == 0) { + ret = -1; + } + } + else if (s[0] == '$' || builtins.InList(s)) { + chAttr = SCE_C_WORD2; + } + else if (nonreserved_keywords.InList(s)) { + chAttr = SCE_C_UUID; + } + } + ColourTo(styler, end, chAttr, (bInAsm && ret != -1)); + return ret; +} + +static int classifyFoldPointTAL(const char* s) { + int lev = 0; + if (!(isdigit(s[0]) || (s[0] == '.'))) { + if (strcmp(s, "begin") == 0 || + strcmp(s, "block") == 0) { + lev=1; + } else if (strcmp(s, "end") == 0) { + lev=-1; + } + } + return lev; +} + +static void ColouriseTALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos); + + int state = initStyle; + if (state == SCE_C_CHARACTER) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + + bool bInClassDefinition; + + int currentLine = styler.GetLine(startPos); + if (currentLine > 0) { + styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); + bInClassDefinition = (styler.GetLineState(currentLine) == 1); + } else { + styler.SetLineState(currentLine, 0); + bInClassDefinition = false; + } + + bool bInAsm = (state == SCE_C_REGEX); + if (bInAsm) + state = SCE_C_DEFAULT; + + styler.StartSegment(startPos); + int visibleChars = 0; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + if (state == SCE_C_CHARACTER) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + visibleChars = 0; + currentLine++; + styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0)); + } + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (isTALwordstart(ch)) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_IDENTIFIER; + } else if (ch == '!' && chNext != '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENT; + } else if (ch == '!' && chNext == '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTDOC; + } else if (ch == '-' && chNext == '-') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTLINE; + } else if (ch == '"') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_STRING; + } else if (ch == '?' && visibleChars == 0) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_PREPROCESSOR; + } else if (isTALoperator(ch)) { + ColourTo(styler, i-1, state, bInAsm); + ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!isTALwordchar(ch)) { + int lStateChange = classifyWordTAL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); + + if(lStateChange == 1) { + styler.SetLineState(currentLine, 1); + bInClassDefinition = true; + } else if(lStateChange == 2) { + bInAsm = true; + } else if(lStateChange == -1) { + styler.SetLineState(currentLine, 0); + bInClassDefinition = false; + bInAsm = false; + } + + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '!' && chNext != '*') { + state = SCE_C_COMMENT; + } else if (ch == '!' && chNext == '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTDOC; + } else if (ch == '-' && chNext == '-') { + state = SCE_C_COMMENTLINE; + } else if (ch == '"') { + state = SCE_C_STRING; + } else if (isTALoperator(ch)) { + ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); + } + } + } else { + if (state == SCE_C_PREPROCESSOR) { + if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '!' || (ch == '\r' || ch == '\n') ) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENTDOC) { + if (ch == '!' || (ch == '\r' || ch == '\n')) { + if (((i > styler.GetStartSegment() + 2) || ( + (initStyle == SCE_C_COMMENTDOC) && + (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '"') { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } + } + if (!isspacechar(ch)) + visibleChars++; + chPrev = ch; + } + ColourTo(styler, lengthDoc - 1, state, bInAsm); +} + +static void FoldTALDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int 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; + bool was_end = false; + bool section = false; + + int lastStart = 0; + + for (unsigned int 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_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_UUID || style == SCE_C_PREPROCESSOR)) + { + // Store last word start point. + lastStart = i; + } + + if (stylePrev == SCE_C_WORD || style == SCE_C_UUID || stylePrev == SCE_C_PREPROCESSOR) { + if(isTALwordchar(ch) && !isTALwordchar(chNext)) { + char s[100]; + getRange(lastStart, i, styler, s, sizeof(s)); + if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0) + { + section = true; + levelCurrent = 1; + levelPrev = 0; + } + else if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_UUID) + { + if (strcmp(s, "block") == 0) + { + // block keyword is ignored immediately after end keyword + if (!was_end) + levelCurrent++; + } + else + levelCurrent += classifyFoldPointTAL(s); + if (strcmp(s, "end") == 0) + { + was_end = true; + } + else + { + was_end = false; + } + } + } + } + + if (foldComment && (style == SCE_C_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelCurrent++; + } else if (chNext2 == '}') { + levelCurrent--; + } + } + } + + if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { + if (ch == '{' && chNext == '$') { + unsigned int j=i+2; // skip {$ + while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelCurrent++; + } else if (styler.Match(j, "end")) { + levelCurrent--; + } + } + } + + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelCurrent++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (atEOL) { + int lev = levelPrev | SC_FOLDLEVELBASE; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev || section) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + section = false; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const TALWordListDesc[] = { + "Keywords", + "Builtins", + 0 +}; + +LexerModule lmTAL(SCLEX_TAL, ColouriseTALDoc, "TAL", FoldTALDoc, TALWordListDesc); |