]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexPS.cxx
1 // Scintilla source code edit control
3 ** Lexer for PostScript
5 ** Written by Nigel Hathaway <nigel@bprj.co.uk>.
6 ** The License.txt file describes the conditions under which this software may be distributed.
17 #include "Scintilla.h"
21 #include "LexAccessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
28 using namespace Scintilla
;
31 static inline bool IsASelfDelimitingChar(const int ch
) {
32 return (ch
== '[' || ch
== ']' || ch
== '{' || ch
== '}' ||
33 ch
== '/' || ch
== '<' || ch
== '>' ||
34 ch
== '(' || ch
== ')' || ch
== '%');
37 static inline bool IsAWhitespaceChar(const int ch
) {
38 return (ch
== ' ' || ch
== '\t' || ch
== '\r' ||
39 ch
== '\n' || ch
== '\f' || ch
== '\0');
42 static bool IsABaseNDigit(const int ch
, const int base
) {
47 maxdig
= '0' + base
- 1;
49 letterext
= base
- 11;
51 return ((ch
>= '0' && ch
<= maxdig
) ||
52 (ch
>= 'A' && ch
<= ('A' + letterext
)) ||
53 (ch
>= 'a' && ch
<= ('a' + letterext
)));
56 static inline bool IsABase85Char(const int ch
) {
57 return ((ch
>= '!' && ch
<= 'u') || ch
== 'z');
60 static void ColourisePSDoc(
61 unsigned int startPos
,
64 WordList
*keywordlists
[],
67 WordList
&keywords1
= *keywordlists
[0];
68 WordList
&keywords2
= *keywordlists
[1];
69 WordList
&keywords3
= *keywordlists
[2];
70 WordList
&keywords4
= *keywordlists
[3];
71 WordList
&keywords5
= *keywordlists
[4];
73 StyleContext
sc(startPos
, length
, initStyle
, styler
);
75 bool tokenizing
= styler
.GetPropertyInt("ps.tokenize") != 0;
76 int pslevel
= styler
.GetPropertyInt("ps.level", 3);
77 int lineCurrent
= styler
.GetLine(startPos
);
78 int nestTextCurrent
= 0;
79 if (lineCurrent
> 0 && initStyle
== SCE_PS_TEXT
)
80 nestTextCurrent
= styler
.GetLineState(lineCurrent
- 1);
82 bool numHasPoint
= false;
83 bool numHasExponent
= false;
84 bool numHasSign
= false;
86 // Clear out existing tokenization
87 if (tokenizing
&& length
> 0) {
88 styler
.StartAt(startPos
, static_cast<char>(INDIC2_MASK
));
89 styler
.ColourTo(startPos
+ length
-1, 0);
91 styler
.StartAt(startPos
);
92 styler
.StartSegment(startPos
);
95 for (; sc
.More(); sc
.Forward()) {
97 lineCurrent
= styler
.GetLine(sc
.currentPos
);
99 // Determine if the current state should terminate.
100 if (sc
.state
== SCE_PS_COMMENT
|| sc
.state
== SCE_PS_DSC_VALUE
) {
102 sc
.SetState(SCE_C_DEFAULT
);
104 } else if (sc
.state
== SCE_PS_DSC_COMMENT
) {
108 sc
.SetState(SCE_PS_DSC_VALUE
);
110 sc
.SetState(SCE_C_DEFAULT
);
111 } else if (sc
.atLineEnd
) {
112 sc
.SetState(SCE_C_DEFAULT
);
113 } else if (IsAWhitespaceChar(sc
.ch
) && sc
.ch
!= '\r') {
114 sc
.ChangeState(SCE_PS_COMMENT
);
116 } else if (sc
.state
== SCE_PS_NUMBER
) {
117 if (IsASelfDelimitingChar(sc
.ch
) || IsAWhitespaceChar(sc
.ch
)) {
118 if ((sc
.chPrev
== '+' || sc
.chPrev
== '-' ||
119 sc
.chPrev
== 'E' || sc
.chPrev
== 'e') && numRadix
== 0)
120 sc
.ChangeState(SCE_PS_NAME
);
121 sc
.SetState(SCE_C_DEFAULT
);
122 } else if (sc
.ch
== '#') {
123 if (numHasPoint
|| numHasExponent
|| numHasSign
|| numRadix
!= 0) {
124 sc
.ChangeState(SCE_PS_NAME
);
127 sc
.GetCurrent(szradix
, 4);
128 numRadix
= atoi(szradix
);
129 if (numRadix
< 2 || numRadix
> 36)
130 sc
.ChangeState(SCE_PS_NAME
);
132 } else if ((sc
.ch
== 'E' || sc
.ch
== 'e') && numRadix
== 0) {
133 if (numHasExponent
) {
134 sc
.ChangeState(SCE_PS_NAME
);
136 numHasExponent
= true;
137 if (sc
.chNext
== '+' || sc
.chNext
== '-')
140 } else if (sc
.ch
== '.') {
141 if (numHasPoint
|| numHasExponent
|| numRadix
!= 0) {
142 sc
.ChangeState(SCE_PS_NAME
);
146 } else if (numRadix
== 0) {
147 if (!IsABaseNDigit(sc
.ch
, 10))
148 sc
.ChangeState(SCE_PS_NAME
);
150 if (!IsABaseNDigit(sc
.ch
, numRadix
))
151 sc
.ChangeState(SCE_PS_NAME
);
153 } else if (sc
.state
== SCE_PS_NAME
|| sc
.state
== SCE_PS_KEYWORD
) {
154 if (IsASelfDelimitingChar(sc
.ch
) || IsAWhitespaceChar(sc
.ch
)) {
156 sc
.GetCurrent(s
, sizeof(s
));
157 if ((pslevel
>= 1 && keywords1
.InList(s
)) ||
158 (pslevel
>= 2 && keywords2
.InList(s
)) ||
159 (pslevel
>= 3 && keywords3
.InList(s
)) ||
160 keywords4
.InList(s
) || keywords5
.InList(s
)) {
161 sc
.ChangeState(SCE_PS_KEYWORD
);
163 sc
.SetState(SCE_C_DEFAULT
);
165 } else if (sc
.state
== SCE_PS_LITERAL
|| sc
.state
== SCE_PS_IMMEVAL
) {
166 if (IsASelfDelimitingChar(sc
.ch
) || IsAWhitespaceChar(sc
.ch
))
167 sc
.SetState(SCE_C_DEFAULT
);
168 } else if (sc
.state
== SCE_PS_PAREN_ARRAY
|| sc
.state
== SCE_PS_PAREN_DICT
||
169 sc
.state
== SCE_PS_PAREN_PROC
) {
170 sc
.SetState(SCE_C_DEFAULT
);
171 } else if (sc
.state
== SCE_PS_TEXT
) {
174 } else if (sc
.ch
== ')') {
175 if (--nestTextCurrent
== 0)
176 sc
.ForwardSetState(SCE_PS_DEFAULT
);
177 } else if (sc
.ch
== '\\') {
180 } else if (sc
.state
== SCE_PS_HEXSTRING
) {
182 sc
.ForwardSetState(SCE_PS_DEFAULT
);
183 } else if (!IsABaseNDigit(sc
.ch
, 16) && !IsAWhitespaceChar(sc
.ch
)) {
184 sc
.SetState(SCE_PS_HEXSTRING
);
185 styler
.ColourTo(sc
.currentPos
, SCE_PS_BADSTRINGCHAR
);
187 } else if (sc
.state
== SCE_PS_BASE85STRING
) {
188 if (sc
.Match('~', '>')) {
190 sc
.ForwardSetState(SCE_PS_DEFAULT
);
191 } else if (!IsABase85Char(sc
.ch
) && !IsAWhitespaceChar(sc
.ch
)) {
192 sc
.SetState(SCE_PS_BASE85STRING
);
193 styler
.ColourTo(sc
.currentPos
, SCE_PS_BADSTRINGCHAR
);
197 // Determine if a new state should be entered.
198 if (sc
.state
== SCE_C_DEFAULT
) {
199 unsigned int tokenpos
= sc
.currentPos
;
201 if (sc
.ch
== '[' || sc
.ch
== ']') {
202 sc
.SetState(SCE_PS_PAREN_ARRAY
);
203 } else if (sc
.ch
== '{' || sc
.ch
== '}') {
204 sc
.SetState(SCE_PS_PAREN_PROC
);
205 } else if (sc
.ch
== '/') {
206 if (sc
.chNext
== '/') {
207 sc
.SetState(SCE_PS_IMMEVAL
);
210 sc
.SetState(SCE_PS_LITERAL
);
212 } else if (sc
.ch
== '<') {
213 if (sc
.chNext
== '<') {
214 sc
.SetState(SCE_PS_PAREN_DICT
);
216 } else if (sc
.chNext
== '~') {
217 sc
.SetState(SCE_PS_BASE85STRING
);
220 sc
.SetState(SCE_PS_HEXSTRING
);
222 } else if (sc
.ch
== '>' && sc
.chNext
== '>') {
223 sc
.SetState(SCE_PS_PAREN_DICT
);
225 } else if (sc
.ch
== '>' || sc
.ch
== ')') {
226 sc
.SetState(SCE_C_DEFAULT
);
227 styler
.ColourTo(sc
.currentPos
, SCE_PS_BADSTRINGCHAR
);
228 } else if (sc
.ch
== '(') {
229 sc
.SetState(SCE_PS_TEXT
);
231 } else if (sc
.ch
== '%') {
232 if (sc
.chNext
== '%' && sc
.atLineStart
) {
233 sc
.SetState(SCE_PS_DSC_COMMENT
);
235 if (sc
.chNext
== '+') {
237 sc
.ForwardSetState(SCE_PS_DSC_VALUE
);
240 sc
.SetState(SCE_PS_COMMENT
);
242 } else if ((sc
.ch
== '+' || sc
.ch
== '-' || sc
.ch
== '.') &&
243 IsABaseNDigit(sc
.chNext
, 10)) {
244 sc
.SetState(SCE_PS_NUMBER
);
246 numHasPoint
= (sc
.ch
== '.');
247 numHasExponent
= false;
248 numHasSign
= (sc
.ch
== '+' || sc
.ch
== '-');
249 } else if ((sc
.ch
== '+' || sc
.ch
== '-') && sc
.chNext
== '.' &&
250 IsABaseNDigit(sc
.GetRelative(2), 10)) {
251 sc
.SetState(SCE_PS_NUMBER
);
254 numHasExponent
= false;
256 } else if (IsABaseNDigit(sc
.ch
, 10)) {
257 sc
.SetState(SCE_PS_NUMBER
);
260 numHasExponent
= false;
262 } else if (!IsAWhitespaceChar(sc
.ch
)) {
263 sc
.SetState(SCE_PS_NAME
);
266 // Mark the start of tokens
267 if (tokenizing
&& sc
.state
!= SCE_C_DEFAULT
&& sc
.state
!= SCE_PS_COMMENT
&&
268 sc
.state
!= SCE_PS_DSC_COMMENT
&& sc
.state
!= SCE_PS_DSC_VALUE
) {
270 styler
.StartAt(tokenpos
, static_cast<char>(INDIC2_MASK
));
271 styler
.ColourTo(tokenpos
, INDIC2_MASK
);
273 styler
.StartAt(tokenpos
);
274 styler
.StartSegment(tokenpos
);
279 styler
.SetLineState(lineCurrent
, nestTextCurrent
);
285 static void FoldPSDoc(unsigned int startPos
, int length
, int, WordList
*[],
287 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
288 bool foldAtElse
= styler
.GetPropertyInt("fold.at.else", 0) != 0;
289 unsigned int endPos
= startPos
+ length
;
290 int visibleChars
= 0;
291 int lineCurrent
= styler
.GetLine(startPos
);
292 int levelCurrent
= SC_FOLDLEVELBASE
;
294 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
295 int levelMinCurrent
= levelCurrent
;
296 int levelNext
= levelCurrent
;
297 char chNext
= styler
[startPos
];
298 int styleNext
= styler
.StyleAt(startPos
);
300 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
302 chNext
= styler
.SafeGetCharAt(i
+ 1);
304 styleNext
= styler
.StyleAt(i
+ 1);
305 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n'); //mac??
306 if ((style
& 31) == SCE_PS_PAREN_PROC
) {
308 // Measure the minimum before a '{' to allow
310 if (levelMinCurrent
> levelNext
) {
311 levelMinCurrent
= levelNext
;
314 } else if (ch
== '}') {
319 int levelUse
= levelCurrent
;
321 levelUse
= levelMinCurrent
;
323 int lev
= levelUse
| levelNext
<< 16;
324 if (visibleChars
== 0 && foldCompact
)
325 lev
|= SC_FOLDLEVELWHITEFLAG
;
326 if (levelUse
< levelNext
)
327 lev
|= SC_FOLDLEVELHEADERFLAG
;
328 if (lev
!= styler
.LevelAt(lineCurrent
)) {
329 styler
.SetLevel(lineCurrent
, lev
);
332 levelCurrent
= levelNext
;
333 levelMinCurrent
= levelCurrent
;
336 if (!isspacechar(ch
))
341 static const char * const psWordListDesc
[] = {
342 "PS Level 1 operators",
343 "PS Level 2 operators",
344 "PS Level 3 operators",
345 "RIP-specific operators",
346 "User-defined operators",
350 LexerModule
lmPS(SCLEX_PS
, ColourisePSDoc
, "ps", FoldPSDoc
, psWordListDesc
);