Source code: ide/VerilogScanner.java
1 /* **********************************
2 File:ColorProvider.java
3 Author: Alec(alecu@kermit.cs.pub.ro)
4 Creted on Sun Jul 4 04:15:31 EDT 1999
5 Comments: Part of the vIDE Project
6 Copyright 1999 the vIDE Team.
7 ***********************************/
8
9 package ide;
10
11 import java.awt.*;
12 import javax.swing.*;
13 import javax.swing.text.Segment;
14 /**
15 * Provides a color for each verilog token
16 */
17
18 class VerilogScanner {
19
20 /*
21 * don't forget to update the colors if you modify
22 * the indexes !
23 */
24 public static final int tokSLComm = 0;
25 public static final int tokMLComm = 1;
26 public static final int tokBinNr = 2;
27 public static final int tokOctNr = 3;
28 public static final int tokDecNr = 4;
29 public static final int tokHexNr = 5;
30 public static final int tokFloatNr = 6;
31 public static final int tokKeyword = 7;
32 public static final int tokPreproc = 8;
33 public static final int tokSysTask = 9;
34 public static final int tokSeparator = 10;
35 public static final int tokString = 11;
36 public static final int tokStuff = 12;
37
38 int tokType;
39 int tokLen;
40 /**
41 * true if an open "/*" was found on this line
42 */
43 boolean openComment;
44
45 char a[];
46 int start;
47 int stop;
48
49 static String keywords[] =
50 {
51 "always", "and", "assign",
52
53 "begin", "buf", "bufif0", "bufif1",
54
55 "case", "casex", "casez", "cmos",
56
57 "deassign", "default", "defparam", "disable",
58
59 "edge", "else", "end", "endcase", "endmodule", "endfunction",
60 "endprimitive", "endspecify", "endtable", "endtask", "event",
61
62 "for", "force", "forever", "fork", "function",
63
64 "highz0", "highz1",
65
66 "if", "ifnone", "initial", "inout", "input", "integer",
67
68 "join",
69
70 "large",
71
72 "macromodule", "medium", "module",
73
74 "nand", "negedge", "nmos", "nor", "not", "notif0", "notif1",
75
76 "or", "output",
77
78 "parameter", "pmos", "posedge", "primitive", "pull0", "pull1",
79 "pullup", "pulldown",
80
81 "rcmos", "real", "realtime", "reg", "release", "repeat", "rnmos",
82 "rpmos", "rtran", "rtranif0", "rtranif1",
83
84 "scalared", "small", "specify", "specparam", "strong0", "strong1",
85 "supply1", "supply0",
86
87 "table", "task", "time", "tran", "tranif0", "tranif1", "tri", "tri0",
88 "tri1", "triand", "trior", "trireg",
89
90 "vectored",
91
92 "wait", "wand", "weak0", "weak1", "while", "wire", "wor",
93
94 "xnor", "xor"
95 };
96
97
98 static int kSize = keywords.length;
99
100 /**
101 * Stores vectors alphabetically ordered. Each of these vectors
102 * contains all the keywords that start with the same letter.
103 * There should be no more than 30
104 * sorts of starting characters and 15 keywords starting with the same
105 * letter.
106 */
107 static char keys[][][] =new char[30][15][];
108
109 /**
110 * How many keys are into each vector.
111 */
112 static int keysLengths[] = new int[30];
113
114 static {
115 /*
116 * fetches tthe keywords into keys, which is more
117 * a more reliable structure for the first
118 * matchloop into matchKeyword.
119 */
120 char [] buffer;
121 for(int i = 0; i < kSize; i++) {
122 buffer = keywords[i].toCharArray();
123 keys[buffer[0]-'a'][keysLengths[buffer[0] - 'a']++] = buffer;
124 }
125 }
126
127 char [][] keyBuffer1, keyBuffer2;
128
129 VerilogScanner () {
130 // 20 shoul be enough for holding all keywords
131 //that start with the same letter
132 keyBuffer1 = new char[20][];
133 keyBuffer2 = new char[20][];
134 }
135
136 /**
137 * The pointer inside the current segment
138 */
139 int c;
140
141 final void init(Segment s) {
142 a = s.array;
143 start = c = s.offset;
144 stop = start + s.count -1;
145 }
146
147
148 /**
149 * no more tears !
150 */
151 final boolean noMoreTokens() {
152 return c > stop;
153 }
154
155 final boolean getToken() {
156 if (c > stop) return false;
157 //c <= stop:
158 int lastC = c;
159 char curChar = a[c];
160 /*System.out.println("current char: " + curChar + " hex: " +
161 Integer.toHexString(curChar));*/
162
163 switch(curChar) {
164 case ' ':
165 case '\t':
166 case '\n':
167 case '\r':
168 tokType = tokStuff;
169 do {
170 c++;
171 if (c > stop) break;
172 curChar = a[c];
173 } while((curChar == ' ') || (curChar == '\t') ||
174 (curChar == '\n') || (curChar == '\r'));
175
176 break;
177 case '-':
178 case '+':
179 case ':':
180 case '*':
181 case '&':
182 case '<':
183 case '>':
184 case '!':
185 case '@':
186 case '#':
187 case '%':
188 case '^':
189 case '(':
190 case ')':
191 case '{':
192 case '}':
193 case '[':
194 case ']':
195 case '=':
196 case '|':
197 case ';':
198 case '.':
199 case ',':
200 tokType = tokSeparator;
201 c++;
202 break;
203 case '0':
204 case '1':
205 case '2':
206 case '3':
207 case '4':
208 case '5':
209 case '6':
210 case '7':
211 case '8':
212 case '9':
213 case '\'':
214 tokType = tokDecNr;
215 boolean cont;
216 loop1:
217 do {
218 c++;
219 cont = false;
220 if (c > stop) break;
221 curChar = a[c];
222 switch (curChar) {
223 case 'b':
224 case 'B':
225 tokType = tokDecNr;
226 cont = true;
227 case 'o':
228 case 'O':
229 tokType = tokOctNr;
230 cont = true;
231 case 'd':
232 case 'D':
233 cont = true;
234 case 'h':
235 case 'H':
236 tokType = tokHexNr;
237 cont = true;;
238 case 'e':
239 case 'E':
240 tokType = tokFloatNr;
241 cont = true;
242 }
243 } while(cont || isDigit(curChar));
244 break;
245 case '/':
246 c++;
247 if (c > stop) break;
248 curChar = a[c];
249 switch(curChar) {
250 case '/':
251 tokType = tokSLComm;
252 c = stop + 1;
253 break;
254 case '*':
255 tokType = tokMLComm;
256 openComment = false;
257 if (c < stop) {
258 c++;
259 char c1 = a[c];
260 do {
261 c++;
262 if (c > stop) {
263 openComment = true;
264 break;
265 }
266 curChar = c1;
267 c1 = a[c];
268 } while((c1 != '/') || (curChar != '*'));
269 } else openComment = true;
270 if (c <= stop) c++; //jump over last '/'
271 break;
272 default:
273 tokType = tokSeparator;
274 }
275 break;
276 case '`':
277 tokType = tokPreproc;
278 do {
279 c++;
280 if (c > stop) break;
281 curChar = a[c];
282 } while(isAlpha(curChar) || isDigit(curChar)
283 || (curChar == '_'));
284 break;
285 case '\"':
286 tokType = tokString;
287 do {
288 c++;
289 if (c > stop) break;
290 curChar = a[c];
291 } while (curChar != '\"');
292 if (c <= stop) c++;
293 break;
294 case '$':
295 tokType = tokSysTask;
296 do {
297 c++;
298 if (c > stop) break;
299 curChar = a[c];
300 } while(isAlpha(curChar) || isDigit(curChar)
301 || (curChar == '_'));
302 break;
303 default:
304 if (isKeywordConstituent(curChar))
305 matchKeyword();
306 else {
307 tokType = tokStuff;
308 c++;
309 }
310 }
311 /*System.out.println("token: [" + (new String(a, lastC, c-lastC )) +
312 "] lastC: " + lastC + " c: " + c + " type: " + tokType);*/
313 tokLen = c - lastC;
314 return true;
315 }
316
317 void debug(String s) {
318 System.out.println(s);
319 }
320
321 /**
322 * Checks whether there is a kwyword starting at tha current
323 * point or not and sets the tokType accordingly. The c pointer
324 * is advanced to the first unmatched character.
325 */
326 void matchKeyword() {
327
328 char curChar = a[c];
329 int m = 0;
330 int charIndex = curChar - 'a';
331 int matches = keysLengths[charIndex], matches1;
332 char[][] tmp;
333
334 tmp = keyBuffer1;
335 keyBuffer1 = keys[charIndex];
336 //debug("keymatch for [" + new String(a, c, stop - c + 1) + "]");
337 tokType = tokKeyword;
338
339 matchloop:
340 while(isKeywordConstituent(curChar)) {
341 matches1 = 0;
342 for(int i = 0, j = 0; i < matches; i++) {
343 if (m == keyBuffer1[i].length) continue;
344 if (curChar == keyBuffer1[i][m]) { //match
345 matches1++;
346 keyBuffer2[j++] = keyBuffer1[i];
347 //debug("matched: [" + new String(keyBuffer2[j-1]) + "]");
348 }
349 }
350 matches = matches1;
351 //rotate buffers:
352 keyBuffer1 = keyBuffer2;
353 keyBuffer2 = tmp;
354 tmp = keyBuffer1;
355 c++;
356 m++;
357 if (matches <= 1) break matchloop; //one or no match found
358 if (c > stop) //nothing uniquely found till the end of the line
359 break;
360 curChar = a[c];
361 }
362
363 if (matches == 1) {
364 //check the remaining characters :
365 int l = keyBuffer1[0].length;
366 while(m < l) {
367 if (c > stop) {
368 tokType = tokStuff;
369 return;
370 }
371 curChar = a[c];
372 if (curChar != keyBuffer1[0][m]) {
373 while(isAlpha1(curChar)) { //eat the rest
374 c++;
375 if (c > stop) break;
376 curChar = a[c];
377 }
378 tokType = tokStuff;
379 return;
380 }
381 m++;
382 c++;
383 }
384 } else {
385 if (matches > 1) {
386 //debug("m: " + m);
387 for (int i = 0; i < matches ; i++){
388 //debug("matching: [" + new String (keyBuffer1[i]) + "]");
389 if (keyBuffer1[i].length == m) {
390 //debug("matched keyword: [" + new String (keyBuffer1[i]) + "]");
391 tokType = tokKeyword;
392 return;
393 }
394 }
395 tokType = tokStuff;
396 } else {
397 while(isAlpha1(curChar)) { //eat the rest
398 c++;
399 if (c > stop) break;
400 curChar = a[c];
401 }
402 tokType = tokStuff; //0 matches
403 }
404 }
405 }
406
407 /**
408 * @return true if the multiline comment
409 * ends on this line
410 */
411 boolean scanCommentEnd() {
412 char curChar1 = 0, curChar2;
413 do {
414 curChar2 = a[c++];
415 if ((curChar1 == '*') && (curChar2 == '/')) {
416 tokLen = c - start;
417 return true;
418 } else
419 curChar1 = curChar2;
420 } while (c <= stop);
421 tokLen = c - start;
422 return false;
423 }
424
425 /**
426 * We could use isAlpha, but as u see from the keyword table,
427 * there appear only lower case words an tha characters '0' ad '1', so we
428 * can shrink the number of tests.
429 */
430 static final boolean isKeywordConstituent(char c) {
431 return ((c >= 'a') && (c <= 'z')) || (c == '0') || (c == '1');
432 }
433
434 static final boolean isAlpha(char c) {
435 return ((c >= 'a') && (c <= 'z')) ||
436 ((c >= 'A') && (c <= 'Z')) || (c == '_');
437 }
438
439 static final boolean isAlpha1(char c) {
440 return ((c >= 'a') && (c <= 'z')) ||
441 ((c >= '0') && (c <= '9')) ||
442 ((c >= 'A') && (c <= 'Z')) || (c == '_');
443 }
444
445 static final boolean isDigit(char c) {
446 return (('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F'))
447 || (('a' <= c) && (c <= 'f')) || (c == '_') || (c == 'x') ||
448 (c == 'X') || (c == 'z') || (c == 'Z') || (c == '?');
449 }
450
451 public static void main (String args[]) {
452 try {
453 UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
454 }
455 catch ( Exception e ) {
456 System.out.println ("bad: " + e);
457 e.printStackTrace();
458 System.exit(0);
459 }
460 UIManager.put(VerilogTextArea.uiClassID, "ide.VerilogTextUI");
461
462 JFrame f = new JFrame();
463 VerilogTextArea vt = new VerilogTextArea();
464 f.setSize(new Dimension(100,100));
465 f.getContentPane().add(vt);
466 f.setVisible(true);
467 }
468 }
469
470
471