KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > VerilogFormatter


1 /*
2  * VerilogFormatter.java
3  *
4  * Copyright (C) 2002 Peter Graves
5  * $Id: VerilogFormatter.java,v 1.1.1.1 2002/09/24 16:08:14 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import java.util.HashSet JavaDoc;
25
26 public final class VerilogFormatter extends Formatter implements Constants
27 {
28     private static final int VERILOG_FORMAT_TEXT = 0;
29     private static final int VERILOG_FORMAT_COMMENT = 1;
30     private static final int VERILOG_FORMAT_STRING = 2;
31     private static final int VERILOG_FORMAT_IDENTIFIER = 3;
32     private static final int VERILOG_FORMAT_KEYWORD = 4;
33     private static final int VERILOG_FORMAT_COMPILER_DIRECTIVE = 5;
34     private static final int VERILOG_FORMAT_FUNCTION = 6;
35     private static final int VERILOG_FORMAT_OPERATOR = 7;
36     private static final int VERILOG_FORMAT_NUMBER = 8;
37
38     private static final VerilogMode mode = VerilogMode.getMode();
39
40     public VerilogFormatter(Buffer buffer)
41     {
42         this.buffer = buffer;
43     }
44
45     private int tokenBegin = 0;
46
47     private void endToken(String JavaDoc text, int tokenEnd, int state)
48     {
49         if (tokenEnd - tokenBegin > 0) {
50             int format = VERILOG_FORMAT_TEXT;
51             switch (state) {
52                 case STATE_NEUTRAL:
53                     format = VERILOG_FORMAT_TEXT;
54                     break;
55                 case STATE_QUOTE:
56                     format = VERILOG_FORMAT_STRING;
57                     break;
58                 case STATE_IDENTIFIER:
59                     format = VERILOG_FORMAT_IDENTIFIER;
60                     break;
61                 case STATE_COMMENT:
62                     format = VERILOG_FORMAT_COMMENT;
63                     break;
64                 case STATE_OPERATOR:
65                     format = VERILOG_FORMAT_OPERATOR;
66                     break;
67                 case STATE_NUMBER:
68                     format = VERILOG_FORMAT_NUMBER;
69                     break;
70             }
71             addSegment(text, tokenBegin, tokenEnd, format);
72             tokenBegin = tokenEnd;
73         }
74     }
75
76     private void parseLine(Line line)
77     {
78         if (line == null) {
79             addSegment("", VERILOG_FORMAT_TEXT);
80             return;
81         }
82         String JavaDoc text;
83         if (Editor.tabsAreVisible())
84             text = Utilities.makeTabsVisible(line.getText(), buffer.getTabWidth());
85         else
86             text = Utilities.detab(line.getText(), buffer.getTabWidth());
87         tokenBegin = 0;
88         int state = line.flags();
89         int i = 0;
90         final int limit = text.length();
91         // Skip whitespace at start of line.
92
while (i < limit) {
93             if (Character.isWhitespace(text.charAt(i))) {
94                 ++i;
95             } else {
96                 endToken(text, i, state);
97                 break;
98             }
99         }
100         while (i < limit) {
101             char c = text.charAt(i);
102             if (state == STATE_COMMENT) {
103                 if (i < limit-1 && c == '*' && text.charAt(i+1) == '/') {
104                     endToken(text, i + 2, state);
105                     state = STATE_NEUTRAL;
106                     i += 2;
107                 } else
108                     ++i;
109                 continue;
110             }
111             if (state == STATE_QUOTE) {
112                 if (c == '"') {
113                     endToken(text, i+1, state);
114                     state = STATE_NEUTRAL;
115                 } else if (c == '\\' && i < limit-1) {
116                     // Escape char.
117
++i;
118                 }
119                 ++i;
120                 continue;
121             }
122             // Reaching here, we're not in a comment or a quoted string.
123
if (c == '"') {
124                 endToken(text, i, state);
125                 state = STATE_QUOTE;
126                 ++i;
127                 continue;
128             }
129             if (c == '/') {
130                 if (i < limit-1) {
131                     if (text.charAt(i+1) == '*') {
132                         endToken(text, i, state);
133                         state = STATE_COMMENT;
134                         i += 2;
135                     } else if (text.charAt(i+1) == '/') {
136                         endToken(text, i, state);
137                         endToken(text, limit, STATE_COMMENT);
138                         return;
139                     } else
140                         ++i;
141                 } else
142                     ++i;
143                 continue;
144             }
145             if (isOperatorChar(c)) {
146                 if (state != STATE_OPERATOR) {
147                     endToken(text, i, state);
148                     // Check for keyword.
149
final LineSegment segment = getLastSegment();
150                     if (segment != null) {
151                         final String JavaDoc segmentText = segment.getText();
152                         if (isKeyword(segmentText))
153                             segment.setFormat(VERILOG_FORMAT_KEYWORD);
154                         else if (isCompilerDirective(segmentText))
155                             segment.setFormat(VERILOG_FORMAT_COMPILER_DIRECTIVE);
156                     }
157                     state = STATE_OPERATOR;
158                 }
159                 ++i;
160                 continue;
161             }
162             if (state == STATE_OPERATOR) {
163                 if (c == '\'') {
164                     if (i < limit-1) {
165                         c = text.charAt(i+1);
166                         if ("bBoOdDhH".indexOf(c) >= 0) {
167                             endToken(text, i, state);
168                             state = STATE_NUMBER;
169                             i += 2;
170                             continue;
171                         }
172                     }
173                 } else if (mode.isIdentifierStart(c)) {
174                     endToken(text, i, state);
175                     state = STATE_IDENTIFIER;
176                 } else if (Character.isDigit(c)) {
177                     endToken(text, i, state);
178                     state = STATE_NUMBER;
179                 } else {
180                     endToken(text, i, state);
181                     state = STATE_NEUTRAL;
182                 }
183                 ++i;
184                 continue;
185             }
186             if (state == STATE_IDENTIFIER) {
187                 if (!mode.isIdentifierPart(c)) {
188                     endToken(text, i, state);
189                     // Check for keyword or function.
190
final LineSegment segment = getLastSegment();
191                     if (segment != null) {
192                         final String JavaDoc segmentText = segment.getText();
193                         if (isKeyword(segmentText)) {
194                             segment.setFormat(VERILOG_FORMAT_KEYWORD);
195                         } else if (isCompilerDirective(segmentText)) {
196                             segment.setFormat(VERILOG_FORMAT_COMPILER_DIRECTIVE);
197                         } else if (c == '(') {
198                             segment.setFormat(VERILOG_FORMAT_FUNCTION);
199                         } else if (Character.isWhitespace(c)) {
200                             // Look ahead to see if next non-whitespace char is '('.
201
int j = i + 1;
202                             while (j < limit && Character.isWhitespace(c = text.charAt(j)))
203                                 ++j;
204                             if (c == '(')
205                                 segment.setFormat(VERILOG_FORMAT_FUNCTION);
206                         }
207                     }
208                     state = STATE_NEUTRAL;
209                 }
210                 ++i;
211                 continue;
212             }
213             if (state == STATE_NUMBER) {
214                 if (Character.isDigit(c))
215                     ;
216                 else if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
217                     ; // Hex digits are OK.
218
else if ("xXzZ?_".indexOf(c) >= 0)
219                     ; // Other legal values.
220
else if (c == '\'') {
221                     if (i < limit-1) {
222                         c = text.charAt(i+1);
223                         if ("bBoOdDhH".indexOf(c) >= 0) {
224                             i += 2;
225                             continue;
226                         }
227                     }
228                 } else {
229                     endToken(text, i, state);
230                     if (mode.isIdentifierStart(c))
231                         state = STATE_IDENTIFIER;
232                     else
233                         state = STATE_NEUTRAL;
234                 }
235                 ++i;
236                 continue;
237             }
238             if (state == STATE_NEUTRAL) {
239                 if (c == '\'') {
240                     if (i < limit-1) {
241                         c = text.charAt(i+1);
242                         if ("bBoOdDhH".indexOf(c) >= 0) {
243                             endToken(text, i, state);
244                             state = STATE_NUMBER;
245                             i += 2;
246                             continue;
247                         }
248                     }
249                 } else if (mode.isIdentifierStart(c)) {
250                     endToken(text, i, state);
251                     state = STATE_IDENTIFIER;
252                 } else if (Character.isDigit(c)) {
253                     endToken(text, i, state);
254                     state = STATE_NUMBER;
255                 }
256             }
257             ++i;
258         }
259         // Reached end of line.
260
endToken(text, i, state);
261         if (state == STATE_IDENTIFIER) {
262             // Last token might be a keyword.
263
final LineSegment segment = getLastSegment();
264             if (segment != null) {
265                 final String JavaDoc segmentText = segment.getText();
266                 if (isKeyword(segmentText))
267                     segment.setFormat(VERILOG_FORMAT_KEYWORD);
268                 else if (isCompilerDirective(segmentText))
269                     segment.setFormat(VERILOG_FORMAT_COMPILER_DIRECTIVE);
270             }
271         }
272     }
273
274     public LineSegmentList formatLine(Line line)
275     {
276         clearSegmentList();
277         parseLine(line);
278         return segmentList;
279     }
280
281     public boolean parseBuffer()
282     {
283         int state = STATE_NEUTRAL;
284         Line line = buffer.getFirstLine();
285         boolean changed = false;
286         while (line != null) {
287             int oldflags = line.flags();
288             // Quoted strings can't span lines.
289
if (state == STATE_QUOTE)
290                 state = STATE_NEUTRAL;
291             if (state != oldflags) {
292                 line.setFlags(state);
293                 changed = true;
294             }
295             final int limit = line.length();
296             for (int i = 0; i < limit; i++) {
297                 char c = line.charAt(i);
298                 if (c == '\\' && i < limit-1) {
299                     // Escape.
300
++i;
301                     continue;
302                 }
303                 if (state == STATE_COMMENT) {
304                     if (c == '*' && i < limit-1) {
305                         c = line.charAt(i+1);
306                         if (c == '/') {
307                             ++i;
308                             state = STATE_NEUTRAL;
309                         }
310                     }
311                     continue;
312                 }
313                 if (state == STATE_QUOTE) {
314                     if (c == '"')
315                         state = STATE_NEUTRAL;
316                     continue;
317                 }
318                 // Not in comment or quoted string.
319
if (c == '/' && i < limit-1) {
320                     c = line.charAt(++i);
321                     if (c == '/') {
322                         // Single-line comment beginning.
323
// Ignore rest of line.
324
break;
325                     } else if (c == '*')
326                         state = STATE_COMMENT;
327                 } else if (c == '"')
328                     state = STATE_QUOTE;
329             }
330             line = line.next();
331         }
332         buffer.setNeedsParsing(false);
333         return changed;
334     }
335
336     private static final boolean isOperatorChar(char c)
337     {
338         return "!&|<>=+/*-".indexOf(c) >= 0;
339     }
340
341     public FormatTable getFormatTable()
342     {
343         if (formatTable == null) {
344             formatTable = new FormatTable("VerilogMode");
345             formatTable.addEntryFromPrefs(VERILOG_FORMAT_TEXT, "text");
346             formatTable.addEntryFromPrefs(VERILOG_FORMAT_COMMENT, "comment");
347             formatTable.addEntryFromPrefs(VERILOG_FORMAT_STRING, "string");
348             formatTable.addEntryFromPrefs(VERILOG_FORMAT_IDENTIFIER, "identifier", "text");
349             formatTable.addEntryFromPrefs(VERILOG_FORMAT_KEYWORD, "keyword");
350             formatTable.addEntryFromPrefs(VERILOG_FORMAT_COMPILER_DIRECTIVE, "preprocessor");
351             formatTable.addEntryFromPrefs(VERILOG_FORMAT_FUNCTION, "function");
352             formatTable.addEntryFromPrefs(VERILOG_FORMAT_OPERATOR, "operator");
353             formatTable.addEntryFromPrefs(VERILOG_FORMAT_NUMBER, "number");
354         }
355         return formatTable;
356     }
357
358     private static boolean isCompilerDirective(String JavaDoc s)
359     {
360         if (s.length() > 0 && s.charAt(0) == '`')
361             return getCompilerDirectives().contains(s);
362         return false;
363     }
364
365     private static HashSet JavaDoc compilerDirectiveHashSet;
366
367     private static HashSet JavaDoc getCompilerDirectives()
368     {
369         if (compilerDirectiveHashSet == null) {
370             String JavaDoc[] array = compilerDirectives;
371             int count = array.length;
372             compilerDirectiveHashSet = new HashSet JavaDoc(Math.max(2 * count, 11));
373             for (int i = count - 1; i >= 0; i--)
374                 compilerDirectiveHashSet.add(array[i]);
375         }
376         return compilerDirectiveHashSet;
377     }
378
379     private static String JavaDoc[] compilerDirectives = {
380         "`autoexpand_vectornets",
381         "`celldefine",
382         "`default_nettype",
383         "`define",
384         "`delay_mode_distributed",
385         "`delay_mode_path",
386         "`delay_mode_unit",
387         "`delay_mode_zero",
388         "`else",
389         "`endcelldefine",
390         "`endif",
391         "`endprotect",
392         "`endprotected",
393         "`expand_vectornets",
394         "`ifdef",
395         "`ifndef",
396         "`include",
397         "`noexpand_vectornets",
398         "`noremove_gatename",
399         "`noremove_netname",
400         "`nounconnected_drive",
401         "`protect",
402         "`protected",
403         "`remove_gatename",
404         "`remove_netname",
405         "`reset_all",
406         "`signed",
407         "`timescale",
408         "`unconnected_drive",
409         "`undef",
410         "`unsigned",
411         "`uselib"
412     };
413 }
414
Popular Tags