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