]>
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.
19 #include "StyleContext.h"
21 #include "Scintilla.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
) {
40 maxdig
= '0' + base
- 1;
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
,
57 WordList
*keywordlists
[],
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);
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);
84 styler
.StartAt(startPos
);
85 styler
.StartSegment(startPos
);
88 for (; sc
.More(); sc
.Forward()) {
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
) {
95 sc
.SetState(SCE_C_DEFAULT
);
97 } else if (sc
.state
== SCE_PS_DSC_COMMENT
) {
101 sc
.SetState(SCE_PS_DSC_VALUE
);
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
);
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
);
129 numHasExponent
= true;
130 if (sc
.chNext
== '+' || sc
.chNext
== '-')
133 } else if (sc
.ch
== '.') {
134 if (numHasPoint
|| numHasExponent
|| numRadix
!= 0) {
135 sc
.ChangeState(SCE_PS_NAME
);
139 } else if (numRadix
== 0) {
140 if (!IsABaseNDigit(sc
.ch
, 10))
141 sc
.ChangeState(SCE_PS_NAME
);
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
)) {
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
) {
167 } else if (sc
.ch
== ')') {
168 if (--nestTextCurrent
== 0)
169 sc
.ForwardSetState(SCE_PS_DEFAULT
);
170 } else if (sc
.ch
== '\\') {
173 } else if (sc
.state
== SCE_PS_HEXSTRING
) {
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('~', '>')) {
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
);
203 sc
.SetState(SCE_PS_LITERAL
);
205 } else if (sc
.ch
== '<') {
206 if (sc
.chNext
== '<') {
207 sc
.SetState(SCE_PS_PAREN_DICT
);
209 } else if (sc
.chNext
== '~') {
210 sc
.SetState(SCE_PS_BASE85STRING
);
213 sc
.SetState(SCE_PS_HEXSTRING
);
215 } else if (sc
.ch
== '>' && sc
.chNext
== '>') {
216 sc
.SetState(SCE_PS_PAREN_DICT
);
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
);
224 } else if (sc
.ch
== '%') {
225 if (sc
.chNext
== '%' && sc
.atLineStart
) {
226 sc
.SetState(SCE_PS_DSC_COMMENT
);
228 if (sc
.chNext
== '+') {
230 sc
.ForwardSetState(SCE_PS_DSC_VALUE
);
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
);
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
);
247 numHasExponent
= false;
249 } else if (IsABaseNDigit(sc
.ch
, 10)) {
250 sc
.SetState(SCE_PS_NUMBER
);
253 numHasExponent
= 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
) {
263 styler
.StartAt(tokenpos
, static_cast<char>(INDIC2_MASK
));
264 styler
.ColourTo(tokenpos
, INDIC2_MASK
);
266 styler
.StartAt(tokenpos
);
267 styler
.StartSegment(tokenpos
);
272 styler
.SetLineState(lineCurrent
, nestTextCurrent
);
278 static void FoldPSDoc(unsigned int startPos
, int length
, int, WordList
*[],
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
;
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
);
293 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
295 chNext
= styler
.SafeGetCharAt(i
+ 1);
297 styleNext
= styler
.StyleAt(i
+ 1);
298 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n'); //mac??
299 if ((style
& 31) == SCE_PS_PAREN_PROC
) {
301 // Measure the minimum before a '{' to allow
303 if (levelMinCurrent
> levelNext
) {
304 levelMinCurrent
= levelNext
;
307 } else if (ch
== '}') {
312 int levelUse
= levelCurrent
;
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
);
325 levelCurrent
= levelNext
;
326 levelMinCurrent
= levelCurrent
;
329 if (!isspacechar(ch
))
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
);