]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/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
24 #include "StyleContext.h"
26 #include "Scintilla.h"
30 using namespace Scintilla
;
33 static inline bool IsAWordChar(int ch
) {
34 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
37 static inline bool IsAWordStart(int ch
) {
38 return (ch
< 0x80) && (isalpha(ch
) || ch
== '_');
41 enum SentenceStart
{ SetSentenceStart
= 0xf, ResetSentenceStart
= 0x10}; // true -> bit = 0
43 static void Colourise4glDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
46 WordList
&keywords1
= *keywordlists
[0]; // regular keywords
47 WordList
&keywords2
= *keywordlists
[1]; // block opening keywords, only when SentenceStart
48 WordList
&keywords3
= *keywordlists
[2]; // block opening keywords
49 //WordList &keywords4 = *keywordlists[3]; // preprocessor keywords. Not implemented
55 StyleContext
sc(startPos
, length
, initStyle
, styler
);
57 for (; sc
.More(); sc
.Forward()) {
60 // Reset states to begining of colourise so no surprises
61 // if different sets of lines lexed.
65 // Handle line continuation generically.
66 if ((sc
.state
& 0xf) < SCE_4GL_COMMENT1
) {
68 if (sc
.chNext
> ' ') {
69 // skip special char after ~
74 // Skip whitespace between ~ and EOL
75 while (sc
.More() && (sc
.chNext
== ' ' || sc
.chNext
== '\t') ) {
78 if (sc
.chNext
== '\n' || sc
.chNext
== '\r') {
80 if (sc
.ch
== '\r' && sc
.chNext
== '\n') {
89 // Determine if a new state should be terminated.
90 mask
= sc
.state
& 0x10;
91 switch (sc
.state
& 0xf) {
92 case SCE_4GL_OPERATOR
:
93 sc
.SetState(SCE_4GL_DEFAULT
| mask
);
96 if (!(IsADigit(sc
.ch
))) {
97 sc
.SetState(SCE_4GL_DEFAULT
| mask
);
100 case SCE_4GL_IDENTIFIER
:
101 if (!IsAWordChar(sc
.ch
) && sc
.ch
!= '-') {
103 sc
.GetCurrentLowered(s
, sizeof(s
));
104 if ((((sc
.state
& 0x10) == 0) && keywords2
.InList(s
)) || keywords3
.InList(s
)) {
105 sc
.ChangeState(SCE_4GL_BLOCK
| ResetSentenceStart
);
107 else if (keywords1
.InList(s
)) {
108 if ((s
[0] == 'e' && s
[1] =='n' && s
[2] == 'd' && !isalnum(s
[3]) && s
[3] != '-') ||
109 (s
[0] == 'f' && s
[1] =='o' && s
[2] == 'r' && s
[3] == 'w' && s
[4] =='a' && s
[5] == 'r' && s
[6] == 'd'&& !isalnum(s
[7]))) {
110 sc
.ChangeState(SCE_4GL_END
| ResetSentenceStart
);
112 else if ((s
[0] == 'e' && s
[1] =='l' && s
[2] == 's' && s
[3] == 'e') ||
113 (s
[0] == 't' && s
[1] =='h' && s
[2] == 'e' && s
[3] == 'n')) {
114 sc
.ChangeState(SCE_4GL_WORD
& SetSentenceStart
);
117 sc
.ChangeState(SCE_4GL_WORD
| ResetSentenceStart
);
120 sc
.SetState(SCE_4GL_DEFAULT
| (sc
.state
& 0x10));
123 case SCE_4GL_PREPROCESSOR
:
124 if (sc
.atLineStart
) {
125 sc
.SetState(SCE_4GL_DEFAULT
& SetSentenceStart
);
127 /* code removed to allow comments inside preprocessor
128 else if (sc.ch == '*' && sc.chNext == '/') {
129 sc.ForwardSetState(SCE_4GL_DEFAULT | sentenceStartState); } */
133 sc
.ForwardSetState(SCE_4GL_DEFAULT
| mask
);
136 case SCE_4GL_CHARACTER
:
138 sc
.ForwardSetState(SCE_4GL_DEFAULT
| mask
);
142 if ((sc
.state
& 0xf) >= SCE_4GL_COMMENT1
) {
143 if (sc
.ch
== '*' && sc
.chNext
== '/') {
145 if ((sc
.state
& 0xf) == SCE_4GL_COMMENT1
) {
146 sc
.ForwardSetState(SCE_4GL_DEFAULT
| mask
);
149 sc
.SetState((sc
.state
& 0x1f) - 1);
150 } else if (sc
.ch
== '/' && sc
.chNext
== '*') {
152 sc
.SetState((sc
.state
& 0x1f) + 1);
157 // Determine if a new state should be entered.
158 mask
= sc
.state
& 0x10;
159 if ((sc
.state
& 0xf) == SCE_4GL_DEFAULT
) {
160 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
161 sc
.SetState(SCE_4GL_NUMBER
| ResetSentenceStart
);
162 } else if (IsAWordStart(sc
.ch
) || (sc
.ch
== '@')) {
163 sc
.SetState(SCE_4GL_IDENTIFIER
| mask
);
164 } else if (sc
.ch
== '/' && sc
.chNext
== '*') {
165 sc
.SetState(SCE_4GL_COMMENT1
| mask
);
167 } else if (sc
.ch
== '\"') {
168 sc
.SetState(SCE_4GL_STRING
| ResetSentenceStart
);
169 } else if (sc
.ch
== '\'') {
170 sc
.SetState(SCE_4GL_CHARACTER
| ResetSentenceStart
);
171 } else if (sc
.ch
== '&' && visibleChars
== 0 && ((sc
.state
& 0x10) == 0)) {
172 sc
.SetState(SCE_4GL_PREPROCESSOR
| ResetSentenceStart
);
173 // Skip whitespace between & and preprocessor word
176 } while ((sc
.ch
== ' ' || sc
.ch
== '\t') && sc
.More());
177 // Handle syntactical line termination
178 } else if ((sc
.ch
== '.' || sc
.ch
== ':' || sc
.ch
== '}') && (sc
.chNext
== ' ' || sc
.chNext
== '\t' || sc
.chNext
== '\n' || sc
.chNext
== '\r')) {
179 sc
.SetState(sc
.state
& SetSentenceStart
);
180 } else if (isoperator(static_cast<char>(sc
.ch
))) {
181 /* This code allows highlight of handles. Alas, it would cause the phrase "last-event:function"
182 to be recognized as a BlockBegin */
185 sc
.SetState(SCE_4GL_OPERATOR
& SetSentenceStart
);
187 sc
.SetState(SCE_4GL_OPERATOR
| ResetSentenceStart
);
191 if (!IsASpace(sc
.ch
)) {
198 static bool IsStreamCommentStyle(int style
) {
199 return (style
& 0xf) >= SCE_4GL_COMMENT1
;
202 // Store both the current line's fold level and the next lines in the
203 // level store to make it easy to pick up with each increment
204 // and to make it possible to fiddle the current level for "} else {".
205 static void FoldNoBox4glDoc(unsigned int startPos
, int length
, int initStyle
,
207 bool foldComment
= styler
.GetPropertyInt("fold.comment") != 0;
208 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
209 bool foldAtElse
= styler
.GetPropertyInt("fold.at.else", 0) != 0;
210 unsigned int endPos
= startPos
+ length
;
211 int visibleChars
= 0;
212 int lineCurrent
= styler
.GetLine(startPos
);
213 int levelCurrent
= SC_FOLDLEVELBASE
;
215 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
216 int levelMinCurrent
= levelCurrent
;
217 int levelNext
= levelCurrent
;
218 char chNext
= static_cast<char>(tolower(styler
[startPos
]));
219 int styleNext
= styler
.StyleAt(startPos
);
220 int style
= initStyle
;
221 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
223 chNext
= static_cast<char>(tolower(styler
.SafeGetCharAt(i
+ 1)));
224 int stylePrev
= style
;
226 styleNext
= styler
.StyleAt(i
+ 1);
227 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
228 if (foldComment
&& IsStreamCommentStyle(style
)) {
229 if (!IsStreamCommentStyle(stylePrev
)) {
231 } else if (!IsStreamCommentStyle(styleNext
)) { // && !atEOL) {
232 // Comments don't end at end of line and the next character may be unstyled.
236 else if ((style
& 0xf) == SCE_4GL_BLOCK
&& !isalnum(chNext
)) {
239 else if ((style
& 0xf) == SCE_4GL_END
&& (ch
== 'e' || ch
== 'f')) {
243 int levelUse
= levelCurrent
;
245 levelUse
= levelMinCurrent
;
247 int lev
= levelUse
| levelNext
<< 16;
248 if (visibleChars
== 0 && foldCompact
)
249 lev
|= SC_FOLDLEVELWHITEFLAG
;
250 if (levelUse
< levelNext
)
251 lev
|= SC_FOLDLEVELHEADERFLAG
;
252 if (lev
!= styler
.LevelAt(lineCurrent
)) {
253 styler
.SetLevel(lineCurrent
, lev
);
256 levelCurrent
= levelNext
;
257 levelMinCurrent
= levelCurrent
;
260 if (!isspacechar(ch
))
265 static void Fold4glDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*[],
267 FoldNoBox4glDoc(startPos
, length
, initStyle
, styler
);
270 static const char * const FglWordLists
[] = {
271 "Primary keywords and identifiers",
272 "Secondary keywords and identifiers",
273 "Documentation comment keywords",
275 "Global classes and typedefs",
279 LexerModule
lmProgress(SCLEX_PROGRESS
, Colourise4glDoc
, "progress", Fold4glDoc
, FglWordLists
);