1
2
3
4
5
6
7
8
9
10 package org.syntax.jedit.tokenmarker;
11
12 import javax.swing.text.Segment;
13
14 import org.syntax.jedit.KeywordMap;
15
16 /***
17 * C token marker.
18 *
19 * @author Slava Pestov
20 * @version $Id: CTokenMarker.java,v 1.34 1999/12/13 03:40:29 sp Exp $
21 */
22 public class CTokenMarker extends TokenMarker
23 {
24 public CTokenMarker()
25 {
26 this( true, getKeywords() );
27 }
28
29 public CTokenMarker( boolean cpp, KeywordMap keywords )
30 {
31 this.cpp = cpp;
32 this.keywords = keywords;
33 }
34
35 public byte markTokensImpl( byte token, Segment line, int lineIndex )
36 {
37 char[] array = line.array;
38 int offset = line.offset;
39 lastOffset = offset;
40 lastKeyword = offset;
41 int length = line.count + offset;
42 boolean backslash = false;
43
44 loop : for( int i = offset; i < length; i++ )
45 {
46 int i1 = ( i + 1 );
47
48 char c = array[i];
49 if( c == '//' )
50 {
51 backslash = !backslash;
52 continue;
53 }
54
55 switch( token )
56 {
57 case Token.NULL :
58 switch( c )
59 {
60 case '#' :
61 if( backslash )
62 backslash = false;
63 else if( cpp )
64 {
65 if( doKeyword( line, i, c ) )
66 break;
67 addToken( i - lastOffset, token );
68 addToken( length - i, Token.KEYWORD2 );
69 lastOffset = lastKeyword = length;
70 break loop;
71 }
72 break;
73 case '"' :
74 doKeyword( line, i, c );
75 if( backslash )
76 backslash = false;
77 else
78 {
79 addToken( i - lastOffset, token );
80 token = Token.LITERAL1;
81 lastOffset = lastKeyword = i;
82 }
83 break;
84 case '\'' :
85 doKeyword( line, i, c );
86 if( backslash )
87 backslash = false;
88 else
89 {
90 addToken( i - lastOffset, token );
91 token = Token.LITERAL2;
92 lastOffset = lastKeyword = i;
93 }
94 break;
95 case ':' :
96 if( lastKeyword == offset )
97 {
98 if( doKeyword( line, i, c ) )
99 break;
100 backslash = false;
101 addToken( i1 - lastOffset, Token.LABEL );
102 lastOffset = lastKeyword = i1;
103 }
104 else if( doKeyword( line, i, c ) )
105 break;
106 break;
107 case '/' :
108 backslash = false;
109 doKeyword( line, i, c );
110 if( length - i > 1 )
111 {
112 switch( array[i1] )
113 {
114 case '*' :
115 addToken( i - lastOffset, token );
116 lastOffset = lastKeyword = i;
117 if( length - i > 2 && array[i + 2] == '*' )
118 token = Token.COMMENT2;
119 else
120 token = Token.COMMENT1;
121 break;
122 case '/' :
123 addToken( i - lastOffset, token );
124 addToken( length - i, Token.COMMENT1 );
125 lastOffset = lastKeyword = length;
126 break loop;
127 }
128 }
129 break;
130 default :
131 backslash = false;
132 if( !Character.isLetterOrDigit( c ) && c != '_' )
133 doKeyword( line, i, c );
134 break;
135 }
136 break;
137 case Token.COMMENT1 :
138 case Token.COMMENT2 :
139 backslash = false;
140 if( c == '*' && length - i > 1 )
141 {
142 if( array[i1] == '/' )
143 {
144 i++ ;
145 addToken( ( i + 1 ) - lastOffset, token );
146 token = Token.NULL;
147 lastOffset = lastKeyword = i + 1;
148 }
149 }
150 break;
151 case Token.LITERAL1 :
152 if( backslash )
153 backslash = false;
154 else if( c == '"' )
155 {
156 addToken( i1 - lastOffset, token );
157 token = Token.NULL;
158 lastOffset = lastKeyword = i1;
159 }
160 break;
161 case Token.LITERAL2 :
162 if( backslash )
163 backslash = false;
164 else if( c == '\'' )
165 {
166 addToken( i1 - lastOffset, Token.LITERAL1 );
167 token = Token.NULL;
168 lastOffset = lastKeyword = i1;
169 }
170 break;
171 default :
172 throw new InternalError( "Invalid state: " + token );
173 }
174 }
175
176 if( token == Token.NULL )
177 doKeyword( line, length, '\0' );
178
179 switch( token )
180 {
181 case Token.LITERAL1 :
182 case Token.LITERAL2 :
183 addToken( length - lastOffset, Token.INVALID );
184 token = Token.NULL;
185 break;
186 case Token.KEYWORD2 :
187 addToken( length - lastOffset, token );
188 if( !backslash )
189 token = Token.NULL;
190 default :
191 addToken( length - lastOffset, token );
192 break;
193 }
194
195 return token;
196 }
197
198 public static KeywordMap getKeywords()
199 {
200 if( cKeywords == null )
201 {
202 cKeywords = new KeywordMap( false );
203 cKeywords.add( "char", Token.KEYWORD3 );
204 cKeywords.add( "double", Token.KEYWORD3 );
205 cKeywords.add( "enum", Token.KEYWORD3 );
206 cKeywords.add( "float", Token.KEYWORD3 );
207 cKeywords.add( "int", Token.KEYWORD3 );
208 cKeywords.add( "long", Token.KEYWORD3 );
209 cKeywords.add( "short", Token.KEYWORD3 );
210 cKeywords.add( "signed", Token.KEYWORD3 );
211 cKeywords.add( "struct", Token.KEYWORD3 );
212 cKeywords.add( "typedef", Token.KEYWORD3 );
213 cKeywords.add( "union", Token.KEYWORD3 );
214 cKeywords.add( "unsigned", Token.KEYWORD3 );
215 cKeywords.add( "void", Token.KEYWORD3 );
216 cKeywords.add( "auto", Token.KEYWORD1 );
217 cKeywords.add( "const", Token.KEYWORD1 );
218 cKeywords.add( "extern", Token.KEYWORD1 );
219 cKeywords.add( "register", Token.KEYWORD1 );
220 cKeywords.add( "static", Token.KEYWORD1 );
221 cKeywords.add( "volatile", Token.KEYWORD1 );
222 cKeywords.add( "break", Token.KEYWORD1 );
223 cKeywords.add( "case", Token.KEYWORD1 );
224 cKeywords.add( "continue", Token.KEYWORD1 );
225 cKeywords.add( "default", Token.KEYWORD1 );
226 cKeywords.add( "do", Token.KEYWORD1 );
227 cKeywords.add( "else", Token.KEYWORD1 );
228 cKeywords.add( "for", Token.KEYWORD1 );
229 cKeywords.add( "goto", Token.KEYWORD1 );
230 cKeywords.add( "if", Token.KEYWORD1 );
231 cKeywords.add( "return", Token.KEYWORD1 );
232 cKeywords.add( "sizeof", Token.KEYWORD1 );
233 cKeywords.add( "switch", Token.KEYWORD1 );
234 cKeywords.add( "while", Token.KEYWORD1 );
235 cKeywords.add( "asm", Token.KEYWORD2 );
236 cKeywords.add( "asmlinkage", Token.KEYWORD2 );
237 cKeywords.add( "far", Token.KEYWORD2 );
238 cKeywords.add( "huge", Token.KEYWORD2 );
239 cKeywords.add( "inline", Token.KEYWORD2 );
240 cKeywords.add( "near", Token.KEYWORD2 );
241 cKeywords.add( "pascal", Token.KEYWORD2 );
242 cKeywords.add( "true", Token.LITERAL2 );
243 cKeywords.add( "false", Token.LITERAL2 );
244 cKeywords.add( "NULL", Token.LITERAL2 );
245 }
246 return cKeywords;
247 }
248
249
250 private static KeywordMap cKeywords;
251
252 private boolean cpp;
253 private KeywordMap keywords;
254 private int lastOffset;
255 private int lastKeyword;
256
257 private boolean doKeyword( Segment line, int i, char c )
258 {
259 int i1 = i + 1;
260
261 int len = i - lastKeyword;
262 byte id = keywords.lookup( line, lastKeyword, len );
263 if( id != Token.NULL )
264 {
265 if( lastKeyword != lastOffset )
266 addToken( lastKeyword - lastOffset, Token.NULL );
267 addToken( len, id );
268 lastOffset = i;
269 }
270 lastKeyword = i1;
271 return false;
272 }
273 }