]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexProgress.cxx
1 // Scintilla source code edit control
2 /** @file LexProgress.cxx
3 ** Lexer for Progress 4GL.
4 ** Based on LexCPP.cxx of Neil Hodgson <neilh@scintilla.org>
6 // Copyright 2006-2007 by Yuval Papish <Yuval@YuvCom.com>
7 // The License.txt file describes the conditions under which this software may be distributed.
10 WebSpeed support in html lexer
11 Support "end triggers" expression of the triggers phrase
12 Support more than 6 comments levels
22 #include "Scintilla.h"
26 #include "LexAccessor.h"
28 #include "StyleContext.h"
29 #include "CharacterSet.h"
30 #include "LexerModule.h"
33 using namespace Scintilla
;
36 static inline bool IsAWordChar(int ch
) {
37 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
40 static inline bool IsAWordStart(int ch
) {
41 return (ch
< 0x80) && (isalpha(ch
) || ch
== '_');
44 enum SentenceStart
{ SetSentenceStart
= 0xf, ResetSentenceStart
= 0x10}; // true -> bit = 0
46 static void Colourise4glDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
49 WordList
&keywords1
= *keywordlists
[0]; // regular keywords
50 WordList
&keywords2
= *keywordlists
[1]; // block opening keywords, only when SentenceStart
51 WordList
&keywords3
= *keywordlists
[2]; // block opening keywords
52 //WordList &keywords4 = *keywordlists[3]; // preprocessor keywords. Not implemented
58 StyleContext
sc(startPos
, length
, initStyle
, styler
);
60 for (; sc
.More(); sc
.Forward()) {
63 // Reset states to begining of colourise so no surprises
64 // if different sets of lines lexed.
68 // Handle line continuation generically.
69 if ((sc
.state
& 0xf) < SCE_4GL_COMMENT1
) {
71 if (sc
.chNext
> ' ') {
72 // skip special char after ~
77 // Skip whitespace between ~ and EOL
78 while (sc
.More() && (sc
.chNext
== ' ' || sc
.chNext
== '\t') ) {
81 if (sc
.chNext
== '\n' || sc
.chNext
== '\r') {
83 if (sc
.ch
== '\r' && sc
.chNext
== '\n') {
92 // Determine if a new state should be terminated.
93 mask
= sc
.state
& 0x10;
94 switch (sc
.state
& 0xf) {
95 case SCE_4GL_OPERATOR
:
96 sc
.SetState(SCE_4GL_DEFAULT
| mask
);
99 if (!(IsADigit(sc
.ch
))) {
100 sc
.SetState(SCE_4GL_DEFAULT
| mask
);
103 case SCE_4GL_IDENTIFIER
:
104 if (!IsAWordChar(sc
.ch
) && sc
.ch
!= '-') {
106 sc
.GetCurrentLowered(s
, sizeof(s
));
107 if ((((sc
.state
& 0x10) == 0) && keywords2
.InList(s
)) || keywords3
.InList(s
)) {
108 sc
.ChangeState(SCE_4GL_BLOCK
| ResetSentenceStart
);
110 else if (keywords1
.InList(s
)) {
111 if ((s
[0] == 'e' && s
[1] =='n' && s
[2] == 'd' && !isalnum(s
[3]) && s
[3] != '-') ||
112 (s
[0] == 'f' && s
[1] =='o' && s
[2] == 'r' && s
[3] == 'w' && s
[4] =='a' && s
[5] == 'r' && s
[6] == 'd'&& !isalnum(s
[7]))) {
113 sc
.ChangeState(SCE_4GL_END
| ResetSentenceStart
);
115 else if ((s
[0] == 'e' && s
[1] =='l' && s
[2] == 's' && s
[3] == 'e') ||
116 (s
[0] == 't' && s
[1] =='h' && s
[2] == 'e' && s
[3] == 'n')) {
117 sc
.ChangeState(SCE_4GL_WORD
& SetSentenceStart
);
120 sc
.ChangeState(SCE_4GL_WORD
| ResetSentenceStart
);
123 sc
.SetState(SCE_4GL_DEFAULT
| (sc
.state
& 0x10));
126 case SCE_4GL_PREPROCESSOR
:
127 if (sc
.atLineStart
) {
128 sc
.SetState(SCE_4GL_DEFAULT
& SetSentenceStart
);
130 /* code removed to allow comments inside preprocessor
131 else if (sc.ch == '*' && sc.chNext == '/') {
132 sc.ForwardSetState(SCE_4GL_DEFAULT | sentenceStartState); } */
136 sc
.ForwardSetState(SCE_4GL_DEFAULT
| mask
);
139 case SCE_4GL_CHARACTER
:
141 sc
.ForwardSetState(SCE_4GL_DEFAULT
| mask
);
145 if ((sc
.state
& 0xf) >= SCE_4GL_COMMENT1
) {
146 if (sc
.ch
== '*' && sc
.chNext
== '/') {
148 if ((sc
.state
& 0xf) == SCE_4GL_COMMENT1
) {
149 sc
.ForwardSetState(SCE_4GL_DEFAULT
| mask
);
152 sc
.SetState((sc
.state
& 0x1f) - 1);
153 } else if (sc
.ch
== '/' && sc
.chNext
== '*') {
155 sc
.SetState((sc
.state
& 0x1f) + 1);
160 // Determine if a new state should be entered.
161 mask
= sc
.state
& 0x10;
162 if ((sc
.state
& 0xf) == SCE_4GL_DEFAULT
) {
163 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
164 sc
.SetState(SCE_4GL_NUMBER
| ResetSentenceStart
);
165 } else if (IsAWordStart(sc
.ch
) || (sc
.ch
== '@')) {
166 sc
.SetState(SCE_4GL_IDENTIFIER
| mask
);
167 } else if (sc
.ch
== '/' && sc
.chNext
== '*') {
168 sc
.SetState(SCE_4GL_COMMENT1
| mask
);
170 } else if (sc
.ch
== '\"') {
171 sc
.SetState(SCE_4GL_STRING
| ResetSentenceStart
);
172 } else if (sc
.ch
== '\'') {
173 sc
.SetState(SCE_4GL_CHARACTER
| ResetSentenceStart
);
174 } else if (sc
.ch
== '&' && visibleChars
== 0 && ((sc
.state
& 0x10) == 0)) {
175 sc
.SetState(SCE_4GL_PREPROCESSOR
| ResetSentenceStart
);
176 // Skip whitespace between & and preprocessor word
179 } while ((sc
.ch
== ' ' || sc
.ch
== '\t') && sc
.More());
180 // Handle syntactical line termination
181 } else if ((sc
.ch
== '.' || sc
.ch
== ':' || sc
.ch
== '}') && (sc
.chNext
== ' ' || sc
.chNext
== '\t' || sc
.chNext
== '\n' || sc
.chNext
== '\r')) {
182 sc
.SetState(sc
.state
& SetSentenceStart
);
183 } else if (isoperator(static_cast<char>(sc
.ch
))) {
184 /* This code allows highlight of handles. Alas, it would cause the phrase "last-event:function"
185 to be recognized as a BlockBegin */
188 sc
.SetState(SCE_4GL_OPERATOR
& SetSentenceStart
);
190 sc
.SetState(SCE_4GL_OPERATOR
| ResetSentenceStart
);
194 if (!IsASpace(sc
.ch
)) {
201 static bool IsStreamCommentStyle(int style
) {
202 return (style
& 0xf) >= SCE_4GL_COMMENT1
;
205 // Store both the current line's fold level and the next lines in the
206 // level store to make it easy to pick up with each increment
207 // and to make it possible to fiddle the current level for "} else {".
208 static void FoldNoBox4glDoc(unsigned int startPos
, int length
, int initStyle
,
210 bool foldComment
= styler
.GetPropertyInt("fold.comment") != 0;
211 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
212 bool foldAtElse
= styler
.GetPropertyInt("fold.at.else", 0) != 0;
213 unsigned int endPos
= startPos
+ length
;
214 int visibleChars
= 0;
215 int lineCurrent
= styler
.GetLine(startPos
);
216 int levelCurrent
= SC_FOLDLEVELBASE
;
218 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
219 int levelMinCurrent
= levelCurrent
;
220 int levelNext
= levelCurrent
;
221 char chNext
= static_cast<char>(tolower(styler
[startPos
]));
222 int styleNext
= styler
.StyleAt(startPos
);
223 int style
= initStyle
;
224 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
226 chNext
= static_cast<char>(tolower(styler
.SafeGetCharAt(i
+ 1)));
227 int stylePrev
= style
;
229 styleNext
= styler
.StyleAt(i
+ 1);
230 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
231 if (foldComment
&& IsStreamCommentStyle(style
)) {
232 if (!IsStreamCommentStyle(stylePrev
)) {
234 } else if (!IsStreamCommentStyle(styleNext
)) { // && !atEOL) {
235 // Comments don't end at end of line and the next character may be unstyled.
239 else if ((style
& 0xf) == SCE_4GL_BLOCK
&& !isalnum(chNext
)) {
242 else if ((style
& 0xf) == SCE_4GL_END
&& (ch
== 'e' || ch
== 'f')) {
246 int levelUse
= levelCurrent
;
248 levelUse
= levelMinCurrent
;
250 int lev
= levelUse
| levelNext
<< 16;
251 if (visibleChars
== 0 && foldCompact
)
252 lev
|= SC_FOLDLEVELWHITEFLAG
;
253 if (levelUse
< levelNext
)
254 lev
|= SC_FOLDLEVELHEADERFLAG
;
255 if (lev
!= styler
.LevelAt(lineCurrent
)) {
256 styler
.SetLevel(lineCurrent
, lev
);
259 levelCurrent
= levelNext
;
260 levelMinCurrent
= levelCurrent
;
263 if (!isspacechar(ch
))
268 static void Fold4glDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*[],
270 FoldNoBox4glDoc(startPos
, length
, initStyle
, styler
);
273 static const char * const FglWordLists
[] = {
274 "Primary keywords and identifiers",
275 "Secondary keywords and identifiers",
276 "Documentation comment keywords",
278 "Global classes and typedefs",
282 LexerModule
lmProgress(SCLEX_PROGRESS
, Colourise4glDoc
, "progress", Fold4glDoc
, FglWordLists
);