1 // Scintilla source code edit control
5 // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
6 // Copyright 2013-2014 by Andreas Tscharner <andy@vis.ethz.ch>
7 // The License.txt file describes the conditions under which this software may be distributed.
16 #include "Scintilla.h"
20 #include "LexAccessor.h"
21 #include "StyleContext.h"
22 #include "CharacterSet.h"
23 #include "LexerModule.h"
26 using namespace Scintilla
;
30 static const char *const DMISWordListDesc
[] = {
33 "Unsupported DMIS Major Words",
34 "Unsupported DMIS Minor Words",
35 "Keywords for code folding start",
36 "Corresponding keywords for code folding end",
41 class LexerDMIS
: public ILexer
45 WordList m_majorWords
;
46 WordList m_minorWords
;
47 WordList m_unsupportedMajor
;
48 WordList m_unsupportedMinor
;
49 WordList m_codeFoldingStart
;
50 WordList m_codeFoldingEnd
;
52 char * SCI_METHOD
UpperCase(char *item
);
53 void SCI_METHOD
InitWordListSets(void);
57 virtual ~LexerDMIS(void);
59 int SCI_METHOD
Version() const {
63 void SCI_METHOD
Release() {
67 const char * SCI_METHOD
PropertyNames() {
71 int SCI_METHOD
PropertyType(const char *) {
75 const char * SCI_METHOD
DescribeProperty(const char *) {
79 int SCI_METHOD
PropertySet(const char *, const char *) {
83 int SCI_METHOD
WordListSet(int n
, const char *wl
);
85 void * SCI_METHOD
PrivateCall(int, void *) {
89 static ILexer
*LexerFactoryDMIS() {
93 const char * SCI_METHOD
DescribeWordListSets();
94 void SCI_METHOD
Lex(unsigned int startPos
, int lengthDoc
, int initStyle
, IDocument
*pAccess
);
95 void SCI_METHOD
Fold(unsigned int startPos
, int lengthDoc
, int initStyle
, IDocument
*pAccess
);
99 char * SCI_METHOD
LexerDMIS::UpperCase(char *item
)
105 while (item
&& *item
) {
106 *item
= toupper(*item
);
112 void SCI_METHOD
LexerDMIS::InitWordListSets(void)
117 for (int i
=0; DMISWordListDesc
[i
]; i
++) {
118 totalLen
+= strlen(DMISWordListDesc
[i
]);
123 this->m_wordListSets
= new char[totalLen
];
124 memset(this->m_wordListSets
, 0, totalLen
);
126 for (int i
=0; DMISWordListDesc
[i
]; i
++) {
127 strcat(this->m_wordListSets
, DMISWordListDesc
[i
]);
128 strcat(this->m_wordListSets
, "\n");
133 LexerDMIS::LexerDMIS(void) {
134 this->InitWordListSets();
136 this->m_majorWords
.Clear();
137 this->m_minorWords
.Clear();
138 this->m_unsupportedMajor
.Clear();
139 this->m_unsupportedMinor
.Clear();
140 this->m_codeFoldingStart
.Clear();
141 this->m_codeFoldingEnd
.Clear();
144 LexerDMIS::~LexerDMIS(void) {
145 delete[] this->m_wordListSets
;
148 int SCI_METHOD
LexerDMIS::WordListSet(int n
, const char *wl
)
152 this->m_majorWords
.Clear();
153 this->m_majorWords
.Set(wl
);
156 this->m_minorWords
.Clear();
157 this->m_minorWords
.Set(wl
);
160 this->m_unsupportedMajor
.Clear();
161 this->m_unsupportedMajor
.Set(wl
);
164 this->m_unsupportedMinor
.Clear();
165 this->m_unsupportedMinor
.Set(wl
);
168 this->m_codeFoldingStart
.Clear();
169 this->m_codeFoldingStart
.Set(wl
);
172 this->m_codeFoldingEnd
.Clear();
173 this->m_codeFoldingEnd
.Set(wl
);
183 const char * SCI_METHOD
LexerDMIS::DescribeWordListSets()
185 return this->m_wordListSets
;
188 void SCI_METHOD
LexerDMIS::Lex(unsigned int startPos
, int lengthDoc
, int initStyle
, IDocument
*pAccess
)
190 const unsigned int MAX_STR_LEN
= 100;
192 LexAccessor
styler(pAccess
);
193 StyleContext
scCTX(startPos
, lengthDoc
, initStyle
, styler
);
194 CharacterSet
setDMISNumber(CharacterSet::setDigits
, ".-+eE");
195 CharacterSet
setDMISWordStart(CharacterSet::setAlpha
, "-234", 0x80, true);
196 CharacterSet
setDMISWord(CharacterSet::setAlpha
);
199 bool isIFLine
= false;
201 for (; scCTX
.More(); scCTX
.Forward()) {
202 if (scCTX
.atLineEnd
) {
206 switch (scCTX
.state
) {
207 case SCE_DMIS_DEFAULT
:
208 if (scCTX
.Match('$', '$')) {
209 scCTX
.SetState(SCE_DMIS_COMMENT
);
212 if (scCTX
.Match('\'')) {
213 scCTX
.SetState(SCE_DMIS_STRING
);
215 if (IsADigit(scCTX
.ch
) || ((scCTX
.Match('-') || scCTX
.Match('+')) && IsADigit(scCTX
.chNext
))) {
216 scCTX
.SetState(SCE_DMIS_NUMBER
);
219 if (setDMISWordStart
.Contains(scCTX
.ch
)) {
220 scCTX
.SetState(SCE_DMIS_KEYWORD
);
222 if (scCTX
.Match('(') && (!isIFLine
)) {
223 scCTX
.SetState(SCE_DMIS_LABEL
);
227 case SCE_DMIS_COMMENT
:
228 if (scCTX
.atLineEnd
) {
229 scCTX
.SetState(SCE_DMIS_DEFAULT
);
233 case SCE_DMIS_STRING
:
234 if (scCTX
.Match('\'')) {
235 scCTX
.SetState(SCE_DMIS_DEFAULT
);
239 case SCE_DMIS_NUMBER
:
240 if (!setDMISNumber
.Contains(scCTX
.ch
)) {
241 scCTX
.SetState(SCE_DMIS_DEFAULT
);
245 case SCE_DMIS_KEYWORD
:
246 if (!setDMISWord
.Contains(scCTX
.ch
)) {
247 char tmpStr
[MAX_STR_LEN
];
248 memset(tmpStr
, 0, MAX_STR_LEN
*sizeof(char));
249 scCTX
.GetCurrent(tmpStr
, (MAX_STR_LEN
-1));
250 strncpy(tmpStr
, this->UpperCase(tmpStr
), (MAX_STR_LEN
-1));
252 if (this->m_minorWords
.InList(tmpStr
)) {
253 scCTX
.ChangeState(SCE_DMIS_MINORWORD
);
255 if (this->m_majorWords
.InList(tmpStr
)) {
256 isIFLine
= (strcmp(tmpStr
, "IF") == 0);
257 scCTX
.ChangeState(SCE_DMIS_MAJORWORD
);
259 if (this->m_unsupportedMajor
.InList(tmpStr
)) {
260 scCTX
.ChangeState(SCE_DMIS_UNSUPPORTED_MAJOR
);
262 if (this->m_unsupportedMinor
.InList(tmpStr
)) {
263 scCTX
.ChangeState(SCE_DMIS_UNSUPPORTED_MINOR
);
266 if (scCTX
.Match('(') && (!isIFLine
)) {
267 scCTX
.SetState(SCE_DMIS_LABEL
);
269 scCTX
.SetState(SCE_DMIS_DEFAULT
);
275 if (scCTX
.Match(')')) {
276 scCTX
.SetState(SCE_DMIS_DEFAULT
);
284 void SCI_METHOD
LexerDMIS::Fold(unsigned int startPos
, int lengthDoc
, int, IDocument
*pAccess
)
286 const int MAX_STR_LEN
= 100;
288 LexAccessor
styler(pAccess
);
289 unsigned int endPos
= startPos
+ lengthDoc
;
290 char chNext
= styler
[startPos
];
291 int lineCurrent
= styler
.GetLine(startPos
);
292 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
293 int levelCurrent
= levelPrev
;
295 bool foldWordPossible
= false;
296 CharacterSet
setDMISFoldWord(CharacterSet::setAlpha
);
300 tmpStr
= new char[MAX_STR_LEN
];
301 memset(tmpStr
, 0, MAX_STR_LEN
*sizeof(char));
303 for (unsigned int i
=startPos
; i
<endPos
; i
++) {
305 chNext
= styler
.SafeGetCharAt(i
+1);
307 bool atEOL
= ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n'));
309 if (strPos
>= (MAX_STR_LEN
-1)) {
310 strPos
= MAX_STR_LEN
-1;
313 int style
= styler
.StyleAt(i
);
314 bool noFoldPos
= ((style
== SCE_DMIS_COMMENT
) || (style
== SCE_DMIS_STRING
));
316 if (foldWordPossible
) {
317 if (setDMISFoldWord
.Contains(ch
)) {
318 tmpStr
[strPos
++] = ch
;
320 tmpStr
= this->UpperCase(tmpStr
);
321 if (this->m_codeFoldingStart
.InList(tmpStr
) && (!noFoldPos
)) {
324 if (this->m_codeFoldingEnd
.InList(tmpStr
) && (!noFoldPos
)) {
327 memset(tmpStr
, 0, MAX_STR_LEN
*sizeof(char));
329 foldWordPossible
= false;
332 if (setDMISFoldWord
.Contains(ch
)) {
333 tmpStr
[strPos
++] = ch
;
334 foldWordPossible
= true;
338 if (atEOL
|| (i
== (endPos
-1))) {
341 if (levelCurrent
> levelPrev
) {
342 lev
|= SC_FOLDLEVELHEADERFLAG
;
344 if (lev
!= styler
.LevelAt(lineCurrent
)) {
345 styler
.SetLevel(lineCurrent
, lev
);
348 levelPrev
= levelCurrent
;
355 LexerModule
lmDMIS(SCLEX_DMIS
, LexerDMIS::LexerFactoryDMIS
, "DMIS", DMISWordListDesc
);