View Javadoc

1   /*
2    * EiffelTokenMarker.java - Eiffel token marker
3    * Copyright (C) 1999 Slava Pestov
4    * Copyright (C) 1999 Artur Biesiadowski
5    *
6    * You may use and modify this package for any purpose. Redistribution is
7    * permitted, in both source and binary form, provided that this notice
8    * remains intact in all source distributions of this package.
9    */
10  
11  package org.syntax.jedit.tokenmarker;
12  
13  import javax.swing.text.Segment;
14  
15  import org.syntax.jedit.KeywordMap;
16  
17  /***
18   * Eiffel token Marker.
19   * 
20   * @author Artur Biesiadowski
21   */
22  public class EiffelTokenMarker extends TokenMarker
23  {
24  
25  	public EiffelTokenMarker()
26  	{
27  		this.keywords = getKeywords();
28  	}
29  
30  	public byte markTokensImpl( byte token, Segment line, int lineIndex )
31  	{
32  		char[] array = line.array;
33  		int offset = line.offset;
34  		lastOffset = offset;
35  		lastKeyword = offset;
36  		int length = line.count + offset;
37  		boolean backslash = false;
38  
39  		loop : for( int i = offset; i < length; i++ )
40  		{
41  			int i1 = ( i + 1 );
42  
43  			char c = array[i];
44  			if( c == '%' )
45  			{
46  				backslash = !backslash;
47  				continue;
48  			}
49  
50  			switch( token )
51  			{
52  			case Token.NULL :
53  				switch( c )
54  				{
55  				case '"' :
56  					doKeyword( line, i, c );
57  					if( backslash )
58  						backslash = false;
59  					else
60  					{
61  						addToken( i - lastOffset, token );
62  						token = Token.LITERAL1;
63  						lastOffset = lastKeyword = i;
64  					}
65  					break;
66  				case '\'' :
67  					doKeyword( line, i, c );
68  					if( backslash )
69  						backslash = false;
70  					else
71  					{
72  						addToken( i - lastOffset, token );
73  						token = Token.LITERAL2;
74  						lastOffset = lastKeyword = i;
75  					}
76  					break;
77  				case ':' :
78  					if( lastKeyword == offset )
79  					{
80  						if( doKeyword( line, i, c ) )
81  							break;
82  						backslash = false;
83  						addToken( i1 - lastOffset, Token.LABEL );
84  						lastOffset = lastKeyword = i1;
85  					}
86  					else if( doKeyword( line, i, c ) )
87  						break;
88  					break;
89  				case '-' :
90  					backslash = false;
91  					doKeyword( line, i, c );
92  					if( length - i > 1 )
93  					{
94  						switch( array[i1] )
95  						{
96  						case '-' :
97  							addToken( i - lastOffset, token );
98  							addToken( length - i, Token.COMMENT1 );
99  							lastOffset = lastKeyword = length;
100 							break loop;
101 						}
102 					}
103 					break;
104 				default :
105 					backslash = false;
106 					if( !Character.isLetterOrDigit( c ) && c != '_' )
107 						doKeyword( line, i, c );
108 					break;
109 				}
110 				break;
111 			case Token.COMMENT1 :
112 			case Token.COMMENT2 :
113 				throw new RuntimeException( "Wrong eiffel parser state" );
114 			case Token.LITERAL1 :
115 				if( backslash )
116 					backslash = false;
117 				else if( c == '"' )
118 				{
119 					addToken( i1 - lastOffset, token );
120 					token = Token.NULL;
121 					lastOffset = lastKeyword = i1;
122 				}
123 				break;
124 			case Token.LITERAL2 :
125 				if( backslash )
126 					backslash = false;
127 				else if( c == '\'' )
128 				{
129 					addToken( i1 - lastOffset, Token.LITERAL1 );
130 					token = Token.NULL;
131 					lastOffset = lastKeyword = i1;
132 				}
133 				break;
134 			default :
135 				throw new InternalError( "Invalid state: " + token );
136 			}
137 		}
138 
139 		if( token == Token.NULL )
140 			doKeyword( line, length, '\0' );
141 
142 		switch( token )
143 		{
144 		case Token.LITERAL1 :
145 		case Token.LITERAL2 :
146 			addToken( length - lastOffset, Token.INVALID );
147 			token = Token.NULL;
148 			break;
149 		case Token.KEYWORD2 :
150 			addToken( length - lastOffset, token );
151 			if( !backslash )
152 				token = Token.NULL;
153 		default :
154 			addToken( length - lastOffset, token );
155 			break;
156 		}
157 
158 		return token;
159 	}
160 
161 	public static KeywordMap getKeywords()
162 	{
163 		if( eiffelKeywords == null )
164 		{
165 			eiffelKeywords = new KeywordMap( true );
166 			eiffelKeywords.add( "alias", Token.KEYWORD1 );
167 			eiffelKeywords.add( "all", Token.KEYWORD1 );
168 			eiffelKeywords.add( "and", Token.KEYWORD1 );
169 			eiffelKeywords.add( "as", Token.KEYWORD1 );
170 			eiffelKeywords.add( "check", Token.KEYWORD1 );
171 			eiffelKeywords.add( "class", Token.KEYWORD1 );
172 			eiffelKeywords.add( "creation", Token.KEYWORD1 );
173 			eiffelKeywords.add( "debug", Token.KEYWORD1 );
174 			eiffelKeywords.add( "deferred", Token.KEYWORD1 );
175 			eiffelKeywords.add( "do", Token.KEYWORD1 );
176 			eiffelKeywords.add( "else", Token.KEYWORD1 );
177 			eiffelKeywords.add( "elseif", Token.KEYWORD1 );
178 			eiffelKeywords.add( "end", Token.KEYWORD1 );
179 			eiffelKeywords.add( "ensure", Token.KEYWORD1 );
180 			eiffelKeywords.add( "expanded", Token.KEYWORD1 );
181 			eiffelKeywords.add( "export", Token.KEYWORD1 );
182 			eiffelKeywords.add( "external", Token.KEYWORD1 );
183 			eiffelKeywords.add( "feature", Token.KEYWORD1 );
184 			eiffelKeywords.add( "from", Token.KEYWORD1 );
185 			eiffelKeywords.add( "frozen", Token.KEYWORD1 );
186 			eiffelKeywords.add( "if", Token.KEYWORD1 );
187 			eiffelKeywords.add( "implies", Token.KEYWORD1 );
188 			eiffelKeywords.add( "indexing", Token.KEYWORD1 );
189 			eiffelKeywords.add( "infix", Token.KEYWORD1 );
190 			eiffelKeywords.add( "inherit", Token.KEYWORD1 );
191 			eiffelKeywords.add( "inspect", Token.KEYWORD1 );
192 			eiffelKeywords.add( "invariant", Token.KEYWORD1 );
193 			eiffelKeywords.add( "is", Token.KEYWORD1 );
194 			eiffelKeywords.add( "like", Token.KEYWORD1 );
195 			eiffelKeywords.add( "local", Token.KEYWORD1 );
196 			eiffelKeywords.add( "loop", Token.KEYWORD1 );
197 			eiffelKeywords.add( "not", Token.KEYWORD1 );
198 			eiffelKeywords.add( "obsolete", Token.KEYWORD1 );
199 			eiffelKeywords.add( "old", Token.KEYWORD1 );
200 			eiffelKeywords.add( "once", Token.KEYWORD1 );
201 			eiffelKeywords.add( "or", Token.KEYWORD1 );
202 			eiffelKeywords.add( "prefix", Token.KEYWORD1 );
203 			eiffelKeywords.add( "redefine", Token.KEYWORD1 );
204 			eiffelKeywords.add( "rename", Token.KEYWORD1 );
205 			eiffelKeywords.add( "require", Token.KEYWORD1 );
206 			eiffelKeywords.add( "rescue", Token.KEYWORD1 );
207 			eiffelKeywords.add( "retry", Token.KEYWORD1 );
208 			eiffelKeywords.add( "select", Token.KEYWORD1 );
209 			eiffelKeywords.add( "separate", Token.KEYWORD1 );
210 			eiffelKeywords.add( "then", Token.KEYWORD1 );
211 			eiffelKeywords.add( "undefine", Token.KEYWORD1 );
212 			eiffelKeywords.add( "until", Token.KEYWORD1 );
213 			eiffelKeywords.add( "variant", Token.KEYWORD1 );
214 			eiffelKeywords.add( "when", Token.KEYWORD1 );
215 			eiffelKeywords.add( "xor", Token.KEYWORD1 );
216 
217 			eiffelKeywords.add( "current", Token.LITERAL2 );
218 			eiffelKeywords.add( "false", Token.LITERAL2 );
219 			eiffelKeywords.add( "precursor", Token.LITERAL2 );
220 			eiffelKeywords.add( "result", Token.LITERAL2 );
221 			eiffelKeywords.add( "strip", Token.LITERAL2 );
222 			eiffelKeywords.add( "true", Token.LITERAL2 );
223 			eiffelKeywords.add( "unique", Token.LITERAL2 );
224 			eiffelKeywords.add( "void", Token.LITERAL2 );
225 
226 		}
227 		return eiffelKeywords;
228 	}
229 
230 	// private members
231 	private static KeywordMap eiffelKeywords;
232 
233 	private boolean cpp;
234 	private KeywordMap keywords;
235 	private int lastOffset;
236 	private int lastKeyword;
237 
238 	private boolean doKeyword( Segment line, int i, char c )
239 	{
240 		int i1 = i + 1;
241 		boolean klassname = false;
242 
243 		int len = i - lastKeyword;
244 		byte id = keywords.lookup( line, lastKeyword, len );
245 		if( id == Token.NULL )
246 		{
247 			klassname = true;
248 			for( int at = lastKeyword; at < lastKeyword + len; at++ )
249 			{
250 				char ch = line.array[at];
251 				if( ch != '_' && !Character.isUpperCase( ch ) )
252 				{
253 					klassname = false;
254 					break;
255 				}
256 			}
257 			if( klassname )
258 				id = Token.KEYWORD3;
259 		}
260 
261 		if( id != Token.NULL )
262 		{
263 			if( lastKeyword != lastOffset )
264 				addToken( lastKeyword - lastOffset, Token.NULL );
265 			addToken( len, id );
266 			lastOffset = i;
267 		}
268 		lastKeyword = i1;
269 		return false;
270 	}
271 }