]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexPerl.cxx
9ccb207d0f3ae44e28507357b0c2efec3fdbaee0
1 // SciTE - Scintilla based Text Editor
2 // LexPerl.cxx - lexer for subset of Perl
3 // Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
4 // The License.txt file describes the conditions under which this software may be distributed.
17 #include "Scintilla.h"
20 inline bool isPerlOperator(char ch
) {
23 // '.' left out as it is used to make up numbers
24 if (ch
== '%' || ch
== '^' || ch
== '&' || ch
== '*' || ch
== '\\' ||
25 ch
== '(' || ch
== ')' || ch
== '-' || ch
== '+' ||
26 ch
== '=' || ch
== '|' || ch
== '{' || ch
== '}' ||
27 ch
== '[' || ch
== ']' || ch
== ':' || ch
== ';' ||
28 ch
== '<' || ch
== '>' || ch
== ',' || ch
== '/' ||
29 ch
== '?' || ch
== '!' || ch
== '.' || ch
== '~')
34 static int classifyWordPerl(unsigned int start
, unsigned int end
, WordList
&keywords
, StylingContext
&styler
) {
36 bool wordIsNumber
= isdigit(styler
[start
]) || (styler
[start
] == '.');
37 for (unsigned int i
= 0; i
< end
- start
+ 1 && i
< 30; i
++) {
38 s
[i
] = styler
[start
+ i
];
41 char chAttr
= SCE_PL_IDENTIFIER
;
43 chAttr
= SCE_PL_NUMBER
;
45 if (keywords
.InList(s
))
48 styler
.ColourTo(end
, chAttr
);
52 static bool isEndVar(char ch
) {
53 return !isalnum(ch
) && ch
!= '#' && ch
!= '$' &&
54 ch
!= '_' && ch
!= '\'';
57 static bool isMatch(StylingContext
&styler
, int lengthDoc
, int pos
, const char *val
) {
58 if ((pos
+ static_cast<int>(strlen(val
))) >= lengthDoc
) {
62 if (*val
!= styler
[pos
++]) {
70 static bool isOKQuote(char ch
) {
80 static char opposite(char ch
) {
92 static void ColourisePerlDoc(unsigned int startPos
, int length
, int initStyle
,
93 WordList
*keywordlists
[], StylingContext
&styler
) {
95 // Lexer for perl often has to backtrack to start of current style to determine
96 // which characters are being used as quotes, how deeply nested is the
97 // start position and what the termination string is for here documents
99 WordList
&keywords
= *keywordlists
[0];
103 char quoteDown
= 'd';
107 bool preferRE
= true;
108 sooked
[sookedpos
] = '\0';
109 int state
= initStyle
;
110 int lengthDoc
= startPos
+ length
;
111 // If in a long distance lexical state, seek to the beginning to find quote characters
112 if (state
== SCE_PL_HERE
|| state
== SCE_PL_REGEX
||
113 state
== SCE_PL_REGSUBST
|| state
== SCE_PL_LONGQUOTE
) {
114 while ((startPos
> 1) && (styler
.StyleAt(startPos
- 1) == state
)) {
117 state
= SCE_PL_DEFAULT
;
119 styler
.StartAt(startPos
);
121 char chNext
= styler
[startPos
];
122 styler
.StartSegment(startPos
);
123 for (int i
= startPos
; i
<= lengthDoc
; i
++) {
125 chNext
= styler
.SafeGetCharAt(i
+ 1);
126 char chNext2
= styler
.SafeGetCharAt(i
+ 2);
128 if (styler
.IsLeadByte(ch
)) {
129 chNext
= styler
.SafeGetCharAt(i
+ 2);
135 if (state
== SCE_PL_DEFAULT
) {
136 if (iswordstart(ch
)) {
137 styler
.ColourTo(i
- 1, state
);
138 if (ch
== 's' && !isalnum(chNext
)) {
139 state
= SCE_PL_REGSUBST
;
144 } else if (ch
== 'm' && !isalnum(chNext
)) {
145 state
= SCE_PL_REGEX
;
150 } else if (ch
== 't' && chNext
== 'r' && !isalnum(chNext2
)) {
151 state
= SCE_PL_REGSUBST
;
158 } else if (ch
== 'q' && (chNext
== 'q' || chNext
== 'r' || chNext
== 'w' || chNext
== 'x') && !isalnum(chNext2
)) {
159 state
= SCE_PL_LONGQUOTE
;
170 } else if (ch
== '#') {
171 styler
.ColourTo(i
- 1, state
);
172 state
= SCE_PL_COMMENTLINE
;
173 } else if (ch
== '\"') {
174 styler
.ColourTo(i
- 1, state
);
175 state
= SCE_PL_STRING
;
176 } else if (ch
== '\'') {
179 styler
.ColourTo(i
, state
);
181 styler
.ColourTo(i
- 1, state
);
182 state
= SCE_PL_CHARACTER
;
184 } else if (ch
== '`') {
185 styler
.ColourTo(i
- 1, state
);
186 state
= SCE_PL_BACKTICKS
;
187 } else if (ch
== '$') {
189 styler
.ColourTo(i
- 1, state
);
190 if (isalnum(chNext
) || chNext
== '#' || chNext
== '$' || chNext
== '_') {
191 state
= SCE_PL_SCALAR
;
192 } else if (chNext
!= '{' && chNext
!= '[') {
193 styler
.ColourTo(i
, SCE_PL_SCALAR
);
198 styler
.ColourTo(i
, SCE_PL_SCALAR
);
200 } else if (ch
== '@') {
202 styler
.ColourTo(i
- 1, state
);
203 if (isalpha(chNext
) || chNext
== '#' || chNext
== '$' || chNext
== '_') {
204 state
= SCE_PL_ARRAY
;
205 } else if (chNext
!= '{' && chNext
!= '[') {
206 styler
.ColourTo(i
, SCE_PL_ARRAY
);
210 styler
.ColourTo(i
, SCE_PL_ARRAY
);
212 } else if (ch
== '%') {
214 styler
.ColourTo(i
- 1, state
);
215 if (isalpha(chNext
) || chNext
== '#' || chNext
== '$' || chNext
== '_') {
217 } else if (chNext
!= '{' && chNext
!= '[') {
218 styler
.ColourTo(i
, SCE_PL_HASH
);
222 styler
.ColourTo(i
, SCE_PL_HASH
);
224 } else if (ch
== '*') {
225 styler
.ColourTo(i
- 1, state
);
226 state
= SCE_PL_SYMBOLTABLE
;
227 } else if (ch
== '/' && preferRE
) {
228 styler
.ColourTo(i
- 1, state
);
229 state
= SCE_PL_REGEX
;
234 } else if (ch
== '<' && chNext
== '<') {
235 styler
.ColourTo(i
- 1, state
);
242 sooked
[sookedpos
] = '\0';
243 } else if (ch
== '=' && isalpha(chNext
)) {
244 styler
.ColourTo(i
- 1, state
);
248 sooked
[sookedpos
] = '\0';
249 } else if (isPerlOperator(ch
)) {
250 if (ch
== ')' || ch
== ']')
254 styler
.ColourTo(i
- 1, state
);
255 styler
.ColourTo(i
, SCE_PL_OPERATOR
);
257 } else if (state
== SCE_PL_WORD
) {
258 if (!iswordchar(ch
) && ch
!= '\'') { // Archaic Perl has quotes inside names
259 if (isMatch(styler
, lengthDoc
, styler
.GetStartSegment(), "__DATA__")) {
260 styler
.ColourTo(i
, SCE_PL_DATASECTION
);
261 state
= SCE_PL_DATASECTION
;
262 } else if (isMatch(styler
, lengthDoc
, styler
.GetStartSegment(), "__END__")) {
263 styler
.ColourTo(i
, SCE_PL_DATASECTION
);
264 state
= SCE_PL_DATASECTION
;
266 if (classifyWordPerl(styler
.GetStartSegment(), i
- 1, keywords
, styler
) == SCE_PL_WORD
)
268 state
= SCE_PL_DEFAULT
;
270 state
= SCE_PL_COMMENTLINE
;
271 } else if (ch
== '\"') {
272 state
= SCE_PL_STRING
;
273 } else if (ch
== '\'') {
274 state
= SCE_PL_CHARACTER
;
275 } else if (ch
== '<' && chNext
== '<') {
279 sooked
[sookedpos
] = '\0';
280 } else if (isPerlOperator(ch
)) {
281 if (ch
== ')' || ch
== ']')
285 styler
.ColourTo(i
, SCE_PL_OPERATOR
);
286 state
= SCE_PL_DEFAULT
;
291 if (state
== SCE_PL_COMMENTLINE
) {
292 if (ch
== '\r' || ch
== '\n') {
293 styler
.ColourTo(i
- 1, state
);
294 state
= SCE_PL_DEFAULT
;
296 } else if (state
== SCE_PL_HERE
) {
297 if (isalnum(ch
) && quotes
< 2) {
298 sooked
[sookedpos
++] = ch
;
299 sooked
[sookedpos
] = '\0';
306 if (quotes
> 1 && isMatch(styler
, lengthDoc
, i
, sooked
)) {
307 styler
.ColourTo(i
+ sookedpos
- 1, SCE_PL_HERE
);
308 state
= SCE_PL_DEFAULT
;
312 } else if (state
== SCE_PL_STRING
) {
314 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
317 chNext
= styler
.SafeGetCharAt(i
+ 1);
319 } else if (ch
== '\"') {
320 styler
.ColourTo(i
, state
);
321 state
= SCE_PL_DEFAULT
;
324 chNext
= styler
.SafeGetCharAt(i
+ 1);
326 } else if (state
== SCE_PL_CHARACTER
) {
328 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
331 chNext
= styler
.SafeGetCharAt(i
+ 1);
333 } else if (ch
== '\'') {
334 styler
.ColourTo(i
, state
);
335 state
= SCE_PL_DEFAULT
;
338 chNext
= styler
.SafeGetCharAt(i
+ 1);
340 } else if (state
== SCE_PL_BACKTICKS
) {
342 styler
.ColourTo(i
, state
);
343 state
= SCE_PL_DEFAULT
;
346 chNext
= styler
.SafeGetCharAt(i
+ 1);
348 } else if (state
== SCE_PL_POD
) {
350 if (isMatch(styler
, lengthDoc
, i
, "=cut")) {
351 styler
.ColourTo(i
- 1 + 4, state
);
353 state
= SCE_PL_DEFAULT
;
358 } else if (state
== SCE_PL_SCALAR
) {
360 styler
.ColourTo(i
- 1, state
);
361 state
= SCE_PL_DEFAULT
;
363 } else if (state
== SCE_PL_ARRAY
) {
365 styler
.ColourTo(i
- 1, state
);
366 state
= SCE_PL_DEFAULT
;
368 } else if (state
== SCE_PL_HASH
) {
370 styler
.ColourTo(i
- 1, state
);
371 state
= SCE_PL_DEFAULT
;
373 } else if (state
== SCE_PL_SYMBOLTABLE
) {
375 styler
.ColourTo(i
- 1, state
);
376 state
= SCE_PL_DEFAULT
;
378 } else if (state
== SCE_PL_REF
) {
380 styler
.ColourTo(i
- 1, state
);
381 state
= SCE_PL_DEFAULT
;
383 } else if (state
== SCE_PL_REGEX
) {
384 if (!quoteUp
&& !isspace(ch
)) {
386 quoteDown
= opposite(ch
);
389 if (ch
== quoteDown
&& chPrev
!= '\\') {
393 if (quoteUp
== quoteDown
) {
397 if (!isalpha(chNext
)) {
399 styler
.ColourTo(i
, state
);
400 state
= SCE_PL_DEFAULT
;
404 } else if (ch
== quoteUp
&& chPrev
!= '\\') {
406 } else if (!isalpha(chNext
)) {
408 styler
.ColourTo(i
, state
);
409 state
= SCE_PL_DEFAULT
;
414 } else if (state
== SCE_PL_REGSUBST
) {
415 if (!quoteUp
&& !isspace(ch
)) {
417 quoteDown
= opposite(ch
);
420 if (ch
== quoteDown
&& chPrev
!= '\\') {
425 if (!isalpha(chNext
)) {
427 styler
.ColourTo(i
, state
);
428 state
= SCE_PL_DEFAULT
;
432 if (quoteUp
== quoteDown
) {
435 } else if (ch
== quoteUp
&& chPrev
!= '\\') {
437 } else if (!isalpha(chNext
)) {
439 styler
.ColourTo(i
, state
);
440 state
= SCE_PL_DEFAULT
;
445 } else if (state
== SCE_PL_LONGQUOTE
) {
446 if (!quoteDown
&& !isspace(ch
)) {
448 quoteDown
= opposite(quoteUp
);
450 } else if (ch
== quoteDown
) {
455 styler
.ColourTo(i
, state
);
456 state
= SCE_PL_DEFAULT
;
459 if (quoteUp
== quoteDown
) {
463 } else if (ch
== quoteUp
) {
468 if (state
== SCE_PL_DEFAULT
) { // One of the above succeeded
470 state
= SCE_PL_COMMENTLINE
;
471 } else if (ch
== '\"') {
472 state
= SCE_PL_STRING
;
473 } else if (ch
== '\'') {
474 state
= SCE_PL_CHARACTER
;
475 } else if (iswordstart(ch
)) {
478 } else if (isoperator(ch
)) {
479 styler
.ColourTo(i
, SCE_PL_OPERATOR
);
485 styler
.ColourTo(lengthDoc
, state
);
488 LexerModule
lmPerl(SCLEX_PERL
, ColourisePerlDoc
);