View Javadoc

1   /*
2    * CTokenMarker.java - C 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  
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 	// private members
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 }