View Javadoc

1   /*
2    * PerlTokenMarker.java - Perl token marker
3    * Copyright (C) 1998, 1999 Slava Pestov
4    *
5    * You may use and modify this package for any purpose. Redistribution is
6    * permitted, in both source and binary form, provided that this notice
7    * remains intact in all source distributions of this package.
8    */
9   
10  package org.syntax.jedit.tokenmarker;
11  
12  import javax.swing.text.Segment;
13  
14  import org.syntax.jedit.KeywordMap;
15  import org.syntax.jedit.SyntaxUtilities;
16  
17  /***
18   * Perl token marker.
19   * 
20   * @author Slava Pestov
21   * @version $Id: PerlTokenMarker.java,v 1.11 1999/12/13 03:40:30 sp Exp $
22   */
23  public class PerlTokenMarker extends TokenMarker
24  {
25  	// public members
26  	public static final byte S_ONE = Token.INTERNAL_FIRST;
27  	public static final byte S_TWO = ( byte )( Token.INTERNAL_FIRST + 1 );
28  	public static final byte S_END = ( byte )( Token.INTERNAL_FIRST + 2 );
29  
30  	public PerlTokenMarker()
31  	{
32  		this( getKeywords() );
33  	}
34  
35  	public PerlTokenMarker( KeywordMap keywords )
36  	{
37  		this.keywords = keywords;
38  	}
39  
40  	public byte markTokensImpl( byte _token, Segment line, int lineIndex )
41  	{
42  		char[] array = line.array;
43  		int offset = line.offset;
44  		token = _token;
45  		lastOffset = offset;
46  		lastKeyword = offset;
47  		matchChar = '\0';
48  		matchCharBracket = false;
49  		matchSpacesAllowed = false;
50  		int length = line.count + offset;
51  
52  		if( token == Token.LITERAL1 && lineIndex != 0 && lineInfo[lineIndex - 1].obj != null )
53  		{
54  			String str = ( String )lineInfo[lineIndex - 1].obj;
55  			if( str != null && str.length() == line.count && SyntaxUtilities.regionMatches( false, line, offset, str ) )
56  			{
57  				addToken( line.count, token );
58  				return Token.NULL;
59  			}
60  			else
61  			{
62  				addToken( line.count, token );
63  				lineInfo[lineIndex].obj = str;
64  				return token;
65  			}
66  		}
67  
68  		boolean backslash = false;
69  		loop : for( int i = offset; i < length; i++ )
70  		{
71  			int i1 = ( i + 1 );
72  
73  			char c = array[i];
74  			if( c == '//' )
75  			{
76  				backslash = !backslash;
77  				continue;
78  			}
79  
80  			switch( token )
81  			{
82  			case Token.NULL :
83  				switch( c )
84  				{
85  				case '#' :
86  					if( doKeyword( line, i, c ) )
87  						break;
88  					if( backslash )
89  						backslash = false;
90  					else
91  					{
92  						addToken( i - lastOffset, token );
93  						addToken( length - i, Token.COMMENT1 );
94  						lastOffset = lastKeyword = length;
95  						break loop;
96  					}
97  					break;
98  				case '=' :
99  					backslash = false;
100 					if( i == offset )
101 					{
102 						token = Token.COMMENT2;
103 						addToken( length - i, token );
104 						lastOffset = lastKeyword = length;
105 						break loop;
106 					}
107 					else
108 						doKeyword( line, i, c );
109 					break;
110 				case '$' :
111 				case '&' :
112 				case '%' :
113 				case '@' :
114 					backslash = false;
115 					if( doKeyword( line, i, c ) )
116 						break;
117 					if( length - i > 1 )
118 					{
119 						if( c == '&' && ( array[i1] == '&' || Character.isWhitespace( array[i1] ) ) )
120 							i++ ;
121 						else
122 						{
123 							addToken( i - lastOffset, token );
124 							lastOffset = lastKeyword = i;
125 							token = Token.KEYWORD2;
126 						}
127 					}
128 					break;
129 				case '"' :
130 					if( doKeyword( line, i, c ) )
131 						break;
132 					if( backslash )
133 						backslash = false;
134 					else
135 					{
136 						addToken( i - lastOffset, token );
137 						token = Token.LITERAL1;
138 						lineInfo[lineIndex].obj = null;
139 						lastOffset = lastKeyword = i;
140 					}
141 					break;
142 				case '\'' :
143 					if( backslash )
144 						backslash = false;
145 					else
146 					{
147 						int oldLastKeyword = lastKeyword;
148 						if( doKeyword( line, i, c ) )
149 							break;
150 						if( i != oldLastKeyword )
151 							break;
152 						addToken( i - lastOffset, token );
153 						token = Token.LITERAL2;
154 						lastOffset = lastKeyword = i;
155 					}
156 					break;
157 				case '`' :
158 					if( doKeyword( line, i, c ) )
159 						break;
160 					if( backslash )
161 						backslash = false;
162 					else
163 					{
164 						addToken( i - lastOffset, token );
165 						token = Token.OPERATOR;
166 						lastOffset = lastKeyword = i;
167 					}
168 					break;
169 				case '<' :
170 					if( doKeyword( line, i, c ) )
171 						break;
172 					if( backslash )
173 						backslash = false;
174 					else
175 					{
176 						if( length - i > 2 && array[i1] == '<' && !Character.isWhitespace( array[i + 2] ) )
177 						{
178 							addToken( i - lastOffset, token );
179 							lastOffset = lastKeyword = i;
180 							token = Token.LITERAL1;
181 							int len = length - ( i + 2 );
182 							if( array[length - 1] == ';' )
183 								len-- ;
184 							lineInfo[lineIndex].obj = createReadinString( array, i + 2, len );
185 						}
186 					}
187 					break;
188 				case ':' :
189 					backslash = false;
190 					if( doKeyword( line, i, c ) )
191 						break;
192 					// Doesn't pick up all labels,
193 					// but at least doesn't mess up
194 					if( lastKeyword != 0 )
195 						break;
196 					addToken( i1 - lastOffset, Token.LABEL );
197 					lastOffset = lastKeyword = i1;
198 					break;
199 				case '-' :
200 					backslash = false;
201 					if( doKeyword( line, i, c ) )
202 						break;
203 					if( i != lastKeyword || length - i <= 1 )
204 						break;
205 					switch( array[i1] )
206 					{
207 					case 'r' :
208 					case 'w' :
209 					case 'x' :
210 					case 'o' :
211 					case 'R' :
212 					case 'W' :
213 					case 'X' :
214 					case 'O' :
215 					case 'e' :
216 					case 'z' :
217 					case 's' :
218 					case 'f' :
219 					case 'd' :
220 					case 'l' :
221 					case 'p' :
222 					case 'S' :
223 					case 'b' :
224 					case 'c' :
225 					case 't' :
226 					case 'u' :
227 					case 'g' :
228 					case 'k' :
229 					case 'T' :
230 					case 'B' :
231 					case 'M' :
232 					case 'A' :
233 					case 'C' :
234 						addToken( i - lastOffset, token );
235 						addToken( 2, Token.KEYWORD3 );
236 						lastOffset = lastKeyword = i + 2;
237 						i++ ;
238 					}
239 					break;
240 				case '/' :
241 				case '?' :
242 					if( doKeyword( line, i, c ) )
243 						break;
244 					if( length - i > 1 )
245 					{
246 						backslash = false;
247 						char ch = array[i1];
248 						if( Character.isWhitespace( ch ) )
249 							break;
250 						matchChar = c;
251 						matchSpacesAllowed = false;
252 						addToken( i - lastOffset, token );
253 						token = S_ONE;
254 						lastOffset = lastKeyword = i;
255 					}
256 					break;
257 				default :
258 					backslash = false;
259 					if( !Character.isLetterOrDigit( c ) && c != '_' )
260 						doKeyword( line, i, c );
261 					break;
262 				}
263 				break;
264 			case Token.KEYWORD2 :
265 				backslash = false;
266 				// This test checks for an end-of-variable
267 				// condition
268 				if( !Character.isLetterOrDigit( c ) && c != '_' && c != '#' && c != '\'' && c != ':' && c != '&' )
269 				{
270 					// If this is the first character
271 					// of the variable name ($'aaa)
272 					// ignore it
273 					if( i != offset && array[i - 1] == '$' )
274 					{
275 						addToken( i1 - lastOffset, token );
276 						lastOffset = lastKeyword = i1;
277 					}
278 					// Otherwise, end of variable...
279 					else
280 					{
281 						addToken( i - lastOffset, token );
282 						lastOffset = lastKeyword = i;
283 						// Wind back so that stuff
284 						// like $hello$fred is picked
285 						// up
286 						i-- ;
287 						token = Token.NULL;
288 					}
289 				}
290 				break;
291 			case S_ONE :
292 			case S_TWO :
293 				if( backslash )
294 					backslash = false;
295 				else
296 				{
297 					if( matchChar == '\0' )
298 					{
299 						if( Character.isWhitespace( matchChar ) && !matchSpacesAllowed )
300 							break;
301 						else
302 							matchChar = c;
303 					}
304 					else
305 					{
306 						switch( matchChar )
307 						{
308 						case '(' :
309 							matchChar = ')';
310 							matchCharBracket = true;
311 							break;
312 						case '[' :
313 							matchChar = ']';
314 							matchCharBracket = true;
315 							break;
316 						case '{' :
317 							matchChar = '}';
318 							matchCharBracket = true;
319 							break;
320 						case '<' :
321 							matchChar = '>';
322 							matchCharBracket = true;
323 							break;
324 						default :
325 							matchCharBracket = false;
326 							break;
327 						}
328 						if( c != matchChar )
329 							break;
330 						if( token == S_TWO )
331 						{
332 							token = S_ONE;
333 							if( matchCharBracket )
334 								matchChar = '\0';
335 						}
336 						else
337 						{
338 							token = S_END;
339 							addToken( i1 - lastOffset, Token.LITERAL2 );
340 							lastOffset = lastKeyword = i1;
341 						}
342 					}
343 				}
344 				break;
345 			case S_END :
346 				backslash = false;
347 				if( !Character.isLetterOrDigit( c ) && c != '_' )
348 					doKeyword( line, i, c );
349 				break;
350 			case Token.COMMENT2 :
351 				backslash = false;
352 				if( i == offset )
353 				{
354 					addToken( line.count, token );
355 					if( length - i > 3 && SyntaxUtilities.regionMatches( false, line, offset, "=cut" ) )
356 						token = Token.NULL;
357 					lastOffset = lastKeyword = length;
358 					break loop;
359 				}
360 				break;
361 			case Token.LITERAL1 :
362 				if( backslash )
363 					backslash = false;
364 				/*
365 				 * else if(c == '$') backslash = true;
366 				 */
367 				else if( c == '"' )
368 				{
369 					addToken( i1 - lastOffset, token );
370 					token = Token.NULL;
371 					lastOffset = lastKeyword = i1;
372 				}
373 				break;
374 			case Token.LITERAL2 :
375 				if( backslash )
376 					backslash = false;
377 				/*
378 				 * else if(c == '$') backslash = true;
379 				 */
380 				else if( c == '\'' )
381 				{
382 					addToken( i1 - lastOffset, Token.LITERAL1 );
383 					token = Token.NULL;
384 					lastOffset = lastKeyword = i1;
385 				}
386 				break;
387 			case Token.OPERATOR :
388 				if( backslash )
389 					backslash = false;
390 				else if( c == '`' )
391 				{
392 					addToken( i1 - lastOffset, token );
393 					token = Token.NULL;
394 					lastOffset = lastKeyword = i1;
395 				}
396 				break;
397 			default :
398 				throw new InternalError( "Invalid state: " + token );
399 			}
400 		}
401 
402 		if( token == Token.NULL )
403 			doKeyword( line, length, '\0' );
404 
405 		switch( token )
406 		{
407 		case Token.KEYWORD2 :
408 			addToken( length - lastOffset, token );
409 			token = Token.NULL;
410 			break;
411 		case Token.LITERAL2 :
412 			addToken( length - lastOffset, Token.LITERAL1 );
413 			break;
414 		case S_END :
415 			addToken( length - lastOffset, Token.LITERAL2 );
416 			token = Token.NULL;
417 			break;
418 		case S_ONE :
419 		case S_TWO :
420 			addToken( length - lastOffset, Token.INVALID );
421 			token = Token.NULL;
422 			break;
423 		default :
424 			addToken( length - lastOffset, token );
425 			break;
426 		}
427 		return token;
428 	}
429 
430 	// private members
431 	private KeywordMap keywords;
432 	private byte token;
433 	private int lastOffset;
434 	private int lastKeyword;
435 	private char matchChar;
436 	private boolean matchCharBracket;
437 	private boolean matchSpacesAllowed;
438 
439 	private boolean doKeyword( Segment line, int i, char c )
440 	{
441 		int i1 = i + 1;
442 
443 		if( token == S_END )
444 		{
445 			addToken( i - lastOffset, Token.LITERAL2 );
446 			token = Token.NULL;
447 			lastOffset = i;
448 			lastKeyword = i1;
449 			return false;
450 		}
451 
452 		int len = i - lastKeyword;
453 		byte id = keywords.lookup( line, lastKeyword, len );
454 		if( id == S_ONE || id == S_TWO )
455 		{
456 			if( lastKeyword != lastOffset )
457 				addToken( lastKeyword - lastOffset, Token.NULL );
458 			addToken( len, Token.LITERAL2 );
459 			lastOffset = i;
460 			lastKeyword = i1;
461 			if( Character.isWhitespace( c ) )
462 				matchChar = '\0';
463 			else
464 				matchChar = c;
465 			matchSpacesAllowed = true;
466 			token = id;
467 			return true;
468 		}
469 		else if( id != Token.NULL )
470 		{
471 			if( lastKeyword != lastOffset )
472 				addToken( lastKeyword - lastOffset, Token.NULL );
473 			addToken( len, id );
474 			lastOffset = i;
475 		}
476 		lastKeyword = i1;
477 		return false;
478 	}
479 
480 	// Converts < EOF >, < 'EOF' >, etc to <EOF>
481 	private String createReadinString( char[] array, int start, int len )
482 	{
483 		int idx1 = start;
484 		int idx2 = start + len - 1;
485 
486 		while( ( idx1 <= idx2 ) && ( !Character.isLetterOrDigit( array[idx1] ) ) )
487 			idx1++ ;
488 
489 		while( ( idx1 <= idx2 ) && ( !Character.isLetterOrDigit( array[idx2] ) ) )
490 			idx2-- ;
491 
492 		return new String( array, idx1, idx2 - idx1 + 1 );
493 	}
494 
495 	private static KeywordMap perlKeywords;
496 
497 	private static KeywordMap getKeywords()
498 	{
499 		if( perlKeywords == null )
500 		{
501 			perlKeywords = new KeywordMap( false );
502 			perlKeywords.add( "my", Token.KEYWORD1 );
503 			perlKeywords.add( "local", Token.KEYWORD1 );
504 			perlKeywords.add( "new", Token.KEYWORD1 );
505 			perlKeywords.add( "if", Token.KEYWORD1 );
506 			perlKeywords.add( "until", Token.KEYWORD1 );
507 			perlKeywords.add( "while", Token.KEYWORD1 );
508 			perlKeywords.add( "elsif", Token.KEYWORD1 );
509 			perlKeywords.add( "else", Token.KEYWORD1 );
510 			perlKeywords.add( "eval", Token.KEYWORD1 );
511 			perlKeywords.add( "unless", Token.KEYWORD1 );
512 			perlKeywords.add( "foreach", Token.KEYWORD1 );
513 			perlKeywords.add( "continue", Token.KEYWORD1 );
514 			perlKeywords.add( "exit", Token.KEYWORD1 );
515 			perlKeywords.add( "die", Token.KEYWORD1 );
516 			perlKeywords.add( "last", Token.KEYWORD1 );
517 			perlKeywords.add( "goto", Token.KEYWORD1 );
518 			perlKeywords.add( "next", Token.KEYWORD1 );
519 			perlKeywords.add( "redo", Token.KEYWORD1 );
520 			perlKeywords.add( "goto", Token.KEYWORD1 );
521 			perlKeywords.add( "return", Token.KEYWORD1 );
522 			perlKeywords.add( "do", Token.KEYWORD1 );
523 			perlKeywords.add( "sub", Token.KEYWORD1 );
524 			perlKeywords.add( "use", Token.KEYWORD1 );
525 			perlKeywords.add( "require", Token.KEYWORD1 );
526 			perlKeywords.add( "package", Token.KEYWORD1 );
527 			perlKeywords.add( "BEGIN", Token.KEYWORD1 );
528 			perlKeywords.add( "END", Token.KEYWORD1 );
529 			perlKeywords.add( "eq", Token.OPERATOR );
530 			perlKeywords.add( "ne", Token.OPERATOR );
531 			perlKeywords.add( "not", Token.OPERATOR );
532 			perlKeywords.add( "and", Token.OPERATOR );
533 			perlKeywords.add( "or", Token.OPERATOR );
534 
535 			perlKeywords.add( "abs", Token.KEYWORD3 );
536 			perlKeywords.add( "accept", Token.KEYWORD3 );
537 			perlKeywords.add( "alarm", Token.KEYWORD3 );
538 			perlKeywords.add( "atan2", Token.KEYWORD3 );
539 			perlKeywords.add( "bind", Token.KEYWORD3 );
540 			perlKeywords.add( "binmode", Token.KEYWORD3 );
541 			perlKeywords.add( "bless", Token.KEYWORD3 );
542 			perlKeywords.add( "caller", Token.KEYWORD3 );
543 			perlKeywords.add( "chdir", Token.KEYWORD3 );
544 			perlKeywords.add( "chmod", Token.KEYWORD3 );
545 			perlKeywords.add( "chomp", Token.KEYWORD3 );
546 			perlKeywords.add( "chr", Token.KEYWORD3 );
547 			perlKeywords.add( "chroot", Token.KEYWORD3 );
548 			perlKeywords.add( "chown", Token.KEYWORD3 );
549 			perlKeywords.add( "closedir", Token.KEYWORD3 );
550 			perlKeywords.add( "close", Token.KEYWORD3 );
551 			perlKeywords.add( "connect", Token.KEYWORD3 );
552 			perlKeywords.add( "cos", Token.KEYWORD3 );
553 			perlKeywords.add( "crypt", Token.KEYWORD3 );
554 			perlKeywords.add( "dbmclose", Token.KEYWORD3 );
555 			perlKeywords.add( "dbmopen", Token.KEYWORD3 );
556 			perlKeywords.add( "defined", Token.KEYWORD3 );
557 			perlKeywords.add( "delete", Token.KEYWORD3 );
558 			perlKeywords.add( "die", Token.KEYWORD3 );
559 			perlKeywords.add( "dump", Token.KEYWORD3 );
560 			perlKeywords.add( "each", Token.KEYWORD3 );
561 			perlKeywords.add( "endgrent", Token.KEYWORD3 );
562 			perlKeywords.add( "endhostent", Token.KEYWORD3 );
563 			perlKeywords.add( "endnetent", Token.KEYWORD3 );
564 			perlKeywords.add( "endprotoent", Token.KEYWORD3 );
565 			perlKeywords.add( "endpwent", Token.KEYWORD3 );
566 			perlKeywords.add( "endservent", Token.KEYWORD3 );
567 			perlKeywords.add( "eof", Token.KEYWORD3 );
568 			perlKeywords.add( "exec", Token.KEYWORD3 );
569 			perlKeywords.add( "exists", Token.KEYWORD3 );
570 			perlKeywords.add( "exp", Token.KEYWORD3 );
571 			perlKeywords.add( "fctnl", Token.KEYWORD3 );
572 			perlKeywords.add( "fileno", Token.KEYWORD3 );
573 			perlKeywords.add( "flock", Token.KEYWORD3 );
574 			perlKeywords.add( "fork", Token.KEYWORD3 );
575 			perlKeywords.add( "format", Token.KEYWORD3 );
576 			perlKeywords.add( "formline", Token.KEYWORD3 );
577 			perlKeywords.add( "getc", Token.KEYWORD3 );
578 			perlKeywords.add( "getgrent", Token.KEYWORD3 );
579 			perlKeywords.add( "getgrgid", Token.KEYWORD3 );
580 			perlKeywords.add( "getgrnam", Token.KEYWORD3 );
581 			perlKeywords.add( "gethostbyaddr", Token.KEYWORD3 );
582 			perlKeywords.add( "gethostbyname", Token.KEYWORD3 );
583 			perlKeywords.add( "gethostent", Token.KEYWORD3 );
584 			perlKeywords.add( "getlogin", Token.KEYWORD3 );
585 			perlKeywords.add( "getnetbyaddr", Token.KEYWORD3 );
586 			perlKeywords.add( "getnetbyname", Token.KEYWORD3 );
587 			perlKeywords.add( "getnetent", Token.KEYWORD3 );
588 			perlKeywords.add( "getpeername", Token.KEYWORD3 );
589 			perlKeywords.add( "getpgrp", Token.KEYWORD3 );
590 			perlKeywords.add( "getppid", Token.KEYWORD3 );
591 			perlKeywords.add( "getpriority", Token.KEYWORD3 );
592 			perlKeywords.add( "getprotobyname", Token.KEYWORD3 );
593 			perlKeywords.add( "getprotobynumber", Token.KEYWORD3 );
594 			perlKeywords.add( "getprotoent", Token.KEYWORD3 );
595 			perlKeywords.add( "getpwent", Token.KEYWORD3 );
596 			perlKeywords.add( "getpwnam", Token.KEYWORD3 );
597 			perlKeywords.add( "getpwuid", Token.KEYWORD3 );
598 			perlKeywords.add( "getservbyname", Token.KEYWORD3 );
599 			perlKeywords.add( "getservbyport", Token.KEYWORD3 );
600 			perlKeywords.add( "getservent", Token.KEYWORD3 );
601 			perlKeywords.add( "getsockname", Token.KEYWORD3 );
602 			perlKeywords.add( "getsockopt", Token.KEYWORD3 );
603 			perlKeywords.add( "glob", Token.KEYWORD3 );
604 			perlKeywords.add( "gmtime", Token.KEYWORD3 );
605 			perlKeywords.add( "grep", Token.KEYWORD3 );
606 			perlKeywords.add( "hex", Token.KEYWORD3 );
607 			perlKeywords.add( "import", Token.KEYWORD3 );
608 			perlKeywords.add( "index", Token.KEYWORD3 );
609 			perlKeywords.add( "int", Token.KEYWORD3 );
610 			perlKeywords.add( "ioctl", Token.KEYWORD3 );
611 			perlKeywords.add( "join", Token.KEYWORD3 );
612 			perlKeywords.add( "keys", Token.KEYWORD3 );
613 			perlKeywords.add( "kill", Token.KEYWORD3 );
614 			perlKeywords.add( "lcfirst", Token.KEYWORD3 );
615 			perlKeywords.add( "lc", Token.KEYWORD3 );
616 			perlKeywords.add( "length", Token.KEYWORD3 );
617 			perlKeywords.add( "link", Token.KEYWORD3 );
618 			perlKeywords.add( "listen", Token.KEYWORD3 );
619 			perlKeywords.add( "log", Token.KEYWORD3 );
620 			perlKeywords.add( "localtime", Token.KEYWORD3 );
621 			perlKeywords.add( "lstat", Token.KEYWORD3 );
622 			perlKeywords.add( "map", Token.KEYWORD3 );
623 			perlKeywords.add( "mkdir", Token.KEYWORD3 );
624 			perlKeywords.add( "msgctl", Token.KEYWORD3 );
625 			perlKeywords.add( "msgget", Token.KEYWORD3 );
626 			perlKeywords.add( "msgrcv", Token.KEYWORD3 );
627 			perlKeywords.add( "no", Token.KEYWORD3 );
628 			perlKeywords.add( "oct", Token.KEYWORD3 );
629 			perlKeywords.add( "opendir", Token.KEYWORD3 );
630 			perlKeywords.add( "open", Token.KEYWORD3 );
631 			perlKeywords.add( "ord", Token.KEYWORD3 );
632 			perlKeywords.add( "pack", Token.KEYWORD3 );
633 			perlKeywords.add( "pipe", Token.KEYWORD3 );
634 			perlKeywords.add( "pop", Token.KEYWORD3 );
635 			perlKeywords.add( "pos", Token.KEYWORD3 );
636 			perlKeywords.add( "printf", Token.KEYWORD3 );
637 			perlKeywords.add( "print", Token.KEYWORD3 );
638 			perlKeywords.add( "push", Token.KEYWORD3 );
639 			perlKeywords.add( "quotemeta", Token.KEYWORD3 );
640 			perlKeywords.add( "rand", Token.KEYWORD3 );
641 			perlKeywords.add( "readdir", Token.KEYWORD3 );
642 			perlKeywords.add( "read", Token.KEYWORD3 );
643 			perlKeywords.add( "readlink", Token.KEYWORD3 );
644 			perlKeywords.add( "recv", Token.KEYWORD3 );
645 			perlKeywords.add( "ref", Token.KEYWORD3 );
646 			perlKeywords.add( "rename", Token.KEYWORD3 );
647 			perlKeywords.add( "reset", Token.KEYWORD3 );
648 			perlKeywords.add( "reverse", Token.KEYWORD3 );
649 			perlKeywords.add( "rewinddir", Token.KEYWORD3 );
650 			perlKeywords.add( "rindex", Token.KEYWORD3 );
651 			perlKeywords.add( "rmdir", Token.KEYWORD3 );
652 			perlKeywords.add( "scalar", Token.KEYWORD3 );
653 			perlKeywords.add( "seekdir", Token.KEYWORD3 );
654 			perlKeywords.add( "seek", Token.KEYWORD3 );
655 			perlKeywords.add( "select", Token.KEYWORD3 );
656 			perlKeywords.add( "semctl", Token.KEYWORD3 );
657 			perlKeywords.add( "semget", Token.KEYWORD3 );
658 			perlKeywords.add( "semop", Token.KEYWORD3 );
659 			perlKeywords.add( "send", Token.KEYWORD3 );
660 			perlKeywords.add( "setgrent", Token.KEYWORD3 );
661 			perlKeywords.add( "sethostent", Token.KEYWORD3 );
662 			perlKeywords.add( "setnetent", Token.KEYWORD3 );
663 			perlKeywords.add( "setpgrp", Token.KEYWORD3 );
664 			perlKeywords.add( "setpriority", Token.KEYWORD3 );
665 			perlKeywords.add( "setprotoent", Token.KEYWORD3 );
666 			perlKeywords.add( "setpwent", Token.KEYWORD3 );
667 			perlKeywords.add( "setsockopt", Token.KEYWORD3 );
668 			perlKeywords.add( "shift", Token.KEYWORD3 );
669 			perlKeywords.add( "shmctl", Token.KEYWORD3 );
670 			perlKeywords.add( "shmget", Token.KEYWORD3 );
671 			perlKeywords.add( "shmread", Token.KEYWORD3 );
672 			perlKeywords.add( "shmwrite", Token.KEYWORD3 );
673 			perlKeywords.add( "shutdown", Token.KEYWORD3 );
674 			perlKeywords.add( "sin", Token.KEYWORD3 );
675 			perlKeywords.add( "sleep", Token.KEYWORD3 );
676 			perlKeywords.add( "socket", Token.KEYWORD3 );
677 			perlKeywords.add( "socketpair", Token.KEYWORD3 );
678 			perlKeywords.add( "sort", Token.KEYWORD3 );
679 			perlKeywords.add( "splice", Token.KEYWORD3 );
680 			perlKeywords.add( "split", Token.KEYWORD3 );
681 			perlKeywords.add( "sprintf", Token.KEYWORD3 );
682 			perlKeywords.add( "sqrt", Token.KEYWORD3 );
683 			perlKeywords.add( "srand", Token.KEYWORD3 );
684 			perlKeywords.add( "stat", Token.KEYWORD3 );
685 			perlKeywords.add( "study", Token.KEYWORD3 );
686 			perlKeywords.add( "substr", Token.KEYWORD3 );
687 			perlKeywords.add( "symlink", Token.KEYWORD3 );
688 			perlKeywords.add( "syscall", Token.KEYWORD3 );
689 			perlKeywords.add( "sysopen", Token.KEYWORD3 );
690 			perlKeywords.add( "sysread", Token.KEYWORD3 );
691 			perlKeywords.add( "syswrite", Token.KEYWORD3 );
692 			perlKeywords.add( "telldir", Token.KEYWORD3 );
693 			perlKeywords.add( "tell", Token.KEYWORD3 );
694 			perlKeywords.add( "tie", Token.KEYWORD3 );
695 			perlKeywords.add( "tied", Token.KEYWORD3 );
696 			perlKeywords.add( "time", Token.KEYWORD3 );
697 			perlKeywords.add( "times", Token.KEYWORD3 );
698 			perlKeywords.add( "truncate", Token.KEYWORD3 );
699 			perlKeywords.add( "uc", Token.KEYWORD3 );
700 			perlKeywords.add( "ucfirst", Token.KEYWORD3 );
701 			perlKeywords.add( "umask", Token.KEYWORD3 );
702 			perlKeywords.add( "undef", Token.KEYWORD3 );
703 			perlKeywords.add( "unlink", Token.KEYWORD3 );
704 			perlKeywords.add( "unpack", Token.KEYWORD3 );
705 			perlKeywords.add( "unshift", Token.KEYWORD3 );
706 			perlKeywords.add( "untie", Token.KEYWORD3 );
707 			perlKeywords.add( "utime", Token.KEYWORD3 );
708 			perlKeywords.add( "values", Token.KEYWORD3 );
709 			perlKeywords.add( "vec", Token.KEYWORD3 );
710 			perlKeywords.add( "wait", Token.KEYWORD3 );
711 			perlKeywords.add( "waitpid", Token.KEYWORD3 );
712 			perlKeywords.add( "wantarray", Token.KEYWORD3 );
713 			perlKeywords.add( "warn", Token.KEYWORD3 );
714 			perlKeywords.add( "write", Token.KEYWORD3 );
715 
716 			perlKeywords.add( "m", S_ONE );
717 			perlKeywords.add( "q", S_ONE );
718 			perlKeywords.add( "qq", S_ONE );
719 			perlKeywords.add( "qw", S_ONE );
720 			perlKeywords.add( "qx", S_ONE );
721 			perlKeywords.add( "s", S_TWO );
722 			perlKeywords.add( "tr", S_TWO );
723 			perlKeywords.add( "y", S_TWO );
724 		}
725 		return perlKeywords;
726 	}
727 }