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