diff options
Diffstat (limited to 'lexers/LexSTTXT.cxx')
-rw-r--r-- | lexers/LexSTTXT.cxx | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/lexers/LexSTTXT.cxx b/lexers/LexSTTXT.cxx new file mode 100644 index 000000000..c58d054aa --- /dev/null +++ b/lexers/LexSTTXT.cxx @@ -0,0 +1,401 @@ +// Scintilla source code edit control +/** @file LexSTTXT.cxx + ** Lexer for Structured Text language. + ** Written by Pavel Bulochkin + **/ +// The License.txt file describes the conditions under which this software may be distributed. + + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#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" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ClassifySTTXTWord(WordList *keywordlists[], StyleContext &sc) +{ + char s[256] = { 0 }; + sc.GetCurrentLowered(s, sizeof(s)); + + if ((*keywordlists[0]).InList(s)) { + sc.ChangeState(SCE_STTXT_KEYWORD); + } + + else if ((*keywordlists[1]).InList(s)) { + sc.ChangeState(SCE_STTXT_TYPE); + } + + else if ((*keywordlists[2]).InList(s)) { + sc.ChangeState(SCE_STTXT_FUNCTION); + } + + else if ((*keywordlists[3]).InList(s)) { + sc.ChangeState(SCE_STTXT_FB); + } + + else if ((*keywordlists[4]).InList(s)) { + sc.ChangeState(SCE_STTXT_VARS); + } + + else if ((*keywordlists[5]).InList(s)) { + sc.ChangeState(SCE_STTXT_PRAGMAS); + } + + sc.SetState(SCE_STTXT_DEFAULT); +} + +static void ColouriseSTTXTDoc (unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setNumber(CharacterSet::setDigits, "_.eE"); + CharacterSet setHexNumber(CharacterSet::setDigits, "_abcdefABCDEF"); + CharacterSet setOperator(CharacterSet::setNone,",.+-*/:;<=>[]()%&"); + CharacterSet setDataTime(CharacterSet::setDigits,"_.-:dmshDMSH"); + + for ( ; sc.More() ; sc.Forward()) + { + if(sc.atLineStart && sc.state != SCE_STTXT_COMMENT) + sc.SetState(SCE_STTXT_DEFAULT); + + switch(sc.state) + { + case SCE_STTXT_NUMBER: { + if(!setNumber.Contains(sc.ch)) + sc.SetState(SCE_STTXT_DEFAULT); + break; + } + case SCE_STTXT_HEXNUMBER: { + if(setHexNumber.Contains(sc.ch)) + continue; + else if(setDataTime.Contains(sc.ch)) + sc.SetState(SCE_STTXT_DATETIME); + else + sc.SetState(SCE_STTXT_DEFAULT); + + break; + } + case SCE_STTXT_DATETIME: { + if(!setDataTime.Contains(sc.ch)) + sc.SetState(SCE_STTXT_DEFAULT); + break; + } + case SCE_STTXT_OPERATOR: { + sc.SetState(SCE_STTXT_DEFAULT); + break; + } + case SCE_STTXT_PRAGMA: { + if (sc.ch == '}') + sc.ForwardSetState(SCE_STTXT_DEFAULT); + break; + } + case SCE_STTXT_COMMENTLINE: { + if (sc.atLineStart) + sc.SetState(SCE_STTXT_DEFAULT); + break; + } + case SCE_STTXT_COMMENT: { + if(sc.Match('*',')')) + { + sc.Forward(); + sc.ForwardSetState(SCE_STTXT_DEFAULT); + } + break; + } + case SCE_STTXT_STRING1: { + if(sc.atLineEnd) + sc.SetState(SCE_STTXT_STRINGEOL); + else if(sc.ch == '\'' && sc.chPrev != '$') + sc.ForwardSetState(SCE_STTXT_DEFAULT); + break; + } + case SCE_STTXT_STRING2: { + if (sc.atLineEnd) + sc.SetState(SCE_STTXT_STRINGEOL); + else if(sc.ch == '\"' && sc.chPrev != '$') + sc.ForwardSetState(SCE_STTXT_DEFAULT); + break; + } + case SCE_STTXT_STRINGEOL: { + if(sc.atLineStart) + sc.SetState(SCE_STTXT_DEFAULT); + break; + } + case SCE_STTXT_CHARACTER: { + if(setHexNumber.Contains(sc.ch)) + sc.SetState(SCE_STTXT_HEXNUMBER); + else if(setDataTime.Contains(sc.ch)) + sc.SetState(SCE_STTXT_DATETIME); + else sc.SetState(SCE_STTXT_DEFAULT); + break; + } + case SCE_STTXT_IDENTIFIER: { + if(!setWord.Contains(sc.ch)) + ClassifySTTXTWord(keywordlists, sc); + break; + } + } + + if(sc.state == SCE_STTXT_DEFAULT) + { + if(IsADigit(sc.ch)) + sc.SetState(SCE_STTXT_NUMBER); + else if (setWordStart.Contains(sc.ch)) + sc.SetState(SCE_STTXT_IDENTIFIER); + else if (sc.Match('/', '/')) + sc.SetState(SCE_STTXT_COMMENTLINE); + else if(sc.Match('(', '*')) + sc.SetState(SCE_STTXT_COMMENT); + else if (sc.ch == '{') + sc.SetState(SCE_STTXT_PRAGMA); + else if (sc.ch == '\'') + sc.SetState(SCE_STTXT_STRING1); + else if (sc.ch == '\"') + sc.SetState(SCE_STTXT_STRING2); + else if(sc.ch == '#') + sc.SetState(SCE_STTXT_CHARACTER); + else if (setOperator.Contains(sc.ch)) + sc.SetState(SCE_STTXT_OPERATOR); + } + } + + if (sc.state == SCE_STTXT_IDENTIFIER && setWord.Contains(sc.chPrev)) + ClassifySTTXTWord(keywordlists, sc); + + sc.Complete(); +} + +static const char * const STTXTWordListDesc[] = { + "Keywords", + "Types", + "Functions", + "FB", + "Local_Var", + "Local_Pragma", + 0 +}; + +static bool IsCommentLine(int line, Accessor &styler, bool type) +{ + int pos = styler.LineStart(line); + int eolPos = styler.LineStart(line + 1) - 1; + + for (int i = pos; i < eolPos; i++) + { + char ch = styler[i]; + char chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + + if(type) { + if (ch == '/' && chNext == '/' && style == SCE_STTXT_COMMENTLINE) + return true; + } + else if (ch == '(' && chNext == '*' && style == SCE_STTXT_COMMENT) + break; + + if (!IsASpaceOrTab(ch)) + return false; + } + + for (int i = eolPos-2; i>pos; i--) + { + char ch = styler[i]; + char chPrev = styler.SafeGetCharAt(i-1); + int style = styler.StyleAt(i); + + if(ch == ')' && chPrev == '*' && style == SCE_STTXT_COMMENT) + return true; + if(!IsASpaceOrTab(ch)) + return false; + } + + return false; +} + +static bool IsPragmaLine(int line, Accessor &styler) +{ + int pos = styler.LineStart(line); + int eolPos = styler.LineStart(line+1) - 1; + + for (int i = pos ; i < eolPos ; i++) + { + char ch = styler[i]; + int style = styler.StyleAt(i); + + if(ch == '{' && style == SCE_STTXT_PRAGMA) + return true; + else if (!IsASpaceOrTab(ch)) + return false; + } + return false; +} + +static void GetRangeUpper(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>(toupper(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static void ClassifySTTXTWordFoldPoint(int &levelCurrent,unsigned int lastStart, + unsigned int currentPos, Accessor &styler) +{ + char s[256]; + GetRangeUpper(lastStart, currentPos, styler, s, sizeof(s)); + + // See Table C.2 - Keywords + if (!strcmp(s, "ACTION") || + !strcmp(s, "CASE") || + !strcmp(s, "CONFIGURATION") || + !strcmp(s, "FOR") || + !strcmp(s, "FUNCTION") || + !strcmp(s, "FUNCTION_BLOCK") || + !strcmp(s, "IF") || + !strcmp(s, "INITIAL_STEP") || + !strcmp(s, "REPEAT") || + !strcmp(s, "RESOURCE") || + !strcmp(s, "STEP") || + !strcmp(s, "STRUCT") || + !strcmp(s, "TRANSITION") || + !strcmp(s, "TYPE") || + !strcmp(s, "VAR") || + !strcmp(s, "VAR_INPUT") || + !strcmp(s, "VAR_OUTPUT") || + !strcmp(s, "VAR_IN_OUT") || + !strcmp(s, "VAR_TEMP") || + !strcmp(s, "VAR_EXTERNAL") || + !strcmp(s, "VAR_ACCESS") || + !strcmp(s, "VAR_CONFIG") || + !strcmp(s, "VAR_GLOBAL") || + !strcmp(s, "WHILE")) + { + levelCurrent++; + } + else if (!strcmp(s, "END_ACTION") || + !strcmp(s, "END_CASE") || + !strcmp(s, "END_CONFIGURATION") || + !strcmp(s, "END_FOR") || + !strcmp(s, "END_FUNCTION") || + !strcmp(s, "END_FUNCTION_BLOCK") || + !strcmp(s, "END_IF") || + !strcmp(s, "END_REPEAT") || + !strcmp(s, "END_RESOURCE") || + !strcmp(s, "END_STEP") || + !strcmp(s, "END_STRUCT") || + !strcmp(s, "END_TRANSITION") || + !strcmp(s, "END_TYPE") || + !strcmp(s, "END_VAR") || + !strcmp(s, "END_WHILE")) + { + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } + } +} + +static void FoldSTTXTDoc(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; + int lastStart = 0; + + CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); + + 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 (foldComment && style == SCE_STTXT_COMMENT) { + if(stylePrev != SCE_STTXT_COMMENT) + levelCurrent++; + else if(styleNext != SCE_STTXT_COMMENT && !atEOL) + levelCurrent--; + } + if ( foldComment && atEOL && ( IsCommentLine(lineCurrent, styler,false) + || IsCommentLine(lineCurrent,styler,true))) { + if(!IsCommentLine(lineCurrent-1, styler,true) && IsCommentLine(lineCurrent+1, styler,true)) + levelCurrent++; + if (IsCommentLine(lineCurrent-1, styler,true) && !IsCommentLine(lineCurrent+1, styler,true)) + levelCurrent--; + if (!IsCommentLine(lineCurrent-1, styler,false) && IsCommentLine(lineCurrent+1, styler,false)) + levelCurrent++; + if (IsCommentLine(lineCurrent-1, styler,false) && !IsCommentLine(lineCurrent+1, styler,false)) + levelCurrent--; + } + if(foldPreprocessor && atEOL && IsPragmaLine(lineCurrent, styler)) { + if(!IsPragmaLine(lineCurrent-1, styler) && IsPragmaLine(lineCurrent+1, styler )) + levelCurrent++; + else if(IsPragmaLine(lineCurrent-1, styler) && !IsPragmaLine(lineCurrent+1, styler)) + levelCurrent--; + } + if (stylePrev != SCE_STTXT_KEYWORD && style == SCE_STTXT_KEYWORD) { + lastStart = i; + } + if(stylePrev == SCE_STTXT_KEYWORD) { + if(setWord.Contains(ch) && !setWord.Contains(chNext)) + ClassifySTTXTWordFoldPoint(levelCurrent,lastStart, i, styler); + } + if (!IsASpace(ch)) { + visibleChars++; + } + 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 we didn't reach the EOL in previous loop, store line level and whitespace information. + // The rest will be filled in later... + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + styler.SetLevel(lineCurrent, lev); + } +} + +LexerModule lmSTTXT(SCLEX_STTXT, ColouriseSTTXTDoc, "fcST", FoldSTTXTDoc, STTXTWordListDesc); |