]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexPS.cxx
Warning fixes.
[wxWidgets.git] / src / stc / scintilla / src / LexPS.cxx
1 // Scintilla source code edit control
2 /** @file LexPS.cxx
3 ** Lexer for PostScript
4 **
5 ** Written by Nigel Hathaway <nigel@bprj.co.uk>.
6 ** The License.txt file describes the conditions under which this software may be distributed.
7 **/
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdarg.h>
13 #include <stdio.h>
14 #include <fcntl.h>
15
16 #include "Platform.h"
17
18 #include "PropSet.h"
19 #include "Accessor.h"
20 #include "StyleContext.h"
21 #include "KeyWords.h"
22 #include "Scintilla.h"
23 #include "SciLexer.h"
24
25 static inline bool IsASelfDelimitingChar(const int ch) {
26 return (ch == '[' || ch == ']' || ch == '{' || ch == '}' ||
27 ch == '/' || ch == '<' || ch == '>' ||
28 ch == '(' || ch == ')' || ch == '%');
29 }
30
31 static inline bool IsAWhitespaceChar(const int ch) {
32 return (ch == ' ' || ch == '\t' || ch == '\r' ||
33 ch == '\n' || ch == '\f' || ch == '\0');
34 }
35
36 static bool IsABaseNDigit(const int ch, const int base) {
37 int maxdig = '9';
38 int letterext = -1;
39
40 if (base <= 10)
41 maxdig = '0' + base - 1;
42 else
43 letterext = base - 11;
44
45 return ((ch >= '0' && ch <= maxdig) ||
46 (ch >= 'A' && ch <= ('A' + letterext)) ||
47 (ch >= 'a' && ch <= ('a' + letterext)));
48 }
49
50 static inline bool IsABase85Char(const int ch) {
51 return ((ch >= '!' && ch <= 'u') || ch == 'z');
52 }
53
54 static void ColourisePSDoc(
55 unsigned int startPos,
56 int length,
57 int initStyle,
58 WordList *keywordlists[],
59 Accessor &styler) {
60
61 WordList &keywords1 = *keywordlists[0];
62 WordList &keywords2 = *keywordlists[1];
63 WordList &keywords3 = *keywordlists[2];
64 WordList &keywords4 = *keywordlists[3];
65 WordList &keywords5 = *keywordlists[4];
66
67 StyleContext sc(startPos, length, initStyle, styler);
68
69 bool tokenizing = styler.GetPropertyInt("ps.tokenize") != 0;
70 int pslevel = styler.GetPropertyInt("ps.level", 3);
71 int lineCurrent = styler.GetLine(startPos);
72 int nestTextCurrent = 0;
73 if (lineCurrent > 0 && initStyle == SCE_PS_TEXT)
74 nestTextCurrent = styler.GetLineState(lineCurrent - 1);
75 int numRadix = 0;
76 bool numHasPoint = false;
77 bool numHasExponent = false;
78 bool numHasSign = false;
79
80 // Clear out existing tokenization
81 if (tokenizing && length > 0) {
82 styler.StartAt(startPos, static_cast<char>(INDIC2_MASK));
83 styler.ColourTo(startPos + length-1, 0);
84 styler.Flush();
85 styler.StartAt(startPos);
86 styler.StartSegment(startPos);
87 }
88
89 for (; sc.More(); sc.Forward()) {
90 if (sc.atLineStart)
91 lineCurrent = styler.GetLine(sc.currentPos);
92
93 // Determine if the current state should terminate.
94 if (sc.state == SCE_PS_COMMENT || sc.state == SCE_PS_DSC_VALUE) {
95 if (sc.atLineEnd) {
96 sc.SetState(SCE_C_DEFAULT);
97 }
98 } else if (sc.state == SCE_PS_DSC_COMMENT) {
99 if (sc.ch == ':') {
100 sc.Forward();
101 if (!sc.atLineEnd)
102 sc.SetState(SCE_PS_DSC_VALUE);
103 else
104 sc.SetState(SCE_C_DEFAULT);
105 } else if (sc.atLineEnd) {
106 sc.SetState(SCE_C_DEFAULT);
107 } else if (IsAWhitespaceChar(sc.ch)) {
108 sc.ChangeState(SCE_PS_COMMENT);
109 }
110 } else if (sc.state == SCE_PS_NUMBER) {
111 if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
112 if ((sc.chPrev == '+' || sc.chPrev == '-' ||
113 sc.chPrev == 'E' || sc.chPrev == 'e') && numRadix == 0)
114 sc.ChangeState(SCE_PS_NAME);
115 sc.SetState(SCE_C_DEFAULT);
116 } else if (sc.ch == '#') {
117 if (numHasPoint || numHasExponent || numHasSign || numRadix != 0) {
118 sc.ChangeState(SCE_PS_NAME);
119 } else {
120 char szradix[5];
121 sc.GetCurrent(szradix, 4);
122 numRadix = atoi(szradix);
123 if (numRadix < 2 || numRadix > 36)
124 sc.ChangeState(SCE_PS_NAME);
125 }
126 } else if ((sc.ch == 'E' || sc.ch == 'e') && numRadix == 0) {
127 if (numHasExponent) {
128 sc.ChangeState(SCE_PS_NAME);
129 } else {
130 numHasExponent = true;
131 if (sc.chNext == '+' || sc.chNext == '-')
132 sc.Forward();
133 }
134 } else if (sc.ch == '.') {
135 if (numHasPoint || numHasExponent || numRadix != 0) {
136 sc.ChangeState(SCE_PS_NAME);
137 } else {
138 numHasPoint = true;
139 }
140 } else if (numRadix == 0) {
141 if (!IsABaseNDigit(sc.ch, 10))
142 sc.ChangeState(SCE_PS_NAME);
143 } else {
144 if (!IsABaseNDigit(sc.ch, numRadix))
145 sc.ChangeState(SCE_PS_NAME);
146 }
147 } else if (sc.state == SCE_PS_NAME || sc.state == SCE_PS_KEYWORD) {
148 if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
149 char s[100];
150 sc.GetCurrent(s, sizeof(s));
151 if ((pslevel >= 1 && keywords1.InList(s)) ||
152 (pslevel >= 2 && keywords2.InList(s)) ||
153 (pslevel >= 3 && keywords3.InList(s)) ||
154 keywords4.InList(s) || keywords5.InList(s)) {
155 sc.ChangeState(SCE_PS_KEYWORD);
156 }
157 sc.SetState(SCE_C_DEFAULT);
158 }
159 } else if (sc.state == SCE_PS_LITERAL || sc.state == SCE_PS_IMMEVAL) {
160 if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch))
161 sc.SetState(SCE_C_DEFAULT);
162 } else if (sc.state == SCE_PS_PAREN_ARRAY || sc.state == SCE_PS_PAREN_DICT ||
163 sc.state == SCE_PS_PAREN_PROC) {
164 sc.SetState(SCE_C_DEFAULT);
165 } else if (sc.state == SCE_PS_TEXT) {
166 if (sc.ch == '(') {
167 nestTextCurrent++;
168 } else if (sc.ch == ')') {
169 if (--nestTextCurrent == 0)
170 sc.ForwardSetState(SCE_PS_DEFAULT);
171 } else if (sc.ch == '\\') {
172 sc.Forward();
173 }
174 } else if (sc.state == SCE_PS_HEXSTRING) {
175 if (sc.ch == '>') {
176 sc.ForwardSetState(SCE_PS_DEFAULT);
177 } else if (!IsABaseNDigit(sc.ch, 16) && !IsAWhitespaceChar(sc.ch)) {
178 sc.SetState(SCE_PS_HEXSTRING);
179 styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
180 }
181 } else if (sc.state == SCE_PS_BASE85STRING) {
182 if (sc.Match('~', '>')) {
183 sc.Forward();
184 sc.ForwardSetState(SCE_PS_DEFAULT);
185 } else if (!IsABase85Char(sc.ch) && !IsAWhitespaceChar(sc.ch)) {
186 sc.SetState(SCE_PS_BASE85STRING);
187 styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
188 }
189 }
190
191 // Determine if a new state should be entered.
192 if (sc.state == SCE_C_DEFAULT) {
193 unsigned int tokenpos = sc.currentPos;
194
195 if (sc.ch == '[' || sc.ch == ']') {
196 sc.SetState(SCE_PS_PAREN_ARRAY);
197 } else if (sc.ch == '{' || sc.ch == '}') {
198 sc.SetState(SCE_PS_PAREN_PROC);
199 } else if (sc.ch == '/') {
200 if (sc.chNext == '/') {
201 sc.SetState(SCE_PS_IMMEVAL);
202 sc.Forward();
203 } else {
204 sc.SetState(SCE_PS_LITERAL);
205 }
206 } else if (sc.ch == '<') {
207 if (sc.chNext == '<') {
208 sc.SetState(SCE_PS_PAREN_DICT);
209 sc.Forward();
210 } else if (sc.chNext == '~') {
211 sc.SetState(SCE_PS_BASE85STRING);
212 sc.Forward();
213 } else {
214 sc.SetState(SCE_PS_HEXSTRING);
215 }
216 } else if (sc.ch == '>' && sc.chNext == '>') {
217 sc.SetState(SCE_PS_PAREN_DICT);
218 sc.Forward();
219 } else if (sc.ch == '>' || sc.ch == ')') {
220 sc.SetState(SCE_C_DEFAULT);
221 styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
222 } else if (sc.ch == '(') {
223 sc.SetState(SCE_PS_TEXT);
224 nestTextCurrent = 1;
225 } else if (sc.ch == '%') {
226 if (sc.chNext == '%' && sc.atLineStart) {
227 sc.SetState(SCE_PS_DSC_COMMENT);
228 sc.Forward();
229 if (sc.chNext == '+') {
230 sc.Forward();
231 sc.ForwardSetState(SCE_PS_DSC_VALUE);
232 }
233 } else {
234 sc.SetState(SCE_PS_COMMENT);
235 }
236 } else if ((sc.ch == '+' || sc.ch == '-' || sc.ch == '.') &&
237 IsABaseNDigit(sc.chNext, 10)) {
238 sc.SetState(SCE_PS_NUMBER);
239 numRadix = 0;
240 numHasPoint = (sc.ch == '.');
241 numHasExponent = false;
242 numHasSign = (sc.ch == '+' || sc.ch == '-');
243 } else if ((sc.ch == '+' || sc.ch == '-') && sc.chNext == '.' &&
244 IsABaseNDigit(sc.GetRelative(2), 10)) {
245 sc.SetState(SCE_PS_NUMBER);
246 numRadix = 0;
247 numHasPoint = false;
248 numHasExponent = false;
249 numHasSign = true;
250 } else if (IsABaseNDigit(sc.ch, 10)) {
251 sc.SetState(SCE_PS_NUMBER);
252 numRadix = 0;
253 numHasPoint = false;
254 numHasExponent = false;
255 numHasSign = false;
256 } else if (!IsAWhitespaceChar(sc.ch)) {
257 sc.SetState(SCE_PS_NAME);
258 }
259
260 // Mark the start of tokens
261 if (tokenizing && sc.state != SCE_C_DEFAULT && sc.state != SCE_PS_COMMENT &&
262 sc.state != SCE_PS_DSC_COMMENT && sc.state != SCE_PS_DSC_VALUE) {
263 styler.Flush();
264 styler.StartAt(tokenpos, static_cast<char>(INDIC2_MASK));
265 styler.ColourTo(tokenpos, INDIC2_MASK);
266 styler.Flush();
267 styler.StartAt(tokenpos);
268 styler.StartSegment(tokenpos);
269 }
270 }
271
272 if (sc.atLineEnd)
273 styler.SetLineState(lineCurrent, nestTextCurrent);
274 }
275
276 sc.Complete();
277 }
278
279 static void FoldPSDoc(unsigned int startPos, int length, int, WordList *[],
280 Accessor &styler) {
281 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
282 bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
283 unsigned int endPos = startPos + length;
284 int visibleChars = 0;
285 int lineCurrent = styler.GetLine(startPos);
286 int levelCurrent = SC_FOLDLEVELBASE;
287 if (lineCurrent > 0)
288 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
289 int levelMinCurrent = levelCurrent;
290 int levelNext = levelCurrent;
291 char chNext = styler[startPos];
292 int styleNext = styler.StyleAt(startPos);
293 int style;
294 for (unsigned int i = startPos; i < endPos; i++) {
295 char ch = chNext;
296 chNext = styler.SafeGetCharAt(i + 1);
297 style = styleNext;
298 styleNext = styler.StyleAt(i + 1);
299 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); //mac??
300 if ((style & 31) == SCE_PS_PAREN_PROC) {
301 if (ch == '{') {
302 // Measure the minimum before a '{' to allow
303 // folding on "} {"
304 if (levelMinCurrent > levelNext) {
305 levelMinCurrent = levelNext;
306 }
307 levelNext++;
308 } else if (ch == '}') {
309 levelNext--;
310 }
311 }
312 if (atEOL) {
313 int levelUse = levelCurrent;
314 if (foldAtElse) {
315 levelUse = levelMinCurrent;
316 }
317 int lev = levelUse | levelNext << 16;
318 if (visibleChars == 0 && foldCompact)
319 lev |= SC_FOLDLEVELWHITEFLAG;
320 if (levelUse < levelNext)
321 lev |= SC_FOLDLEVELHEADERFLAG;
322 if (lev != styler.LevelAt(lineCurrent)) {
323 styler.SetLevel(lineCurrent, lev);
324 }
325 lineCurrent++;
326 levelCurrent = levelNext;
327 levelMinCurrent = levelCurrent;
328 visibleChars = 0;
329 }
330 if (!isspacechar(ch))
331 visibleChars++;
332 }
333 }
334
335 static const char * const psWordListDesc[] = {
336 "PS Level 1 operators",
337 "PS Level 2 operators",
338 "PS Level 3 operators",
339 "RIP-specific operators",
340 "User-defined operators",
341 0
342 };
343
344 LexerModule lmPS(SCLEX_PS, ColourisePSDoc, "ps", FoldPSDoc, psWordListDesc);