diff options
author | Neil <nyamatongwe@gmail.com> | 2014-04-29 08:35:12 +1000 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2014-04-29 08:35:12 +1000 |
commit | ac63e3430a9787d1c98090a5f55dadc3cc4dd6f3 (patch) | |
tree | 49dc7806819b13b7c61018259b83d53fb76a0a1b | |
parent | 8265cfedef23121375966cfd6f22975330580f11 (diff) | |
download | scintilla-mirror-ac63e3430a9787d1c98090a5f55dadc3cc4dd6f3.tar.gz |
Feature [feature-requests:#1049]. Lexer added for DMIS, a language for coordinate
measuring machines.
From Andreas Tscharner.
-rw-r--r-- | doc/ScintillaHistory.html | 5 | ||||
-rw-r--r-- | include/SciLexer.h | 11 | ||||
-rw-r--r-- | include/Scintilla.iface | 13 | ||||
-rw-r--r-- | lexers/LexDMIS.cxx | 355 | ||||
-rw-r--r-- | src/Catalogue.cxx | 1 | ||||
-rw-r--r-- | win32/scintilla.mak | 3 |
6 files changed, 388 insertions, 0 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index b6c2fbc50..4f95c28af 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -447,6 +447,7 @@ <td>Mike M</td> </tr><tr> <td>nkmathew</td> + <td>Andreas Tscharner</td> </tr> </table> <p> @@ -470,6 +471,10 @@ SC_MOD_INSERTCHECK. </li> <li> + DMIS lexer added. DMIS is a language for coordinate measuring machines. + <a href="http://sourceforge.net/p/scintilla/feature-requests/1049/">Feature #1049.</a> + </li> + <li> Line state may be displayed in the line number margin to aid in debugging lexing and folding with SC_FOLDFLAG_LINESTATE (128). </li> diff --git a/include/SciLexer.h b/include/SciLexer.h index 0438f545d..54cc8ba7e 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -126,6 +126,7 @@ #define SCLEX_RUST 111 #define SCLEX_DMAP 112 #define SCLEX_AS 113 +#define SCLEX_DMIS 114 #define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 @@ -1702,6 +1703,16 @@ #define SCE_DMAP_WORD 8 #define SCE_DMAP_WORD2 9 #define SCE_DMAP_WORD3 10 +#define SCE_DMIS_DEFAULT 0 +#define SCE_DMIS_COMMENT 1 +#define SCE_DMIS_STRING 2 +#define SCE_DMIS_NUMBER 3 +#define SCE_DMIS_KEYWORD 4 +#define SCE_DMIS_MAJORWORD 5 +#define SCE_DMIS_MINORWORD 6 +#define SCE_DMIS_UNSUPPORTED_MAJOR 7 +#define SCE_DMIS_UNSUPPORTED_MINOR 8 +#define SCE_DMIS_LABEL 9 /* --Autogenerated -- end of section automatically generated from Scintilla.iface */ #endif diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 2fe27654a..f6b17bca8 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -2664,6 +2664,7 @@ val SCLEX_KVIRC=110 val SCLEX_RUST=111 val SCLEX_DMAP=112 val SCLEX_AS=113 +val SCLEX_DMIS=114 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -4445,6 +4446,18 @@ val SCE_DMAP_IDENTIFIER=7 val SCE_DMAP_WORD=8 val SCE_DMAP_WORD2=9 val SCE_DMAP_WORD3=10 +# Lexical states for SCLEX_DMIS +lex DMIS=SCLEX_DMIS SCE_DMIS_ +val SCE_DMIS_DEFAULT=0 +val SCE_DMIS_COMMENT=1 +val SCE_DMIS_STRING=2 +val SCE_DMIS_NUMBER=3 +val SCE_DMIS_KEYWORD=4 +val SCE_DMIS_MAJORWORD=5 +val SCE_DMIS_MINORWORD=6 +val SCE_DMIS_UNSUPPORTED_MAJOR=7 +val SCE_DMIS_UNSUPPORTED_MINOR=8 +val SCE_DMIS_LABEL=9 # Events diff --git a/lexers/LexDMIS.cxx b/lexers/LexDMIS.cxx new file mode 100644 index 000000000..38526154d --- /dev/null +++ b/lexers/LexDMIS.cxx @@ -0,0 +1,355 @@ +// Scintilla source code edit control +/** @file LexDMIS.cxx + ** Lexer for DMIS. + **/ +// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> +// Copyright 2013-2014 by Andreas Tscharner <andy@vis.ethz.ch> +// The License.txt file describes the conditions under which this software may be distributed. + + +#include <cstdlib> +#include <cassert> +#include <cstring> +#include <cctype> + +#include "ILexer.h" +#include "SciLexer.h" +#include "Scintilla.h" + +#include "LexerModule.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "WordList.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static const char *const DMISWordListDesc[] = { + "DMIS Major Words", + "DMIS Minor Words", + "Unsupported DMIS Major Words", + "Unsupported DMIS Minor Words", + "Keywords for code folding start", + "Corresponding keywords for code folding end", + 0 +}; + + +class LexerDMIS : public ILexer +{ + private: + char *m_wordListSets; + WordList m_majorWords; + WordList m_minorWords; + WordList m_unsupportedMajor; + WordList m_unsupportedMinor; + WordList m_codeFoldingStart; + WordList m_codeFoldingEnd; + + char * SCI_METHOD UpperCase(char *item); + void SCI_METHOD InitWordListSets(void); + + public: + LexerDMIS(void); + virtual ~LexerDMIS(void); + + int SCI_METHOD Version() const { + return lvOriginal; + } + + void SCI_METHOD Release() { + delete this; + } + + const char * SCI_METHOD PropertyNames() { + return NULL; + } + + int SCI_METHOD PropertyType(const char *) { + return -1; + } + + const char * SCI_METHOD DescribeProperty(const char *) { + return NULL; + } + + int SCI_METHOD PropertySet(const char *, const char *) { + return -1; + } + + int SCI_METHOD WordListSet(int n, const char *wl); + + void * SCI_METHOD PrivateCall(int, void *) { + return NULL; + } + + static ILexer *LexerFactoryDMIS() { + return new LexerDMIS; + } + + const char * SCI_METHOD DescribeWordListSets(); + void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); +}; + + +char * SCI_METHOD LexerDMIS::UpperCase(char *item) +{ + char *itemStart; + + + itemStart = item; + while (item && *item) { + *item = toupper(*item); + item++; + }; + return itemStart; +} + +void SCI_METHOD LexerDMIS::InitWordListSets(void) +{ + size_t totalLen = 0; + + + for (int i=0; DMISWordListDesc[i]; i++) { + totalLen += strlen(DMISWordListDesc[i]); + totalLen++; + }; + + totalLen++; + this->m_wordListSets = new char[totalLen]; + memset(this->m_wordListSets, 0, totalLen); + + for (int i=0; DMISWordListDesc[i]; i++) { + strcat(this->m_wordListSets, DMISWordListDesc[i]); + strcat(this->m_wordListSets, "\n"); + }; +} + + +LexerDMIS::LexerDMIS(void) { + this->InitWordListSets(); + + this->m_majorWords.Clear(); + this->m_minorWords.Clear(); + this->m_unsupportedMajor.Clear(); + this->m_unsupportedMinor.Clear(); + this->m_codeFoldingStart.Clear(); + this->m_codeFoldingEnd.Clear(); +} + +LexerDMIS::~LexerDMIS(void) { + delete[] this->m_wordListSets; +} + +int SCI_METHOD LexerDMIS::WordListSet(int n, const char *wl) +{ + switch (n) { + case 0: + this->m_majorWords.Clear(); + this->m_majorWords.Set(wl); + break; + case 1: + this->m_minorWords.Clear(); + this->m_minorWords.Set(wl); + break; + case 2: + this->m_unsupportedMajor.Clear(); + this->m_unsupportedMajor.Set(wl); + break; + case 3: + this->m_unsupportedMinor.Clear(); + this->m_unsupportedMinor.Set(wl); + break; + case 4: + this->m_codeFoldingStart.Clear(); + this->m_codeFoldingStart.Set(wl); + break; + case 5: + this->m_codeFoldingEnd.Clear(); + this->m_codeFoldingEnd.Set(wl); + break; + default: + return -1; + break; + } + + return 0; +} + +const char * SCI_METHOD LexerDMIS::DescribeWordListSets() +{ + return this->m_wordListSets; +} + +void SCI_METHOD LexerDMIS::Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) +{ + const unsigned int MAX_STR_LEN = 100; + + LexAccessor styler(pAccess); + StyleContext scCTX(startPos, lengthDoc, initStyle, styler); + CharacterSet setDMISNumber(CharacterSet::setDigits, ".-+eE"); + CharacterSet setDMISWordStart(CharacterSet::setAlpha, "-", 0x80, true); + CharacterSet setDMISWord(CharacterSet::setAlpha); + + + bool isIFLine = false; + + for (; scCTX.More(); scCTX.Forward()) { + if (scCTX.atLineEnd) { + isIFLine = false; + }; + + switch (scCTX.state) { + case SCE_DMIS_DEFAULT: + if (scCTX.Match('$', '$')) { + scCTX.SetState(SCE_DMIS_COMMENT); + scCTX.Forward(); + }; + if (scCTX.Match('\'')) { + scCTX.SetState(SCE_DMIS_STRING); + }; + if (IsADigit(scCTX.ch) || ((scCTX.Match('-') || scCTX.Match('+')) && IsADigit(scCTX.chNext))) { + scCTX.SetState(SCE_DMIS_NUMBER); + break; + }; + if (setDMISWordStart.Contains(scCTX.ch)) { + scCTX.SetState(SCE_DMIS_KEYWORD); + }; + if (scCTX.Match('(') && (!isIFLine)) { + scCTX.SetState(SCE_DMIS_LABEL); + }; + break; + + case SCE_DMIS_COMMENT: + if (scCTX.atLineEnd) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + + case SCE_DMIS_STRING: + if (scCTX.Match('\'')) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + + case SCE_DMIS_NUMBER: + if (!setDMISNumber.Contains(scCTX.ch)) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + + case SCE_DMIS_KEYWORD: + if (!setDMISWord.Contains(scCTX.ch)) { + char tmpStr[MAX_STR_LEN]; + memset(tmpStr, 0, MAX_STR_LEN*sizeof(char)); + scCTX.GetCurrent(tmpStr, (MAX_STR_LEN-1)); + strncpy(tmpStr, this->UpperCase(tmpStr), (MAX_STR_LEN-1)); + + if (this->m_minorWords.InList(tmpStr)) { + scCTX.ChangeState(SCE_DMIS_MINORWORD); + }; + if (this->m_majorWords.InList(tmpStr)) { + isIFLine = (strcmp(tmpStr, "IF") == 0); + scCTX.ChangeState(SCE_DMIS_MAJORWORD); + }; + if (this->m_unsupportedMajor.InList(tmpStr)) { + scCTX.ChangeState(SCE_DMIS_UNSUPPORTED_MAJOR); + }; + if (this->m_unsupportedMinor.InList(tmpStr)) { + scCTX.ChangeState(SCE_DMIS_UNSUPPORTED_MINOR); + }; + + if (scCTX.Match('(') && (isIFLine)) { + scCTX.SetState(SCE_DMIS_LABEL); + } else { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + }; + break; + + case SCE_DMIS_LABEL: + if (scCTX.Match(')')) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + }; + }; + scCTX.Complete(); +} + +void SCI_METHOD LexerDMIS::Fold(unsigned int startPos, int lengthDoc, int, IDocument *pAccess) +{ + const int MAX_STR_LEN = 100; + + LexAccessor styler(pAccess); + unsigned int endPos = startPos + lengthDoc; + char chNext = styler[startPos]; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + int strPos = 0; + bool foldWordPossible = false; + CharacterSet setDMISFoldWord(CharacterSet::setAlpha); + char *tmpStr; + + + tmpStr = new char[MAX_STR_LEN]; + memset(tmpStr, 0, MAX_STR_LEN*sizeof(char)); + + for (unsigned int i=startPos; i<endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i+1); + + bool atEOL = ((ch == '\r' && chNext != '\n') || (ch == '\n')); + + if (strPos >= (MAX_STR_LEN-1)) { + strPos = MAX_STR_LEN-1; + }; + + int style = styler.StyleAt(i); + bool noFoldPos = ((style == SCE_DMIS_COMMENT) || (style == SCE_DMIS_STRING)); + + if (foldWordPossible) { + if (setDMISFoldWord.Contains(ch)) { + tmpStr[strPos++] = ch; + } else { + tmpStr = this->UpperCase(tmpStr); + if (this->m_codeFoldingStart.InList(tmpStr) && (!noFoldPos)) { + levelCurrent++; + }; + if (this->m_codeFoldingEnd.InList(tmpStr) && (!noFoldPos)) { + levelCurrent--; + }; + memset(tmpStr, 0, MAX_STR_LEN*sizeof(char)); + strPos = 0; + foldWordPossible = false; + }; + } else { + if (setDMISFoldWord.Contains(ch)) { + tmpStr[strPos++] = ch; + foldWordPossible = true; + }; + }; + + if (atEOL || (i == (endPos-1))) { + int lev = levelPrev; + + if (levelCurrent > levelPrev) { + lev |= SC_FOLDLEVELHEADERFLAG; + }; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + }; + lineCurrent++; + levelPrev = levelCurrent; + }; + }; + delete[] tmpStr; +} + + +LexerModule lmDMIS(SCLEX_DMIS, LexerDMIS::LexerFactoryDMIS, "DMIS", DMISWordListDesc); diff --git a/src/Catalogue.cxx b/src/Catalogue.cxx index 41d5d5489..c507296d2 100644 --- a/src/Catalogue.cxx +++ b/src/Catalogue.cxx @@ -106,6 +106,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmD); LINK_LEXER(lmDiff); LINK_LEXER(lmDMAP); + LINK_LEXER(lmDMIS); LINK_LEXER(lmECL); LINK_LEXER(lmEiffel); LINK_LEXER(lmEiffelkw); diff --git a/win32/scintilla.mak b/win32/scintilla.mak index d9b0be80e..f4421d3b1 100644 --- a/win32/scintilla.mak +++ b/win32/scintilla.mak @@ -116,6 +116,7 @@ LEXOBJS=\ $(DIR_O)\LexCSS.obj \ $(DIR_O)\LexD.obj \ $(DIR_O)\LexDMAP.obj \ + $(DIR_O)\LexDMIS.obj \ $(DIR_O)\LexECL.obj \ $(DIR_O)\LexEiffel.obj \ $(DIR_O)\LexErlang.obj \ @@ -369,6 +370,8 @@ $(DIR_O)\LexD.obj: ..\lexers\LexD.cxx $(LEX_HEADERS) $(DIR_O)\LexDMAP.obj: ..\lexers\LexDMAP.cxx $(LEX_HEADERS) +$(DIR_O)\LexDMIS.obj: ..\lexers\LexDMIS.cxx $(LEX_HEADERS) + $(DIR_O)\LexECL.obj: ..\lexers\LexECL.cxx $(LEX_HEADERS) $(DIR_O)\LexEiffel.obj: ..\lexers\LexEiffel.cxx $(LEX_HEADERS) |