1
2
3
4
5
6
7
8
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
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 }