]>
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"
25 using namespace Scintilla
;
28 static inline bool IsASelfDelimitingChar(const int ch
) {
29 return (ch
== '[' || ch
== ']' || ch
== '{' || ch
== '}' ||
30 ch
== '/' || ch
== '<' || ch
== '>' ||
31 ch
== '(' || ch
== ')' || ch
== '%');
34 static inline bool IsAWhitespaceChar(const int ch
) {
35 return (ch
== ' ' || ch
== '\t' || ch
== '\r' ||
36 ch
== '\n' || ch
== '\f' || ch
== '\0');
39 static bool IsABaseNDigit(const int ch
, const int base
) {
44 maxdig
= '0' + base
- 1;
46 letterext
= base
- 11;
48 return ((ch
>= '0' && ch
<= maxdig
) ||
49 (ch
>= 'A' && ch
<= ('A' + letterext
)) ||
50 (ch
>= 'a' && ch
<= ('a' + letterext
)));
53 static inline bool IsABase85Char(const int ch
) {
54 return ((ch
>= '!' && ch
<= 'u') || ch
== 'z');
57 static void ColourisePSDoc(
58 unsigned int startPos
,
61 WordList
*keywordlists
[],
64 WordList
&keywords1
= *keywordlists
[0];
65 WordList
&keywords2
= *keywordlists
[1];
66 WordList
&keywords3
= *keywordlists
[2];
67 WordList
&keywords4
= *keywordlists
[3];
68 WordList
&keywords5
= *keywordlists
[4];
70 StyleContext
sc(startPos
, length
, initStyle
, styler
);
72 bool tokenizing
= styler
.GetPropertyInt("ps.tokenize") != 0;
73 int pslevel
= styler
.GetPropertyInt("ps.level", 3);
74 int lineCurrent
= styler
.GetLine(startPos
);
75 int nestTextCurrent
= 0;
76 if (lineCurrent
> 0 && initStyle
== SCE_PS_TEXT
)
77 nestTextCurrent
= styler
.GetLineState(lineCurrent
- 1);
79 bool numHasPoint
= false;
80 bool numHasExponent
= false;
81 bool numHasSign
= false;
83 // Clear out existing tokenization
84 if (tokenizing
&& length
> 0) {
85 styler
.StartAt(startPos
, static_cast<char>(INDIC2_MASK
));
86 styler
.ColourTo(startPos
+ length
-1, 0);
88 styler
.StartAt(startPos
);
89 styler
.StartSegment(startPos
);
92 for (; sc
.More(); sc
.Forward()) {
94 lineCurrent
= styler
.GetLine(sc
.currentPos
);
96 // Determine if the current state should terminate.
97 if (sc
.state
== SCE_PS_COMMENT
|| sc
.state
== SCE_PS_DSC_VALUE
) {
99 sc
.SetState(SCE_C_DEFAULT
);
101 } else if (sc
.state
== SCE_PS_DSC_COMMENT
) {
105 sc
.SetState(SCE_PS_DSC_VALUE
);
107 sc
.SetState(SCE_C_DEFAULT
);
108 } else if (sc
.atLineEnd
) {
109 sc
.SetState(SCE_C_DEFAULT
);
110 } else if (IsAWhitespaceChar(sc
.ch
) && sc
.ch
!= '\r') {
111 sc
.ChangeState(SCE_PS_COMMENT
);
113 } else if (sc
.state
== SCE_PS_NUMBER
) {
114 if (IsASelfDelimitingChar(sc
.ch
) || IsAWhitespaceChar(sc
.ch
)) {
115 if ((sc
.chPrev
== '+' || sc
.chPrev
== '-' ||
116 sc
.chPrev
== 'E' || sc
.chPrev
== 'e') && numRadix
== 0)
117 sc
.ChangeState(SCE_PS_NAME
);
118 sc
.SetState(SCE_C_DEFAULT
);
119 } else if (sc
.ch
== '#') {
120 if (numHasPoint
|| numHasExponent
|| numHasSign
|| numRadix
!= 0) {
121 sc
.ChangeState(SCE_PS_NAME
);
124 sc
.GetCurrent(szradix
, 4);
125 numRadix
= atoi(szradix
);
126 if (numRadix
< 2 || numRadix
> 36)
127 sc
.ChangeState(SCE_PS_NAME
);
129 } else if ((sc
.ch
== 'E' || sc
.ch
== 'e') && numRadix
== 0) {
130 if (numHasExponent
) {
131 sc
.ChangeState(SCE_PS_NAME
);
133 numHasExponent
= true;
134 if (sc
.chNext
== '+' || sc
.chNext
== '-')
137 } else if (sc
.ch
== '.') {
138 if (numHasPoint
|| numHasExponent
|| numRadix
!= 0) {
139 sc
.ChangeState(SCE_PS_NAME
);
143 } else if (numRadix
== 0) {
144 if (!IsABaseNDigit(sc
.ch
, 10))
145 sc
.ChangeState(SCE_PS_NAME
);
147 if (!IsABaseNDigit(sc
.ch
, numRadix
))
148 sc
.ChangeState(SCE_PS_NAME
);
150 } else if (sc
.state
== SCE_PS_NAME
|| sc
.state
== SCE_PS_KEYWORD
) {
151 if (IsASelfDelimitingChar(sc
.ch
) || IsAWhitespaceChar(sc
.ch
)) {
153 sc
.GetCurrent(s
, sizeof(s
));
154 if ((pslevel
>= 1 && keywords1
.InList(s
)) ||
155 (pslevel
>= 2 && keywords2
.InList(s
)) ||
156 (pslevel
>= 3 && keywords3
.InList(s
)) ||
157 keywords4
.InList(s
) || keywords5
.InList(s
)) {
158 sc
.ChangeState(SCE_PS_KEYWORD
);
160 sc
.SetState(SCE_C_DEFAULT
);
162 } else if (sc
.state
== SCE_PS_LITERAL
|| sc
.state
== SCE_PS_IMMEVAL
) {
163 if (IsASelfDelimitingChar(sc
.ch
) || IsAWhitespaceChar(sc
.ch
))
164 sc
.SetState(SCE_C_DEFAULT
);
165 } else if (sc
.state
== SCE_PS_PAREN_ARRAY
|| sc
.state
== SCE_PS_PAREN_DICT
||
166 sc
.state
== SCE_PS_PAREN_PROC
) {
167 sc
.SetState(SCE_C_DEFAULT
);
168 } else if (sc
.state
== SCE_PS_TEXT
) {
171 } else if (sc
.ch
== ')') {
172 if (--nestTextCurrent
== 0)
173 sc
.ForwardSetState(SCE_PS_DEFAULT
);
174 } else if (sc
.ch
== '\\') {
177 } else if (sc
.state
== SCE_PS_HEXSTRING
) {
179 sc
.ForwardSetState(SCE_PS_DEFAULT
);
180 } else if (!IsABaseNDigit(sc
.ch
, 16) && !IsAWhitespaceChar(sc
.ch
)) {
181 sc
.SetState(SCE_PS_HEXSTRING
);
182 styler
.ColourTo(sc
.currentPos
, SCE_PS_BADSTRINGCHAR
);
184 } else if (sc
.state
== SCE_PS_BASE85STRING
) {
185 if (sc
.Match('~', '>')) {
187 sc
.ForwardSetState(SCE_PS_DEFAULT
);
188 } else if (!IsABase85Char(sc
.ch
) && !IsAWhitespaceChar(sc
.ch
)) {
189 sc
.SetState(SCE_PS_BASE85STRING
);
190 styler
.ColourTo(sc
.currentPos
, SCE_PS_BADSTRINGCHAR
);
194 // Determine if a new state should be entered.
195 if (sc
.state
== SCE_C_DEFAULT
) {
196 unsigned int tokenpos
= sc
.currentPos
;
198 if (sc
.ch
== '[' || sc
.ch
== ']') {
199 sc
.SetState(SCE_PS_PAREN_ARRAY
);
200 } else if (sc
.ch
== '{' || sc
.ch
== '}') {
201 sc
.SetState(SCE_PS_PAREN_PROC
);
202 } else if (sc
.ch
== '/') {
203 if (sc
.chNext
== '/') {
204 sc
.SetState(SCE_PS_IMMEVAL
);
207 sc
.SetState(SCE_PS_LITERAL
);
209 } else if (sc
.ch
== '<') {
210 if (sc
.chNext
== '<') {
211 sc
.SetState(SCE_PS_PAREN_DICT
);
213 } else if (sc
.chNext
== '~') {
214 sc
.SetState(SCE_PS_BASE85STRING
);
217 sc
.SetState(SCE_PS_HEXSTRING
);
219 } else if (sc
.ch
== '>' && sc
.chNext
== '>') {
220 sc
.SetState(SCE_PS_PAREN_DICT
);
222 } else if (sc
.ch
== '>' || sc
.ch
== ')') {
223 sc
.SetState(SCE_C_DEFAULT
);
224 styler
.ColourTo(sc
.currentPos
, SCE_PS_BADSTRINGCHAR
);
225 } else if (sc
.ch
== '(') {
226 sc
.SetState(SCE_PS_TEXT
);
228 } else if (sc
.ch
== '%') {
229 if (sc
.chNext
== '%' && sc
.atLineStart
) {
230 sc
.SetState(SCE_PS_DSC_COMMENT
);
232 if (sc
.chNext
== '+') {
234 sc
.ForwardSetState(SCE_PS_DSC_VALUE
);
237 sc
.SetState(SCE_PS_COMMENT
);
239 } else if ((sc
.ch
== '+' || sc
.ch
== '-' || sc
.ch
== '.') &&
240 IsABaseNDigit(sc
.chNext
, 10)) {
241 sc
.SetState(SCE_PS_NUMBER
);
243 numHasPoint
= (sc
.ch
== '.');
244 numHasExponent
= false;
245 numHasSign
= (sc
.ch
== '+' || sc
.ch
== '-');
246 } else if ((sc
.ch
== '+' || sc
.ch
== '-') && sc
.chNext
== '.' &&
247 IsABaseNDigit(sc
.GetRelative(2), 10)) {
248 sc
.SetState(SCE_PS_NUMBER
);
251 numHasExponent
= false;
253 } else if (IsABaseNDigit(sc
.ch
, 10)) {
254 sc
.SetState(SCE_PS_NUMBER
);
257 numHasExponent
= false;
259 } else if (!IsAWhitespaceChar(sc
.ch
)) {
260 sc
.SetState(SCE_PS_NAME
);
263 // Mark the start of tokens
264 if (tokenizing
&& sc
.state
!= SCE_C_DEFAULT
&& sc
.state
!= SCE_PS_COMMENT
&&
265 sc
.state
!= SCE_PS_DSC_COMMENT
&& sc
.state
!= SCE_PS_DSC_VALUE
) {
267 styler
.StartAt(tokenpos
, static_cast<char>(INDIC2_MASK
));
268 styler
.ColourTo(tokenpos
, INDIC2_MASK
);
270 styler
.StartAt(tokenpos
);
271 styler
.StartSegment(tokenpos
);
276 styler
.SetLineState(lineCurrent
, nestTextCurrent
);
282 static void FoldPSDoc(unsigned int startPos
, int length
, int, WordList
*[],
284 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
285 bool foldAtElse
= styler
.GetPropertyInt("fold.at.else", 0) != 0;
286 unsigned int endPos
= startPos
+ length
;
287 int visibleChars
= 0;
288 int lineCurrent
= styler
.GetLine(startPos
);
289 int levelCurrent
= SC_FOLDLEVELBASE
;
291 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
292 int levelMinCurrent
= levelCurrent
;
293 int levelNext
= levelCurrent
;
294 char chNext
= styler
[startPos
];
295 int styleNext
= styler
.StyleAt(startPos
);
297 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
299 chNext
= styler
.SafeGetCharAt(i
+ 1);
301 styleNext
= styler
.StyleAt(i
+ 1);
302 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n'); //mac??
303 if ((style
& 31) == SCE_PS_PAREN_PROC
) {
305 // Measure the minimum before a '{' to allow
307 if (levelMinCurrent
> levelNext
) {
308 levelMinCurrent
= levelNext
;
311 } else if (ch
== '}') {
316 int levelUse
= levelCurrent
;
318 levelUse
= levelMinCurrent
;
320 int lev
= levelUse
| levelNext
<< 16;
321 if (visibleChars
== 0 && foldCompact
)
322 lev
|= SC_FOLDLEVELWHITEFLAG
;
323 if (levelUse
< levelNext
)
324 lev
|= SC_FOLDLEVELHEADERFLAG
;
325 if (lev
!= styler
.LevelAt(lineCurrent
)) {
326 styler
.SetLevel(lineCurrent
, lev
);
329 levelCurrent
= levelNext
;
330 levelMinCurrent
= levelCurrent
;
333 if (!isspacechar(ch
))
338 static const char * const psWordListDesc
[] = {
339 "PS Level 1 operators",
340 "PS Level 2 operators",
341 "PS Level 3 operators",
342 "RIP-specific operators",
343 "User-defined operators",
347 LexerModule
lmPS(SCLEX_PS
, ColourisePSDoc
, "ps", FoldPSDoc
, psWordListDesc
);