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)
133 						&& c != '_')
134 						doKeyword(line,i,c);
135 					break;
136 				}
137 				break;
138 			case Token.COMMENT1:
139 			case Token.COMMENT2:
140 				backslash = false;
141 				if(c == '*' && length - i > 1)
142 				{
143 					if(array[i1] == '/')
144 					{
145 						i++;
146 						addToken((i+1) - lastOffset,token);
147 						token = Token.NULL;
148 						lastOffset = lastKeyword = i+1;
149 					}
150 				}
151 				break;
152 			case Token.LITERAL1:
153 				if(backslash)
154 					backslash = false;
155 				else if(c == '"')
156 				{
157 					addToken(i1 - lastOffset,token);
158 					token = Token.NULL;
159 					lastOffset = lastKeyword = i1;
160 				}
161 				break;
162 			case Token.LITERAL2:
163 				if(backslash)
164 					backslash = false;
165 				else if(c == '\'')
166 				{
167 					addToken(i1 - lastOffset,Token.LITERAL1);
168 					token = Token.NULL;
169 					lastOffset = lastKeyword = i1;
170 				}
171 				break;
172 			default:
173 				throw new InternalError("Invalid state: "
174 					+ token);
175 			}
176 		}
177 
178 		if(token == Token.NULL)
179 			doKeyword(line,length,'\0');
180 
181 		switch(token)
182 		{
183 		case Token.LITERAL1:
184 		case Token.LITERAL2:
185 			addToken(length - lastOffset,Token.INVALID);
186 			token = Token.NULL;
187 			break;
188 		case Token.KEYWORD2:
189 			addToken(length - lastOffset,token);
190 			if(!backslash)
191 				token = Token.NULL;
192 		default:
193 			addToken(length - lastOffset,token);
194 			break;
195 		}
196 
197 		return token;
198 	}
199 
200 	public static KeywordMap getKeywords()
201 	{
202 		if(cKeywords == null)
203 		{
204 			cKeywords = new KeywordMap(false);
205 			cKeywords.add("char",Token.KEYWORD3);
206 			cKeywords.add("double",Token.KEYWORD3);
207 			cKeywords.add("enum",Token.KEYWORD3);
208 			cKeywords.add("float",Token.KEYWORD3);
209 			cKeywords.add("int",Token.KEYWORD3);
210 			cKeywords.add("long",Token.KEYWORD3);
211 			cKeywords.add("short",Token.KEYWORD3);
212 			cKeywords.add("signed",Token.KEYWORD3);
213 			cKeywords.add("struct",Token.KEYWORD3);
214 			cKeywords.add("typedef",Token.KEYWORD3);
215 			cKeywords.add("union",Token.KEYWORD3);
216 			cKeywords.add("unsigned",Token.KEYWORD3);
217 			cKeywords.add("void",Token.KEYWORD3);
218 			cKeywords.add("auto",Token.KEYWORD1);
219 			cKeywords.add("const",Token.KEYWORD1);
220 			cKeywords.add("extern",Token.KEYWORD1);
221 			cKeywords.add("register",Token.KEYWORD1);
222 			cKeywords.add("static",Token.KEYWORD1);
223 			cKeywords.add("volatile",Token.KEYWORD1);
224 			cKeywords.add("break",Token.KEYWORD1);
225 			cKeywords.add("case",Token.KEYWORD1);
226 			cKeywords.add("continue",Token.KEYWORD1);
227 			cKeywords.add("default",Token.KEYWORD1);
228 			cKeywords.add("do",Token.KEYWORD1);
229 			cKeywords.add("else",Token.KEYWORD1);
230 			cKeywords.add("for",Token.KEYWORD1);
231 			cKeywords.add("goto",Token.KEYWORD1);
232 			cKeywords.add("if",Token.KEYWORD1);
233 			cKeywords.add("return",Token.KEYWORD1);
234 			cKeywords.add("sizeof",Token.KEYWORD1);
235 			cKeywords.add("switch",Token.KEYWORD1);
236 			cKeywords.add("while",Token.KEYWORD1);
237 			cKeywords.add("asm",Token.KEYWORD2);
238 			cKeywords.add("asmlinkage",Token.KEYWORD2);
239 			cKeywords.add("far",Token.KEYWORD2);
240 			cKeywords.add("huge",Token.KEYWORD2);
241 			cKeywords.add("inline",Token.KEYWORD2);
242 			cKeywords.add("near",Token.KEYWORD2);
243 			cKeywords.add("pascal",Token.KEYWORD2);
244 			cKeywords.add("true",Token.LITERAL2);
245 			cKeywords.add("false",Token.LITERAL2);
246 			cKeywords.add("NULL",Token.LITERAL2);
247 		}
248 		return cKeywords;
249 	}
250 
251 	// private members
252 	private static KeywordMap cKeywords;
253 
254 	private boolean cpp;
255 	private KeywordMap keywords;
256 	private int lastOffset;
257 	private int lastKeyword;
258 
259 	private boolean doKeyword(Segment line, int i, char c)
260 	{
261 		int i1 = i+1;
262 
263 		int len = i - lastKeyword;
264 		byte id = keywords.lookup(line,lastKeyword,len);
265 		if(id != Token.NULL)
266 		{
267 			if(lastKeyword != lastOffset)
268 				addToken(lastKeyword - lastOffset,Token.NULL);
269 			addToken(len,id);
270 			lastOffset = i;
271 		}
272 		lastKeyword = i1;
273 		return false;
274 	}
275 }