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);  | 
