]> git.saurik.com Git - wxWidgets.git/blame - src/stc/scintilla/src/LexProgress.cxx
Update Scintilla to version 1.75
[wxWidgets.git] / src / stc / scintilla / src / LexProgress.cxx
CommitLineData
7e0c58e9
RD
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>
5 **/
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.
8
9/** TODO:
10WebSpeed support in html lexer
11Support "end triggers" expression of the triggers phrase
12change lmPS to lmProgress
13Support more than 6 comments levels
14**/
15#include <stdlib.h>
16#include <string.h>
17#include <ctype.h>
18#include <stdio.h>
19#include <stdarg.h>
20
21#include "Platform.h"
22
23#include "PropSet.h"
24#include "Accessor.h"
25#include "StyleContext.h"
26#include "KeyWords.h"
27#include "Scintilla.h"
28#include "SciLexer.h"
29
30#ifdef SCI_NAMESPACE
31using namespace Scintilla;
32#endif
33
34static inline bool IsAWordChar(int ch) {
35 return (ch < 0x80) && (isalnum(ch) || ch == '_');
36}
37
38static inline bool IsAWordStart(int ch) {
39 return (ch < 0x80) && (isalpha(ch) || ch == '_');
40}
41
42enum SentenceStart { SetSentenceStart = 0xf, ResetSentenceStart = 0x10}; // true -> bit = 0
43
44static void Colourise4glDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
45 Accessor &styler) {
46
47 WordList &keywords1 = *keywordlists[0];
48 WordList &keywords2 = *keywordlists[1];
49 WordList &keywords3 = *keywordlists[2];
50 //WordList &keywords4 = *keywordlists[3];
51 //WordList &keywords5 = *keywordlists[4];
52
53 int visibleChars = 0;
54 int mask;
55
56 StyleContext sc(startPos, length, initStyle, styler);
57
58 for (; sc.More(); sc.Forward()) {
59
60 if (sc.atLineStart) {
61 // Reset states to begining of colourise so no surprises
62 // if different sets of lines lexed.
63 visibleChars = 0;
64 }
65
66 // Handle line continuation generically.
67 if (sc.ch == '~') {
68 // Skip whitespace between ~ and EOL
69 /* do {
70 sc.Forward();
71 } */
72 while ((sc.chNext == ' ' || sc.chNext == '\t') ) {
73 sc.Forward();
74 sc.More();
75 }
76 if (sc.chNext == '\n' || sc.chNext == '\r') {
77 sc.Forward();
78 if (sc.ch == '\r' && sc.chNext == '\n') {
79 sc.Forward();
80 }
81 sc.Forward();
82 continue;
83 }
84 }
85 // Determine if a new state should be terminated.
86 mask = sc.state & 0x10;
87 switch (sc.state & 0xf) {
88 case SCE_4GL_OPERATOR:
89 sc.SetState(SCE_4GL_DEFAULT | mask);
90 break;
91 case SCE_4GL_NUMBER:
92 if (!(IsADigit(sc.ch))) {
93 sc.SetState(SCE_4GL_DEFAULT | mask);
94 }
95 break;
96 case SCE_4GL_IDENTIFIER:
97 if (!IsAWordChar(sc.ch) && sc.ch != '-') {
98 char s[1000];
99 sc.GetCurrentLowered(s, sizeof(s));
100 if (((sc.state & 0x10) == 0) && keywords2.InList(s) || keywords3.InList(s)) {
101 sc.ChangeState(SCE_4GL_BLOCK | ResetSentenceStart);
102 }
103 else if (keywords1.InList(s)) {
104 if ((s[0] == 'e' && s[1] =='n' && s[2] == 'd' && !isalnum(s[3]) && s[3] != '-') ||
105 (s[0] == 'f' && s[1] =='o' && s[2] == 'r' && s[3] == 'w' && s[4] =='a' && s[5] == 'r' && s[6] == 'd'&& !isalnum(s[7]))) {
106 sc.ChangeState(SCE_4GL_END | ResetSentenceStart);
107 }
108 else if ((s[0] == 'e' && s[1] =='l' && s[2] == 's' && s[3] == 'e') ||
109 (s[0] == 't' && s[1] =='h' && s[2] == 'e' && s[3] == 'n')) {
110 sc.ChangeState(SCE_4GL_WORD & SetSentenceStart);
111 }
112 else {
113 sc.ChangeState(SCE_4GL_WORD | ResetSentenceStart);
114 }
115 }
116 sc.SetState(SCE_4GL_DEFAULT | (sc.state & 0x10));
117 }
118 break;
119 case SCE_4GL_PREPROCESSOR:
120 if (sc.atLineStart) {
121 sc.SetState(SCE_4GL_DEFAULT & SetSentenceStart);
122 } else if (sc.ch == '*' && sc.chNext == '/') {
123 sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
124 }
125 break;
126 case SCE_4GL_STRING:
127 if (sc.ch == '\"') {
128 sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
129 }
130 break;
131 case SCE_4GL_CHARACTER:
132 if (sc.ch == '\'') {
133 sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
134 }
135 break;
136 default:
137 if ((sc.state & 0xf) >= SCE_4GL_COMMENT1) {
138 if (sc.ch == '*' && sc.chNext == '/') {
139 sc.Forward();
140 if ((sc.state & 0xf) == SCE_4GL_COMMENT1) {
141 sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
142 }
143 else
144 sc.SetState((sc.state & 0x1f) - 1);
145 } else if (sc.ch == '/' && sc.chNext == '*') {
146 sc.Forward();
147 sc.SetState((sc.state & 0x1f) + 1);
148 }
149 }
150 }
151
152 // Determine if a new state should be entered.
153 mask = sc.state & 0x10;
154 if ((sc.state & 0xf) == SCE_4GL_DEFAULT) {
155 if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
156 sc.SetState(SCE_4GL_NUMBER | ResetSentenceStart);
157 } else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
158 sc.SetState(SCE_4GL_IDENTIFIER | mask);
159 } else if (sc.ch == '/' && sc.chNext == '*') {
160 sc.SetState(SCE_4GL_COMMENT1 | mask);
161 sc.Forward();
162 } else if (sc.ch == '\"') {
163 sc.SetState(SCE_4GL_STRING | ResetSentenceStart);
164 } else if (sc.ch == '\'') {
165 sc.SetState(SCE_4GL_CHARACTER | ResetSentenceStart);
166 } else if (sc.ch == '&' && visibleChars == 0 && ((sc.state & 0x10) == 0)) {
167 sc.SetState(SCE_4GL_PREPROCESSOR | ResetSentenceStart);
168 // Skip whitespace between & and preprocessor word
169 do {
170 sc.Forward();
171 } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
172 // Handle syntactical line termination
173 } else if ((sc.ch == '.' || sc.ch == ':' || sc.ch == '}') && (sc.chNext == ' ' || sc.chNext == '\t' || sc.chNext == '\n' || sc.chNext == '\r')) {
174 sc.SetState(sc.state & SetSentenceStart);
175 } else if (isoperator(static_cast<char>(sc.ch))) {
176 if (sc.ch == ':')
177 sc.SetState(SCE_4GL_OPERATOR & SetSentenceStart);
178 else
179 sc.SetState(SCE_4GL_OPERATOR | ResetSentenceStart);
180 }
181 }
182
183 if (!IsASpace(sc.ch)) {
184 visibleChars++;
185 }
186 }
187 sc.Complete();
188}
189
190static bool IsStreamCommentStyle(int style) {
191 return (style & 0xf) >= SCE_4GL_COMMENT1 ;
192}
193
194// Store both the current line's fold level and the next lines in the
195// level store to make it easy to pick up with each increment
196// and to make it possible to fiddle the current level for "} else {".
197static void FoldNoBox4glDoc(unsigned int startPos, int length, int initStyle,
198 Accessor &styler) {
199 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
200 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
201 bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
202 unsigned int endPos = startPos + length;
203 int visibleChars = 0;
204 int lineCurrent = styler.GetLine(startPos);
205 int levelCurrent = SC_FOLDLEVELBASE;
206 if (lineCurrent > 0)
207 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
208 int levelMinCurrent = levelCurrent;
209 int levelNext = levelCurrent;
210 char chNext = static_cast<char>(tolower(styler[startPos]));
211 int styleNext = styler.StyleAt(startPos);
212 int style = initStyle;
213 for (unsigned int i = startPos; i < endPos; i++) {
214 char ch = chNext;
215 chNext = static_cast<char>(tolower(styler.SafeGetCharAt(i + 1)));
216 int stylePrev = style;
217 style = styleNext;
218 styleNext = styler.StyleAt(i + 1);
219 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
220 if (foldComment && IsStreamCommentStyle(style)) {
221 if (!IsStreamCommentStyle(stylePrev)) {
222 levelNext++;
223 } else if (!IsStreamCommentStyle(styleNext)) { // && !atEOL) {
224 // Comments don't end at end of line and the next character may be unstyled.
225 levelNext--;
226 }
227 }
228 else if ((style & 0xf) == SCE_4GL_BLOCK && !isalnum(chNext)) {
229 levelNext++;
230 }
231 else if ((style & 0xf) == SCE_4GL_END && (ch == 'e' || ch == 'f')) {
232 levelNext--;
233 }
234 if (atEOL) {
235 int levelUse = levelCurrent;
236 if (foldAtElse) {
237 levelUse = levelMinCurrent;
238 }
239 int lev = levelUse | levelNext << 16;
240 if (visibleChars == 0 && foldCompact)
241 lev |= SC_FOLDLEVELWHITEFLAG;
242 if (levelUse < levelNext)
243 lev |= SC_FOLDLEVELHEADERFLAG;
244 if (lev != styler.LevelAt(lineCurrent)) {
245 styler.SetLevel(lineCurrent, lev);
246 }
247 lineCurrent++;
248 levelCurrent = levelNext;
249 levelMinCurrent = levelCurrent;
250 visibleChars = 0;
251 }
252 if (!isspacechar(ch))
253 visibleChars++;
254 }
255}
256
257static void Fold4glDoc(unsigned int startPos, int length, int initStyle, WordList *[],
258 Accessor &styler) {
259 FoldNoBox4glDoc(startPos, length, initStyle, styler);
260}
261
262static const char * const FglWordLists[] = {
263 "Primary keywords and identifiers",
264 "Secondary keywords and identifiers",
265 "Documentation comment keywords",
266 "Unused",
267 "Global classes and typedefs",
268 0,
269 };
270
271LexerModule lmProgress(SCLEX_PS, Colourise4glDoc, "progress", Fold4glDoc, FglWordLists);