]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/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.
20 #include "StyleContext.h"
22 #include "Scintilla.h"
25 static inline bool IsASelfDelimitingChar(const int ch
) {
26 return (ch
== '[' || ch
== ']' || ch
== '{' || ch
== '}' ||
27 ch
== '/' || ch
== '<' || ch
== '>' ||
28 ch
== '(' || ch
== ')' || ch
== '%');
31 static inline bool IsAWhitespaceChar(const int ch
) {
32 return (ch
== ' ' || ch
== '\t' || ch
== '\r' ||
33 ch
== '\n' || ch
== '\f' || ch
== '\0');
36 static bool IsABaseNDigit(const int ch
, const int base
) {
41 maxdig
= '0' + base
- 1;
43 letterext
= base
- 11;
45 return ((ch
>= '0' && ch
<= maxdig
) ||
46 (ch
>= 'A' && ch
<= ('A' + letterext
)) ||
47 (ch
>= 'a' && ch
<= ('a' + letterext
)));
50 static inline bool IsABase85Char(const int ch
) {
51 return ((ch
>= '!' && ch
<= 'u') || ch
== 'z');
54 static void ColourisePSDoc(
55 unsigned int startPos
,
58 WordList
*keywordlists
[],
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];
67 StyleContext
sc(startPos
, length
, initStyle
, styler
);
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);
76 bool numHasPoint
= false;
77 bool numHasExponent
= false;
78 bool numHasSign
= false;
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);
85 styler
.StartAt(startPos
);
86 styler
.StartSegment(startPos
);
89 for (; sc
.More(); sc
.Forward()) {
91 lineCurrent
= styler
.GetLine(sc
.currentPos
);
93 // Determine if the current state should terminate.
94 if (sc
.state
== SCE_PS_COMMENT
|| sc
.state
== SCE_PS_DSC_VALUE
) {
96 sc
.SetState(SCE_C_DEFAULT
);
98 } else if (sc
.state
== SCE_PS_DSC_COMMENT
) {
102 sc
.SetState(SCE_PS_DSC_VALUE
);
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
);
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
);
121 sc
.GetCurrent(szradix
, 4);
122 numRadix
= atoi(szradix
);
123 if (numRadix
< 2 || numRadix
> 36)
124 sc
.ChangeState(SCE_PS_NAME
);
126 } else if ((sc
.ch
== 'E' || sc
.ch
== 'e') && numRadix
== 0) {
127 if (numHasExponent
) {
128 sc
.ChangeState(SCE_PS_NAME
);
130 numHasExponent
= true;
131 if (sc
.chNext
== '+' || sc
.chNext
== '-')
134 } else if (sc
.ch
== '.') {
135 if (numHasPoint
|| numHasExponent
|| numRadix
!= 0) {
136 sc
.ChangeState(SCE_PS_NAME
);
140 } else if (numRadix
== 0) {
141 if (!IsABaseNDigit(sc
.ch
, 10))
142 sc
.ChangeState(SCE_PS_NAME
);
144 if (!IsABaseNDigit(sc
.ch
, numRadix
))
145 sc
.ChangeState(SCE_PS_NAME
);
147 } else if (sc
.state
== SCE_PS_NAME
|| sc
.state
== SCE_PS_KEYWORD
) {
148 if (IsASelfDelimitingChar(sc
.ch
) || IsAWhitespaceChar(sc
.ch
)) {
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
);
157 sc
.SetState(SCE_C_DEFAULT
);
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
) {
168 } else if (sc
.ch
== ')') {
169 if (--nestTextCurrent
== 0)
170 sc
.ForwardSetState(SCE_PS_DEFAULT
);
171 } else if (sc
.ch
== '\\') {
174 } else if (sc
.state
== SCE_PS_HEXSTRING
) {
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
);
181 } else if (sc
.state
== SCE_PS_BASE85STRING
) {
182 if (sc
.Match('~', '>')) {
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
);
191 // Determine if a new state should be entered.
192 if (sc
.state
== SCE_C_DEFAULT
) {
193 unsigned int tokenpos
= sc
.currentPos
;
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
);
204 sc
.SetState(SCE_PS_LITERAL
);
206 } else if (sc
.ch
== '<') {
207 if (sc
.chNext
== '<') {
208 sc
.SetState(SCE_PS_PAREN_DICT
);
210 } else if (sc
.chNext
== '~') {
211 sc
.SetState(SCE_PS_BASE85STRING
);
214 sc
.SetState(SCE_PS_HEXSTRING
);
216 } else if (sc
.ch
== '>' && sc
.chNext
== '>') {
217 sc
.SetState(SCE_PS_PAREN_DICT
);
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
);
225 } else if (sc
.ch
== '%') {
226 if (sc
.chNext
== '%' && sc
.atLineStart
) {
227 sc
.SetState(SCE_PS_DSC_COMMENT
);
229 if (sc
.chNext
== '+') {
231 sc
.ForwardSetState(SCE_PS_DSC_VALUE
);
234 sc
.SetState(SCE_PS_COMMENT
);
236 } else if ((sc
.ch
== '+' || sc
.ch
== '-' || sc
.ch
== '.') &&
237 IsABaseNDigit(sc
.chNext
, 10)) {
238 sc
.SetState(SCE_PS_NUMBER
);
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
);
248 numHasExponent
= false;
250 } else if (IsABaseNDigit(sc
.ch
, 10)) {
251 sc
.SetState(SCE_PS_NUMBER
);
254 numHasExponent
= false;
256 } else if (!IsAWhitespaceChar(sc
.ch
)) {
257 sc
.SetState(SCE_PS_NAME
);
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
) {
264 styler
.StartAt(tokenpos
, static_cast<char>(INDIC2_MASK
));
265 styler
.ColourTo(tokenpos
, INDIC2_MASK
);
267 styler
.StartAt(tokenpos
);
268 styler
.StartSegment(tokenpos
);
273 styler
.SetLineState(lineCurrent
, nestTextCurrent
);
279 static void FoldPSDoc(unsigned int startPos
, int length
, int, WordList
*[],
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
;
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
);
294 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
296 chNext
= styler
.SafeGetCharAt(i
+ 1);
298 styleNext
= styler
.StyleAt(i
+ 1);
299 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n'); //mac??
300 if ((style
& 31) == SCE_PS_PAREN_PROC
) {
302 // Measure the minimum before a '{' to allow
304 if (levelMinCurrent
> levelNext
) {
305 levelMinCurrent
= levelNext
;
308 } else if (ch
== '}') {
313 int levelUse
= levelCurrent
;
315 levelUse
= levelMinCurrent
;
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
);
326 levelCurrent
= levelNext
;
327 levelMinCurrent
= levelCurrent
;
330 if (!isspacechar(ch
))
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",
344 LexerModule
lmPS(SCLEX_PS
, ColourisePSDoc
, "ps", FoldPSDoc
, psWordListDesc
);